Skip to content

Commit

Permalink
added key size parameter (k) to argon2i/argon2id algorithms
Browse files Browse the repository at this point in the history
  • Loading branch information
phifty committed Mar 2, 2020
1 parent a0cb575 commit db01ecb
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 90 deletions.
16 changes: 8 additions & 8 deletions argon2i.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,13 @@ const (
argon2iDefaultMemory = 32 * 1024
argon2iDefaultTime = 4
argon2iDefaultThreads = 4
argon2iKeySize = 32
argon2iDefaultKeySize = 32
argon2iDefaultSaltSize = 16
argon2iMaxSaltSize = 16 // 0xFFFFFFFF
)

// Argon2iSettings returns argon2i settings with the provided parameter.
func Argon2iSettings(m, t, p int, salts ...string) (string, error) {
settings := fmt.Sprintf("%sv=19$m=%d,t=%d,p=%d", Argon2iPrefix, m, t, p)
func Argon2iSettings(m, t, p, k int, salts ...string) (string, error) {
settings := fmt.Sprintf("%sv=19$m=%d,t=%d,p=%d,k=%d", Argon2iPrefix, m, t, p, k)
salt := strings.Join(salts, "")
if salt == "" {
b := make([]byte, argon2iDefaultSaltSize)
Expand All @@ -68,14 +67,12 @@ func argon2iAlgorithm(password, settings string) (string, error) {
return "", fmt.Errorf("base64 decode [%s]: %v", salt, err)
}
}
if len(saltBytes) > argon2iMaxSaltSize {
saltBytes = saltBytes[:argon2iMaxSaltSize]
}
memory := parameter.GetInt("m", argon2iDefaultMemory)
time := parameter.GetInt("t", argon2iDefaultTime)
threads := parameter.GetInt("p", argon2iDefaultThreads)
keySize := parameter.GetInt("k", argon2iDefaultKeySize)

hash := argon2.Key(passwordBytes, saltBytes, uint32(time), uint32(memory), uint8(threads), argon2iKeySize)
hash := argon2.Key(passwordBytes, saltBytes, uint32(time), uint32(memory), uint8(threads), uint32(keySize))

p := []string{}
if memory != argon2iDefaultMemory {
Expand All @@ -87,6 +84,9 @@ func argon2iAlgorithm(password, settings string) (string, error) {
if threads != argon2iDefaultThreads {
p = append(p, "p="+strconv.Itoa(threads))
}
if keySize != argon2iDefaultKeySize {
p = append(p, "k="+strconv.Itoa(keySize))
}

buf := bytes.Buffer{}
buf.Write([]byte(Argon2iPrefix))
Expand Down
28 changes: 18 additions & 10 deletions argon2i_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,22 +33,30 @@ func TestArgon2i(t *testing.T) {
}
}

t.Run(testFn("generate salt", "$argon2i$v=19$m=65536,t=2,p=4$", "$argon2i$v=19$m=65536,t=2$", nil))
t.Run(testFn("password", "$argon2i$v=19$m=65536,t=2,p=4$c29tZXNhbHQ", "$argon2i$v=19$m=65536,t=2$c29tZXNhbHQ$IMit9qkFULCMA/ViizL57cnTLOa5DiVM9eMwpAvPwr4", nil))
t.Run(testFn("another password", "$argon2i$v=19$m=65536,t=2,p=4$YW5vdGhlcnNhbHQ", "$argon2i$v=19$m=65536,t=2$YW5vdGhlcnNhbHQ$BCRltpeTFX0QYrELiOXWGZniID9nOUsBPy8Bu0SE7bM", nil))
t.Run(testFn("password", "$argon2i$v=19$m=65536,t=2,p=1$bG9uZ3NhbHRsb25nc2FsdGxvbmc", "$argon2i$v=19$m=65536,t=2,p=1$bG9uZ3NhbHRsb25nc2FsdA$8BZnxCqANQ3mGYITjgezarZ/b5vivfVRVy3cWwwXGHI", nil))
t.Run(testFn("ignore-hash-in-settings", "$argon2i$v=19$m=65536,t=2$bG9uZ3NhbHRsb25nc2FsdGxvbmc$rDmQABiNkSO3bGHbBUkShgb7wIlBP8HHfq6nDH+Sqss", "$argon2i$v=19$m=65536,t=2$bG9uZ3NhbHRsb25nc2FsdA$Cfa1JVLA/wGtR7UeWI+Q+ZOfMmyPchePKy2h+kjryG8", nil))
t.Run(testFn("password", "$argon2i$v=19$m=65536,t=3,p=1$bG9uZ3NhbHRsb25nc2FsdA", "$argon2i$v=19$m=65536,t=3,p=1$bG9uZ3NhbHRsb25nc2FsdA$K2rLfVoQG17LuUn26otasTX1WBXjr6hi5NZXKKxmYrs", nil))
t.Run(testFn("generate salt", "$argon2i$v=19$m=65536,t=2,p=4$",
"$argon2i$v=19$m=65536,t=2$", nil))
t.Run(testFn("password", "$argon2i$v=19$m=65536,t=2,p=4$c29tZXNhbHQ",
"$argon2i$v=19$m=65536,t=2$c29tZXNhbHQ$IMit9qkFULCMA/ViizL57cnTLOa5DiVM9eMwpAvPwr4", nil))
t.Run(testFn("another password", "$argon2i$v=19$m=65536,t=2,p=4$YW5vdGhlcnNhbHQ",
"$argon2i$v=19$m=65536,t=2$YW5vdGhlcnNhbHQ$BCRltpeTFX0QYrELiOXWGZniID9nOUsBPy8Bu0SE7bM", nil))
t.Run(testFn("password", "$argon2i$v=19$m=65536,t=2,p=1$bG9uZ3NhbHRsb25nc2FsdGxvbmc",
"$argon2i$v=19$m=65536,t=2,p=1$bG9uZ3NhbHRsb25nc2FsdGxvbmc$N2zfK+oCIRMbTX04zZS4X2uLKX3SK0KkNxyCw/NURrU", nil))
t.Run(testFn("ignore-hash-in-settings", "$argon2i$v=19$m=65536,t=2$bG9uZ3NhbHRsb25nc2FsdGxvbmc$rDmQABiNkSO3bGHbBUkShgb7wIlBP8HHfq6nDH+Sqss",
"$argon2i$v=19$m=65536,t=2$bG9uZ3NhbHRsb25nc2FsdGxvbmc$xY9IRFH+zQduVUYoZfSoT6tylET3/AUIOMS3rFF0x0o", nil))
t.Run(testFn("password", "$argon2i$v=19$m=65536,t=3,p=1$bG9uZ3NhbHRsb25nc2FsdA",
"$argon2i$v=19$m=65536,t=3,p=1$bG9uZ3NhbHRsb25nc2FsdA$K2rLfVoQG17LuUn26otasTX1WBXjr6hi5NZXKKxmYrs", nil))
t.Run(testFn("password", "$argon2i$v=19$m=65536,t=3,p=1,k=64$bG9uZ3NhbHRsb25nc2FsdA",
"$argon2i$v=19$m=65536,t=3,p=1,k=64$bG9uZ3NhbHRsb25nc2FsdA$7DnJ2B7gxZDMEk+HVNDpIuTtOxDkwDaA0IhvuiBn9oeBTXpqBPxP9iro2cPiFongTwoFHHpVrqiL8JvMXrb63Q", nil))
}

func TestArgon2iSettings(t *testing.T) {
testFn := func(m, t, p int, expectSettingsPrefix string) (string, func(*testing.T)) {
return fmt.Sprintf("m=%d,t=%d,p=%d", m, t, p), func(tt *testing.T) {
settings, err := crypt.Argon2iSettings(m, t, p)
testFn := func(m, t, p, k int, expectSettingsPrefix string) (string, func(*testing.T)) {
return fmt.Sprintf("m=%d,t=%d,p=%d,k=%d", m, t, p, k), func(tt *testing.T) {
settings, err := crypt.Argon2iSettings(m, t, p, k)
require.NoError(tt, err)
assert.True(tt, strings.HasPrefix(settings, expectSettingsPrefix))
}
}

t.Run(testFn(65536, 2, 4, "$argon2i$v=19$m=65536,t=2,p=4"))
t.Run(testFn(65536, 2, 4, 64, "$argon2i$v=19$m=65536,t=2,p=4,k=64"))
}
33 changes: 24 additions & 9 deletions argon2id.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,13 @@ const (
argon2idDefaultMemory = 32 * 1024
argon2idDefaultTime = 1
argon2idDefaultThreads = 4
argon2idKeySize = 32
argon2idDefaultKeySize = 32
argon2idDefaultSaltSize = 16
)

// Argon2idSettings returns argon2id settings with the provided parameter.
func Argon2idSettings(m, t, p int, salts ...string) (string, error) {
settings := fmt.Sprintf("%sv=19$m=%d,t=%d,p=%d", Argon2idPrefix, m, t, p)
func Argon2idSettings(m, t, p, k int, salts ...string) (string, error) {
settings := fmt.Sprintf("%sv=19$m=%d,t=%d,p=%d,k=%d", Argon2idPrefix, m, t, p, k)
salt := strings.Join(salts, "")
if salt == "" {
b := make([]byte, argon2idDefaultSaltSize)
Expand Down Expand Up @@ -74,16 +74,31 @@ func argon2idAlgorithm(password, settings string) (string, error) {
memory := parameter.GetInt("m", argon2idDefaultMemory)
time := parameter.GetInt("t", argon2idDefaultTime)
threads := parameter.GetInt("p", argon2idDefaultThreads)
keySize := parameter.GetInt("k", argon2idDefaultKeySize)

hash := argon2.IDKey(passwordBytes, saltBytes, uint32(time), uint32(memory), uint8(threads), argon2idKeySize)
hash := argon2.IDKey(passwordBytes, saltBytes, uint32(time), uint32(memory), uint8(threads), uint32(keySize))

p := []string{}
if memory != argon2iDefaultMemory {
p = append(p, "m="+strconv.Itoa(memory))
}
if time != argon2iDefaultTime {
p = append(p, "t="+strconv.Itoa(time))
}
if threads != argon2iDefaultThreads {
p = append(p, "p="+strconv.Itoa(threads))
}
if keySize != argon2iDefaultKeySize {
p = append(p, "k="+strconv.Itoa(keySize))
}

buf := bytes.Buffer{}
buf.Write([]byte(Argon2idPrefix))
buf.Write([]byte(Argon2iPrefix))
buf.WriteString("v=19$")
buf.WriteString("m="+strconv.Itoa(memory)+",")
buf.WriteString("t="+strconv.Itoa(time)+",")
buf.WriteString("p="+strconv.Itoa(threads))
buf.WriteString("$")
if len(p) > 0 {
buf.WriteString(strings.Join(p, ","))
buf.WriteString("$")
}
buf.WriteString(Base64Encoding.EncodeToString(saltBytes))
buf.WriteString("$")
buf.WriteString(Base64Encoding.EncodeToString(hash))
Expand Down
90 changes: 27 additions & 63 deletions argon2id_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,74 +25,38 @@ import (
)

func TestArgon2id(t *testing.T) {
tcs := []struct {
password string
settings string
expectedResult string
expectedErr error
}{
{
"generate salt",
"$argon2id$v=19$m=65536,t=2,p=4$",
"$argon2id$v=19$m=65536,t=2,p=4$",
nil,
},
{
"password", // salt = somesalt
"$argon2id$v=19$m=65536,t=2,p=4$c29tZXNhbHQ",
"$argon2id$v=19$m=65536,t=2,p=4$c29tZXNhbHQ$GpZ3sK/oH9p7VIiV56G/64Zo/8GaUw434IimaPqxwCo",
nil,
},
{
"another password", // salt = anothersalt
"$argon2id$v=19$m=65536,t=2,p=4$YW5vdGhlcnNhbHQ",
"$argon2id$v=19$m=65536,t=2,p=4$YW5vdGhlcnNhbHQ$ZU9gSnQfqeEZG2Wu6Wq9pek2UAttI/N8NLCEecVBRZc",
nil,
},
{
"password", // salt = longsaltlongsaltlong
"$argon2id$v=19$m=65536,t=2,p=1$bG9uZ3NhbHRsb25nc2FsdGxvbmc",
"$argon2id$v=19$m=65536,t=2,p=1$bG9uZ3NhbHRsb25nc2FsdGxvbmc$y3Tz6SCUIw7occvkgsUYx0hwaePXLus7rxUzsOghhnE",
nil,
},
{
"ignore-hash-in-settings", // salt = longsaltlongsaltlong
"$argon2id$v=19$m=65536,t=2,p=1$bG9uZ3NhbHRsb25nc2FsdGxvbmc$y3Tz6SCUIw7occvkgsUYx0hwaePXLus7rxUzsOghhnE",
"$argon2id$v=19$m=65536,t=2,p=1$bG9uZ3NhbHRsb25nc2FsdGxvbmc$sToxuMqIBNNRYEPy2Gh690R7qa7mkhJ627ciTZdyQSA",
nil,
},
{
"password", // salt = longsaltlongsalt
"$argon2id$v=19$m=65536,t=3,p=1$bG9uZ3NhbHRsb25nc2FsdA",
"$argon2id$v=19$m=65536,t=3,p=1$bG9uZ3NhbHRsb25nc2FsdA$SHogC8dbNGlyrOIJTrZ4f0/r/ZmTglvCx4u5GUzw6EM",
nil,
},
testFn := func(password, settings, expectResult string, expectErr error) (string, func(*testing.T)) {
return settings, func(t *testing.T) {
result, err := crypt.Crypt(password, settings)
require.Equal(t, expectErr, err)
assert.True(t, strings.HasPrefix(result, expectResult), "expected prefix %q, got %q", expectResult, result)
}
}

for _, tc := range tcs {
t.Run(tc.settings, func(t *testing.T) {
result, err := crypt.Crypt(tc.password, tc.settings)
require.Equal(t, tc.expectedErr, err)
assert.True(t, strings.HasPrefix(result, tc.expectedResult), "expected prefix %q, got %q", tc.expectedResult, result)
})
}
t.Run(testFn("generate salt", "$argon2id$v=19$m=65536,t=2,p=4$",
"$argon2i$v=19$m=65536,t=2$", nil))
t.Run(testFn("password", "$argon2id$v=19$m=65536,t=2,p=4$c29tZXNhbHQ",
"$argon2i$v=19$m=65536,t=2$c29tZXNhbHQ$GpZ3sK/oH9p7VIiV56G/64Zo/8GaUw434IimaPqxwCo", nil))
t.Run(testFn("another password", "$argon2id$v=19$m=65536,t=2,p=4$YW5vdGhlcnNhbHQ",
"$argon2i$v=19$m=65536,t=2$YW5vdGhlcnNhbHQ$ZU9gSnQfqeEZG2Wu6Wq9pek2UAttI/N8NLCEecVBRZc", nil))
t.Run(testFn("password", "$argon2id$v=19$m=65536,t=2,p=1$bG9uZ3NhbHRsb25nc2FsdGxvbmc",
"$argon2i$v=19$m=65536,t=2,p=1$bG9uZ3NhbHRsb25nc2FsdGxvbmc$y3Tz6SCUIw7occvkgsUYx0hwaePXLus7rxUzsOghhnE", nil))
t.Run(testFn("ignore-hash-in-settings", "$argon2id$v=19$m=65536,t=2,p=1$bG9uZ3NhbHRsb25nc2FsdGxvbmc$y3Tz6SCUIw7occvkgsUYx0hwaePXLus7rxUzsOghhnE",
"$argon2i$v=19$m=65536,t=2,p=1$bG9uZ3NhbHRsb25nc2FsdGxvbmc$sToxuMqIBNNRYEPy2Gh690R7qa7mkhJ627ciTZdyQSA", nil))
t.Run(testFn("password", "$argon2id$v=19$m=65536,t=3,p=1$bG9uZ3NhbHRsb25nc2FsdA",
"$argon2i$v=19$m=65536,t=3,p=1$bG9uZ3NhbHRsb25nc2FsdA$SHogC8dbNGlyrOIJTrZ4f0/r/ZmTglvCx4u5GUzw6EM", nil))
t.Run(testFn("password", "$argon2id$v=19$m=65536,t=3,p=1,k=64$bG9uZ3NhbHRsb25nc2FsdA",
"$argon2i$v=19$m=65536,t=3,p=1,k=64$bG9uZ3NhbHRsb25nc2FsdA$gaB/QbA34/AJkE/QbuEByjVhIF3sCvX+LHo8L3otGHhWh5q++cFMfidqGQd6qoGu3Qcm7LEPl8dQWMzyblYqYg", nil))
}

func TestArgon2idSettings(t *testing.T) {
tcs := []struct {
m int
t int
p int
expectedSettingsPrefix string
}{
{65536, 2, 4, "$argon2id$v=19$m=65536,t=2,p=4"},
testFn := func(m, t, p, k int, expectSettingsPrefix string) (string, func(*testing.T)) {
return fmt.Sprintf("m=%d,t=%d,p=%d,k=%d", m, t, p, k), func(tt *testing.T) {
settings, err := crypt.Argon2idSettings(m, t, p, k)
require.NoError(tt, err)
assert.True(tt, strings.HasPrefix(settings, expectSettingsPrefix))
}
}

for _, tc := range tcs {
t.Run(fmt.Sprintf("m=%d,t=%d,p=%d", tc.m, tc.t, tc.p), func(t *testing.T) {
settings, err := crypt.Argon2idSettings(tc.m, tc.t, tc.p)
require.NoError(t, err)
assert.True(t, strings.HasPrefix(settings, tc.expectedSettingsPrefix))
})
}
t.Run(testFn(65536, 2, 4, 64, "$argon2id$v=19$m=65536,t=2,p=4,k=64"))
}
2 changes: 2 additions & 0 deletions settings_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ func TestSettings(t *testing.T) {
t.Run(testFn("$2a$08$ybX1Hjkb5N.8WEcYtBuB7u", "$2a$08$ybX1Hjkb5N.8WEcYtBuB7u"))
t.Run(testFn("$2a$08$ybX1Hjkb5N.8WEcYtBuB7u$CMA/ViizL57cnTLOa5DiVM9e", "$2a$08$ybX1Hjkb5N.8WEcYtBuB7u"))
t.Run(testFn("$argon2i$v=19$m=65536,t=2,p=4$c29tZXNhbHQ$IMit9qkFULCMA/ViizL57cnTLOa5DiVM9eMwpAvPwr4", "$argon2i$v=19$m=65536,t=2,p=4$c29tZXNhbHQ"))
t.Run(testFn("$argon2i$v=19$m=65536,t=2,p=4,k=64$c29tZXNhbHQ$IMit9qkFULCMA/ViizL57cnTLOa5DiVM9eMwpAvPwr4", "$argon2i$v=19$m=65536,t=2,p=4,k=64$c29tZXNhbHQ"))
}

func TestDecodeSettings(t *testing.T) {
Expand All @@ -62,4 +63,5 @@ func TestDecodeSettings(t *testing.T) {
t.Run(testFn("$1$rounds=300$salt$hash$", "1", crypt.Parameter{"rounds": "300"}, "salt", "hash", nil))
t.Run(testFn("$2a$08$ybX1Hjkb5N.8WEcYtBuB7u", "2a", crypt.Parameter{"cost": "8"}, "ybX1Hjkb5N.8WEcYtBuB7u", "", nil))
t.Run(testFn("$argon2i$v=19$m=65536,t=2,p=4$c29tZXNhbHQ$IMit9qkFULCMA/ViizL57cnTLOa5DiVM9eMwpAvPwr4", "argon2i", crypt.Parameter{"v": "19", "m": "65536", "t": "2", "p": "4"}, "c29tZXNhbHQ", "IMit9qkFULCMA/ViizL57cnTLOa5DiVM9eMwpAvPwr4", nil))
t.Run(testFn("$argon2i$v=19$m=65536,t=2,p=4,k=64$c29tZXNhbHQ$IMit9qkFULCMA/ViizL57cnTLOa5DiVM9eMwpAvPwr4", "argon2i", crypt.Parameter{"v": "19", "m": "65536", "t": "2", "p": "4", "k": "64"}, "c29tZXNhbHQ", "IMit9qkFULCMA/ViizL57cnTLOa5DiVM9eMwpAvPwr4", nil))
}

0 comments on commit db01ecb

Please sign in to comment.