Add Pwhash test vectors from PyNaCl and RbNaCl.
Pwhash::Algorithm renamed to Mode to be more like other libsodium bindings. Cryptobox#encrypt now returns {encrypted, nonce} identical to SecretBox.
This commit is contained in:
parent
92ac0ef6d4
commit
769e02e4c7
@ -34,7 +34,7 @@ Crystal bindings for the [libsodium API](https://libsodium.gitbook.io/doc/)
|
||||
- [x] Complete libsodium implementation including `key`, `salt`, `personal` and fully selectable output sizes.
|
||||
- [ ] [SipHash](https://libsodium.gitbook.io/doc/hashing/short-input_hashing)
|
||||
- [Password Hashing](https://libsodium.gitbook.io/doc/password_hashing)
|
||||
- [x] [Argon2](https://libsodium.gitbook.io/doc/password_hashing/the_argon2i_function) (Use for new applications)
|
||||
- [x] [x] [Argon2](https://libsodium.gitbook.io/doc/password_hashing/the_argon2i_function) (Use for new applications)
|
||||
- [ ] [Scrypt](https://libsodium.gitbook.io/doc/advanced/scrypt) (For compatibility with older applications)
|
||||
- Other
|
||||
- [x] [Key Derivation](https://libsodium.gitbook.io/doc/key_derivation)
|
||||
|
6
spec/data/box_from_seed.txt
Normal file
6
spec/data/box_from_seed.txt
Normal file
@ -0,0 +1,6 @@
|
||||
# Reference data taken from libsodium's test/default/box_seed.c
|
||||
# and test/default/box_seed.exp.
|
||||
# The seed comes from box_seed.c, the public and secret keys
|
||||
# come from box_seed.exp where they are directly concatenated.
|
||||
# Fmt: <seed> <tab> <public_key> || <secret_key>
|
||||
77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a ed7749b4d989f6957f3bfde6c56767e988e21c9f8784d91d610011cd553f9b06accd44eb8e93319c0570bc11005c0e0189d34ff02f6c17773411ad191293c98f
|
92
spec/data/modular_crypt_argon2i_hashes.json
Normal file
92
spec/data/modular_crypt_argon2i_hashes.json
Normal file
@ -0,0 +1,92 @@
|
||||
[
|
||||
{
|
||||
"passwd": "gCb0SBnpxkdLZdWe",
|
||||
"mode": "crypt",
|
||||
"dgst_len": 20,
|
||||
"iters": 4,
|
||||
"salt": "kSmmBSy5uyC4",
|
||||
"pwhash": "$argon2i$v=19$m=131072,t=4,p=1$a1NtbUJTeTV1eUM0$gNxxt8jHCHaKDUcbdP3ugX9i+BA",
|
||||
"maxmem": 131072
|
||||
},
|
||||
{
|
||||
"passwd": "mu3KbBv3",
|
||||
"mode": "crypt",
|
||||
"dgst_len": 17,
|
||||
"iters": 4,
|
||||
"salt": "kvPMDFk4yT9sZI",
|
||||
"pwhash": "$argon2i$v=19$m=32768,t=4,p=1$a3ZQTURGazR5VDlzWkk$V+L2XhLr+F/EevADgyfo+bM",
|
||||
"maxmem": 32768
|
||||
},
|
||||
{
|
||||
"passwd": "Bxrsg5L0A0",
|
||||
"mode": "crypt",
|
||||
"dgst_len": 17,
|
||||
"iters": 3,
|
||||
"salt": "Z5c5VUWXSJcSbr",
|
||||
"pwhash": "$argon2i$v=19$m=65536,t=3,p=1$WjVjNVZVV1hTSmNTYnI$BqyrFpvLJUCFaf9cQAFH1Ms",
|
||||
"maxmem": 65536
|
||||
},
|
||||
{
|
||||
"passwd": "EQmTLQ2ET",
|
||||
"mode": "crypt",
|
||||
"dgst_len": 30,
|
||||
"iters": 3,
|
||||
"salt": "8aWdz2IL",
|
||||
"pwhash": "$argon2i$v=19$m=32768,t=3,p=1$OGFXZHoySUw$U6F0Tm/c/gyjJyMi4SWjLS+8dpuiKFK0OZje6iEZ",
|
||||
"maxmem": 32768
|
||||
},
|
||||
{
|
||||
"passwd": "9wQdHVSks3tbXx",
|
||||
"mode": "crypt",
|
||||
"dgst_len": 19,
|
||||
"iters": 5,
|
||||
"salt": "HW4AgInQoU",
|
||||
"pwhash": "$argon2i$v=19$m=65536,t=5,p=1$SFc0QWdJblFvVQ$IwHIJ6VP1vIV7xrKm+mlI1nupA",
|
||||
"maxmem": 65536
|
||||
},
|
||||
{
|
||||
"passwd": "XRGHrq53wJ1LWgV",
|
||||
"mode": "crypt",
|
||||
"dgst_len": 27,
|
||||
"iters": 5,
|
||||
"salt": "Dr57DsF3",
|
||||
"pwhash": "$argon2i$v=19$m=131072,t=5,p=1$RHI1N0RzRjM$shLAeDv4NbeHN9Sce+jaoEHIjUTP6OnGOtZ1",
|
||||
"maxmem": 131072
|
||||
},
|
||||
{
|
||||
"passwd": "JVoDvUkiJgtm",
|
||||
"mode": "crypt",
|
||||
"dgst_len": 17,
|
||||
"iters": 5,
|
||||
"salt": "C5jzAUY8D",
|
||||
"pwhash": "$argon2i$v=19$m=131072,t=5,p=1$QzVqekFVWThE$SqZ2XYLggynRZgYlsWFiXGI",
|
||||
"maxmem": 131072
|
||||
},
|
||||
{
|
||||
"passwd": "eZf6zOck",
|
||||
"mode": "crypt",
|
||||
"dgst_len": 16,
|
||||
"iters": 3,
|
||||
"salt": "ID0CNHQR",
|
||||
"pwhash": "$argon2i$v=19$m=65536,t=3,p=1$SUQwQ05IUVI$ShibIsTX2z5mclt4TKyAkQ",
|
||||
"maxmem": 65536
|
||||
},
|
||||
{
|
||||
"passwd": "nPeXb5WW",
|
||||
"mode": "crypt",
|
||||
"dgst_len": 26,
|
||||
"iters": 5,
|
||||
"salt": "DibJwvJWarySIIic",
|
||||
"pwhash": "$argon2i$v=19$m=16384,t=5,p=1$RGliSnd2SldhcnlTSUlpYw$3n/DLofidmz8LPnM925hbm+4He/iKjAlvG4",
|
||||
"maxmem": 16384
|
||||
},
|
||||
{
|
||||
"passwd": "Vgv3CCRnqkgTO2co",
|
||||
"mode": "crypt",
|
||||
"dgst_len": 17,
|
||||
"iters": 5,
|
||||
"salt": "MfmTsCzom",
|
||||
"pwhash": "$argon2i$v=19$m=131072,t=5,p=1$TWZtVHNDem9t$1W2xtNO3w3BylGxOHuX/IZ0",
|
||||
"maxmem": 131072
|
||||
}
|
||||
]
|
102
spec/data/modular_crypt_argon2id_hashes.json
Normal file
102
spec/data/modular_crypt_argon2id_hashes.json
Normal file
@ -0,0 +1,102 @@
|
||||
[
|
||||
{
|
||||
"iters": 1,
|
||||
"maxmem": 131072,
|
||||
"dgst_len": 30,
|
||||
"passwd": "6GaBkxnU",
|
||||
"salt": "SIWAuVklLU",
|
||||
"construct": "argon2id",
|
||||
"pwhash": "$argon2id$v=19$m=131072,t=1,p=1$U0lXQXVWa2xMVQ$+EaGmstgtSas9elKIXLVqcybaYJIBWifLeLWkFAZ",
|
||||
"mode": "crypt"
|
||||
},
|
||||
{
|
||||
"iters": 3,
|
||||
"maxmem": 65536,
|
||||
"dgst_len": 31,
|
||||
"passwd": "JU1K5W8rzP1K",
|
||||
"salt": "9Jve1X5OQ2tp",
|
||||
"construct": "argon2id",
|
||||
"pwhash": "$argon2id$v=19$m=65536,t=3,p=1$OUp2ZTFYNU9RMnRw$7yApdAtgdaPQZWisUa58lb328fR+kgznHqQqcafaCg",
|
||||
"mode": "crypt"
|
||||
},
|
||||
{
|
||||
"iters": 2,
|
||||
"maxmem": 131072,
|
||||
"dgst_len": 20,
|
||||
"passwd": "zBqdT3A3WReQFO",
|
||||
"salt": "ahTuAAVQ6",
|
||||
"construct": "argon2id",
|
||||
"pwhash": "$argon2id$v=19$m=131072,t=2,p=1$YWhUdUFBVlE2$jLdOXTu7R5XVuLKyHoEKVojIYsM",
|
||||
"mode": "crypt"
|
||||
},
|
||||
{
|
||||
"iters": 5,
|
||||
"maxmem": 262144,
|
||||
"dgst_len": 30,
|
||||
"passwd": "FF3gKe0hL",
|
||||
"salt": "XYpBw246J",
|
||||
"construct": "argon2id",
|
||||
"pwhash": "$argon2id$v=19$m=262144,t=5,p=1$WFlwQncyNDZK$8D7TbKnOi9PMuhooK9HUJLTKdPBXD9CZ5/dE4p0r",
|
||||
"mode": "crypt"
|
||||
},
|
||||
{
|
||||
"iters": 4,
|
||||
"maxmem": 131072,
|
||||
"dgst_len": 20,
|
||||
"passwd": "tUhcdnSMH",
|
||||
"salt": "qGQAKPomg08",
|
||||
"construct": "argon2id",
|
||||
"pwhash": "$argon2id$v=19$m=131072,t=4,p=1$cUdRQUtQb21nMDg$7kj3MDpz4aOZazen9BrazcIiMQE",
|
||||
"mode": "crypt"
|
||||
},
|
||||
{
|
||||
"iters": 5,
|
||||
"maxmem": 131072,
|
||||
"dgst_len": 19,
|
||||
"passwd": "oxx700QV8RVHQA2l",
|
||||
"salt": "r8R7NqsNyb",
|
||||
"construct": "argon2id",
|
||||
"pwhash": "$argon2id$v=19$m=131072,t=5,p=1$cjhSN05xc055Yg$yHz0aPvCukbkMw1oXaKejEkG6Q",
|
||||
"mode": "crypt"
|
||||
},
|
||||
{
|
||||
"iters": 4,
|
||||
"maxmem": 262144,
|
||||
"dgst_len": 27,
|
||||
"passwd": "zTKzEfuKI4",
|
||||
"salt": "ajbUgkhOX9bxaD",
|
||||
"construct": "argon2id",
|
||||
"pwhash": "$argon2id$v=19$m=262144,t=4,p=1$YWpiVWdraE9YOWJ4YUQ$h0NTYkqWF6qEpVnLP4Bqsk7oYjG4DNyn6+q0",
|
||||
"mode": "crypt"
|
||||
},
|
||||
{
|
||||
"iters": 2,
|
||||
"maxmem": 65536,
|
||||
"dgst_len": 21,
|
||||
"passwd": "DicnLJsOvUTGBSAx",
|
||||
"salt": "djp2efSTgmrz",
|
||||
"construct": "argon2id",
|
||||
"pwhash": "$argon2id$v=19$m=65536,t=2,p=1$ZGpwMmVmU1RnbXJ6$Ar5DxZsxCAjUrGrBZPsa0vOVhjvk",
|
||||
"mode": "crypt"
|
||||
},
|
||||
{
|
||||
"iters": 1,
|
||||
"maxmem": 32768,
|
||||
"dgst_len": 30,
|
||||
"passwd": "HyURt4Ofuwivg8",
|
||||
"salt": "9tArBEgW8GU",
|
||||
"construct": "argon2id",
|
||||
"pwhash": "$argon2id$v=19$m=32768,t=1,p=1$OXRBckJFZ1c4R1U$l/6y/kKeMPSk3WQb+bM4ir3bGj5yxj+/r6Wi/D8A",
|
||||
"mode": "crypt"
|
||||
},
|
||||
{
|
||||
"iters": 2,
|
||||
"maxmem": 65536,
|
||||
"dgst_len": 31,
|
||||
"passwd": "ikt3keViPK0S",
|
||||
"salt": "4Wh4LpHrUy",
|
||||
"construct": "argon2id",
|
||||
"pwhash": "$argon2id$v=19$m=65536,t=2,p=1$NFdoNExwSHJVeQ$MrbDWj1XHpotj2+n6vs5KF+2E0oUGt9Ge/mo0IJ0tA",
|
||||
"mode": "crypt"
|
||||
}
|
||||
]
|
92
spec/data/raw_argon2i_hashes.json
Normal file
92
spec/data/raw_argon2i_hashes.json
Normal file
@ -0,0 +1,92 @@
|
||||
[
|
||||
{
|
||||
"passwd": "5qflFfSWpOvQ",
|
||||
"mode": "raw",
|
||||
"dgst_len": 20,
|
||||
"iters": 5,
|
||||
"salt": "QIA9x2qmhRVmdRCU",
|
||||
"pwhash": "3eb202f3e4b0e2c078031f724103ea526fe2a065",
|
||||
"maxmem": 16384
|
||||
},
|
||||
{
|
||||
"passwd": "pf1SMoxVb54r",
|
||||
"mode": "raw",
|
||||
"dgst_len": 26,
|
||||
"iters": 4,
|
||||
"salt": "NPBA55CsQp9wsWKy",
|
||||
"pwhash": "b7173ea20f6eb6946d3044542fc75ef5dda0d9c94acf86d834ca",
|
||||
"maxmem": 131072
|
||||
},
|
||||
{
|
||||
"passwd": "bg9Laxjhrk8MUyhM",
|
||||
"mode": "raw",
|
||||
"dgst_len": 18,
|
||||
"iters": 4,
|
||||
"salt": "exKErRXWGdCDRSop",
|
||||
"pwhash": "9c7957beb49f1c5e868d6a04f34d1da821f6",
|
||||
"maxmem": 65536
|
||||
},
|
||||
{
|
||||
"passwd": "n95X5vWQncMXlP",
|
||||
"mode": "raw",
|
||||
"dgst_len": 17,
|
||||
"iters": 3,
|
||||
"salt": "gxSD9VHiGF0oou1k",
|
||||
"pwhash": "b605e0557e9f57455f246e474e93648595",
|
||||
"maxmem": 32768
|
||||
},
|
||||
{
|
||||
"passwd": "5G8iiXVYwI",
|
||||
"mode": "raw",
|
||||
"dgst_len": 29,
|
||||
"iters": 4,
|
||||
"salt": "GcjAUSZ4pLAZsDHL",
|
||||
"pwhash": "5fa4d3b86c8ca981dbc3ea4cbbd015030bda8bd444d4039309e88b23c7",
|
||||
"maxmem": 32768
|
||||
},
|
||||
{
|
||||
"passwd": "cUu3ACKqAHnI54Eh",
|
||||
"mode": "raw",
|
||||
"dgst_len": 23,
|
||||
"iters": 3,
|
||||
"salt": "6H99IAjhJQ2WFgom",
|
||||
"pwhash": "6202e1b58e65a658d1adcc0584fafd6373e565d6fd8348",
|
||||
"maxmem": 32768
|
||||
},
|
||||
{
|
||||
"passwd": "jBB3PBZ8v1H1aga",
|
||||
"mode": "raw",
|
||||
"dgst_len": 20,
|
||||
"iters": 4,
|
||||
"salt": "L3vcnvwJbLJTdvKx",
|
||||
"pwhash": "f3d792b3edbf49441c269c22c2641e724cb21ef0",
|
||||
"maxmem": 16384
|
||||
},
|
||||
{
|
||||
"passwd": "WGA58n0DVW9FT",
|
||||
"mode": "raw",
|
||||
"dgst_len": 18,
|
||||
"iters": 3,
|
||||
"salt": "qN6Q3h3lzJtXcMkH",
|
||||
"pwhash": "ec9dd7f5503cc5b74ab1fc8ac6cad426327f",
|
||||
"maxmem": 65536
|
||||
},
|
||||
{
|
||||
"passwd": "rxB2Op3fo17s6",
|
||||
"mode": "raw",
|
||||
"dgst_len": 27,
|
||||
"iters": 5,
|
||||
"salt": "xw9IrU6uf4E4hBo3",
|
||||
"pwhash": "ffe9c857e686ab40f8758415acd6d3409acfe80d54bac24bcacfa3",
|
||||
"maxmem": 65536
|
||||
},
|
||||
{
|
||||
"passwd": "JyjdXkjHxGiGjg",
|
||||
"mode": "raw",
|
||||
"dgst_len": 30,
|
||||
"iters": 5,
|
||||
"salt": "rN0D8NoVbNBnlEex",
|
||||
"pwhash": "fab6d8b5e1849c99f5261c15ff502b1bb245f8076efa5e01cbbdc1903512",
|
||||
"maxmem": 32768
|
||||
}
|
||||
]
|
102
spec/data/raw_argon2id_hashes.json
Normal file
102
spec/data/raw_argon2id_hashes.json
Normal file
@ -0,0 +1,102 @@
|
||||
[
|
||||
{
|
||||
"iters": 1,
|
||||
"mode": "raw",
|
||||
"salt": "RPgjpKWKmH7otL58",
|
||||
"dgst_len": 25,
|
||||
"construct": "argon2id",
|
||||
"passwd": "jfuT8oJu2Fg",
|
||||
"pwhash": "959f27c6ac7a7f9d4cebb7bb1cc05833810079e4e384f687a7",
|
||||
"maxmem": 131072
|
||||
},
|
||||
{
|
||||
"iters": 4,
|
||||
"mode": "raw",
|
||||
"salt": "hsvjdI3ckgfMke6x",
|
||||
"dgst_len": 19,
|
||||
"construct": "argon2id",
|
||||
"passwd": "J2TU89T68L",
|
||||
"pwhash": "f45619dcd98553c38a4f311904a06e888dd5dd",
|
||||
"maxmem": 32768
|
||||
},
|
||||
{
|
||||
"iters": 3,
|
||||
"mode": "raw",
|
||||
"salt": "oCSdi7b6I3UYftj6",
|
||||
"dgst_len": 23,
|
||||
"construct": "argon2id",
|
||||
"passwd": "ZTgoKeVg",
|
||||
"pwhash": "823cd743a9378b0013a61b275d8a8d61b4abf465e3c758",
|
||||
"maxmem": 65536
|
||||
},
|
||||
{
|
||||
"iters": 3,
|
||||
"mode": "raw",
|
||||
"salt": "BcZv9BmKSL1BZXBD",
|
||||
"dgst_len": 25,
|
||||
"construct": "argon2id",
|
||||
"passwd": "3bDtmljuB86",
|
||||
"pwhash": "a667a360356b3658656cc51feda5abc3c9932d1e3b4a398633",
|
||||
"maxmem": 16384
|
||||
},
|
||||
{
|
||||
"iters": 5,
|
||||
"mode": "raw",
|
||||
"salt": "hqiuuNWIOLHft77r",
|
||||
"dgst_len": 20,
|
||||
"construct": "argon2id",
|
||||
"passwd": "410nLopRL2Pt6yT",
|
||||
"pwhash": "7274d6a9be2b52feab9b346df1abee1a68ec5c79",
|
||||
"maxmem": 65536
|
||||
},
|
||||
{
|
||||
"iters": 1,
|
||||
"mode": "raw",
|
||||
"salt": "ZP3u5yVZTAl0F33z",
|
||||
"dgst_len": 31,
|
||||
"construct": "argon2id",
|
||||
"passwd": "0pXnCEpVlR",
|
||||
"pwhash": "d14d136cae8ca735e0fe03d2c618f904cff07a525579d0dc67d813b223ac7a",
|
||||
"maxmem": 32768
|
||||
},
|
||||
{
|
||||
"iters": 3,
|
||||
"mode": "raw",
|
||||
"salt": "QWWo5rUeD3nBv0dF",
|
||||
"dgst_len": 28,
|
||||
"construct": "argon2id",
|
||||
"passwd": "vl50xKRCK0EHNRY",
|
||||
"pwhash": "23560c5771bb56d02c8129effd4ff2c70d2f28e1912636ff1a4f11a6",
|
||||
"maxmem": 262144
|
||||
},
|
||||
{
|
||||
"iters": 5,
|
||||
"mode": "raw",
|
||||
"salt": "OADldcmnqJHY6tkc",
|
||||
"dgst_len": 24,
|
||||
"construct": "argon2id",
|
||||
"passwd": "EuXIuKCdFq",
|
||||
"pwhash": "bae0f9ff8143a141bfb8b8629414eba2c51f122b2524e73d",
|
||||
"maxmem": 65536
|
||||
},
|
||||
{
|
||||
"iters": 2,
|
||||
"mode": "raw",
|
||||
"salt": "cxYQAFWsKbji4Y0e",
|
||||
"dgst_len": 30,
|
||||
"construct": "argon2id",
|
||||
"passwd": "2su5ROWRMZLOOWbv",
|
||||
"pwhash": "6341329de527593dbd479e24ca02b7f6bfcc29a6c74def655db74808e199",
|
||||
"maxmem": 32768
|
||||
},
|
||||
{
|
||||
"iters": 1,
|
||||
"mode": "raw",
|
||||
"salt": "Zk6vLoBZZA8lgzKL",
|
||||
"dgst_len": 19,
|
||||
"construct": "argon2id",
|
||||
"passwd": "7mPYiXjrwLw",
|
||||
"pwhash": "84dc96e740c84cc52855c3f7c1b5b05070d14a",
|
||||
"maxmem": 65536
|
||||
}
|
||||
]
|
6
spec/data/sealed_box_ref.txt
Normal file
6
spec/data/sealed_box_ref.txt
Normal file
@ -0,0 +1,6 @@
|
||||
# generated reference vectors for crypto_seal_box
|
||||
# Format: <recipient sk> <tab> <recipient pk> <tab> <pt_len>:<plaintext> <tab> <cr_len>:<ciphertext> [<tab> ...]
|
||||
# all fields are hex encoded
|
||||
77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a 8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a 131:be075fc53c81f2d5cf141316ebeb0c7b5228c52a4c62cbd44b66849b64244ffce5ecbaaf33bd751a1ac728d45e6c61296cdc3c01233561f41db66cce314adb310e3be8250c46f06dceea3a7fa1348057e2f6556ad6b1318a024a838f21af1fde048977eb48f59ffd4924ca1c60902e52f0a089bc76897040e082f937763848645e0705 179:199c808806a62c1be56951023ad3396b0ce0ef2c5b9ca688ac96d2d06ca43f65d314400cc9bbefb23dd26f824c9cb553f81e8c894ea9a553f4d777c77b66d5a6925da3f5961c5f7147172db5597ac14210066ee3ee13e6230a9a9610e9cddbf24094f54fbbf6694c08a436cec39ff5a373656d9584f4df9dd8c817e2e597540628d0ee21a6524a3fcf3eabdc0968390bd260a47366ead7f71cc2e774d411d96f3497c7e10291937bc16dc46a111686b85a8c86
|
||||
7fdc652e0f714cc6f6d5f7bf1aab9da7fcaa5b27f1f7763f31a659cc6ddd60d5 695ec87c37afbb70771a1a048e08d7c70a25b7d710e23a5814248128f3db035d 0: 48:017f873a1536b35eac54f729e0f05ea5c5a96f9c221327d70bf46497b3b33007a84d0b93667ea189ad4dfcc016f727d1
|
||||
1bcdb90ac2996d3e5598a404fd8753bae482ec821a64e306e15416228bae7212 6415b1fe7bb4dc602097f607249df89eb59cf2e75be1cb74abfc0664dc0f0a3d 1:eb 49:dbe788125ef86d2d4049feb371cf25e2a52a0d71505eeb2ebff526e859e6495c3c278fa7ba88e41c92c711a0ddbd3bdf09
|
@ -40,7 +40,7 @@ describe Sodium::CryptoBox::SecretKey do
|
||||
# Encrypt a message for Bob using his public key, signing it with Alice's
|
||||
# secret key
|
||||
box = alice.box bob.public_key
|
||||
nonce, encrypted = box.encrypt_easy data
|
||||
encrypted, nonce = box.encrypt_easy data
|
||||
|
||||
# Decrypt the message using Bob's secret key, and verify its signature against
|
||||
# Alice's public key
|
||||
|
@ -1,5 +1,47 @@
|
||||
require "../spec_helper"
|
||||
require "../../src/sodium/pwhash"
|
||||
require "json"
|
||||
|
||||
def test_vectors(filename, pwmode)
|
||||
pwhash = Sodium::Pwhash.new
|
||||
|
||||
buf = File.read Path[__DIR__].join("..", "data", filename)
|
||||
vectors = Array(Hash(String, String | Int32)).from_json(buf).map do |h|
|
||||
{
|
||||
salt: h["salt"].to_s,
|
||||
pass: h["passwd"].to_s,
|
||||
mode: h["mode"].to_s,
|
||||
ops: h["iters"].to_i,
|
||||
mem: h["maxmem"].to_i * 1024,
|
||||
dgst_len: h["dgst_len"].to_i,
|
||||
hash: h["pwhash"].to_s,
|
||||
# h: h,
|
||||
}
|
||||
end
|
||||
|
||||
vectors.each do |h|
|
||||
case h[:mode]
|
||||
when "argon2i"
|
||||
pwhash.mode = Sodium::Pwhash::Mode::Argon2i13
|
||||
pwhash.verify h[:hash], h[:pass]
|
||||
when "argon2id"
|
||||
pwhash.mode = Sodium::Pwhash::Mode::Argon2id13
|
||||
pwhash.verify h[:hash], h[:pass]
|
||||
when "raw"
|
||||
pwhash.opslimit = h[:ops].to_u64
|
||||
pwhash.memlimit = h[:mem].to_u64
|
||||
pwhash.mode = pwmode
|
||||
# p pwhash, h
|
||||
key = pwhash.key_derive salt: h[:salt].to_slice, pass: h[:pass], key_bytes: h[:dgst_len]
|
||||
key.should eq h[:hash].hexbytes
|
||||
else
|
||||
# p h
|
||||
puts "unhandled mode #{h[:mode]}"
|
||||
next
|
||||
# raise "unhandled mode #{h[:mode]}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private def pw_min
|
||||
pwhash = Sodium::Pwhash.new
|
||||
@ -26,7 +68,7 @@ describe Sodium::Pwhash do
|
||||
pwhash.needs_rehash?(hash).should be_true
|
||||
end
|
||||
|
||||
it "key_derive fails without an algorithm" do
|
||||
it "key_derive fails without a mode" do
|
||||
pwhash = pw_min
|
||||
expect_raises(ArgumentError) do
|
||||
pwhash.key_derive pwhash.salt, "foo", 16
|
||||
@ -35,7 +77,7 @@ describe Sodium::Pwhash do
|
||||
|
||||
it "derives a key from a password" do
|
||||
pwhash = pw_min
|
||||
pwhash.algorithm = Sodium::Pwhash::Algorithm::Argon2id13
|
||||
pwhash.mode = Sodium::Pwhash::Mode::Argon2id13
|
||||
salt = pwhash.salt
|
||||
key1 = pwhash.key_derive salt, "foo", 16
|
||||
key2 = pwhash.key_derive salt, "foo", 16
|
||||
@ -46,6 +88,35 @@ describe Sodium::Pwhash do
|
||||
key1.should eq key2
|
||||
key1.should_not eq key3
|
||||
key1.should_not eq key4
|
||||
# BUG: validate against known passwords
|
||||
end
|
||||
|
||||
it "PyNaCl key vectors" do
|
||||
test_vectors "modular_crypt_argon2i_hashes.json", Sodium::Pwhash::Mode::Argon2i13
|
||||
test_vectors "modular_crypt_argon2id_hashes.json", Sodium::Pwhash::Mode::Argon2id13
|
||||
test_vectors "raw_argon2i_hashes.json", Sodium::Pwhash::Mode::Argon2i13
|
||||
test_vectors "raw_argon2id_hashes.json", Sodium::Pwhash::Mode::Argon2id13
|
||||
end
|
||||
|
||||
# from libsodium/test/default/pwhash_argon2id.c
|
||||
it "RbNaCl key vectors" do
|
||||
pwhash = Sodium::Pwhash.new
|
||||
pwhash.mode = Sodium::Pwhash::Mode::Argon2id13
|
||||
pwhash.opslimit = 5_u64
|
||||
pwhash.memlimit = 7_256_678_u64
|
||||
key_len = 155
|
||||
|
||||
pass = "a347ae92bce9f80f6f595a4480fc9c2fe7e7d7148d371e9487d75f5c23008ffae0" \
|
||||
"65577a928febd9b1973a5a95073acdbeb6a030cfc0d79caa2dc5cd011cef02c08d" \
|
||||
"a232d76d52dfbca38ca8dcbd665b17d1665f7cf5fe59772ec909733b24de97d6f5" \
|
||||
"8d220b20c60d7c07ec1fd93c52c31020300c6c1facd77937a597c7a6".hexbytes
|
||||
salt = "5541fbc995d5c197ba290346d2c559de".hexbytes
|
||||
expected = "18acec5d6507739f203d1f5d9f1d862f7c2cdac4f19d2bdff64487e60d969e3ced6" \
|
||||
"15337b9eec6ac4461c6ca07f0939741e57c24d0005c7ea171a0ee1e7348249d135b" \
|
||||
"38f222e4dad7b9a033ed83f5ca27277393e316582033c74affe2566a2bea47f91f0" \
|
||||
"fd9fe49ece7e1f79f3ad6e9b23e0277c8ecc4b313225748dd2a80f5679534a0700e" \
|
||||
"246a79a49b3f74eb89ec6205fe1eeb941c73b1fcf1".hexbytes
|
||||
|
||||
key = pwhash.key_derive salt, pass, key_len
|
||||
key.should eq expected
|
||||
end
|
||||
end
|
||||
|
@ -1,6 +1,7 @@
|
||||
require "./lib_sodium"
|
||||
require "./wipe"
|
||||
require "./crypto_box/secret_key"
|
||||
require "./nonce"
|
||||
|
||||
module Sodium
|
||||
class CryptoBox
|
||||
@ -24,7 +25,7 @@ module Sodium
|
||||
if LibSodium.crypto_box_easy(dst, src, src.bytesize, nonce.to_slice, @public_key.to_slice, @secret_key.to_slice) != 0
|
||||
raise Error.new("crypto_box_easy")
|
||||
end
|
||||
{nonce, dst}
|
||||
{dst, nonce}
|
||||
end
|
||||
|
||||
def decrypt_easy(src)
|
||||
|
@ -20,10 +20,11 @@ module Sodium
|
||||
MEMLIMIT_INTERACTIVE = LibSodium.crypto_pwhash_memlimit_interactive
|
||||
MEMLIMIT_MAX = LibSodium.crypto_pwhash_memlimit_max # Don't use this. Maximum of the library which is more ram than any computer.
|
||||
|
||||
SALT_SIZE = LibSodium.crypto_pwhash_saltbytes
|
||||
STR_SIZE = LibSodium.crypto_pwhash_strbytes
|
||||
|
||||
# Use the most recent algorithm Argon2id13 for new applications.
|
||||
enum Algorithm
|
||||
enum Mode
|
||||
Argon2i13 = 1
|
||||
Argon2id13 = 2
|
||||
end
|
||||
@ -33,7 +34,7 @@ module Sodium
|
||||
property memlimit = MEMLIMIT_INTERACTIVE
|
||||
|
||||
# Used by and must be set before calling #key_derive
|
||||
property algorithm : Algorithm?
|
||||
property mode : Mode?
|
||||
|
||||
# Apply the most recent password hashing algorithm agains a password.
|
||||
# Returns a opaque String which includes:
|
||||
@ -73,28 +74,30 @@ module Sodium
|
||||
end
|
||||
end
|
||||
|
||||
# Returns a consistent key based on [salt, pass, key_bytes, algorithm, ops_limit, mem_limit]
|
||||
# Returns a consistent key based on [salt, pass, key_bytes, mode, ops_limit, mem_limit]
|
||||
#
|
||||
# Must set an algorithm before calling.
|
||||
def key_derive(salt : Bytes, pass : Bytes, key_bytes) : Bytes
|
||||
if alg = algorithm
|
||||
key = Bytes.new key_bytes
|
||||
if LibSodium.crypto_pwhash(key, key.bytesize, pass, pass.bytesize, salt, @opslimit, @memlimit, alg) != 0
|
||||
raise Sodium::Error.new("crypto_pwhash_str")
|
||||
end
|
||||
key
|
||||
else
|
||||
raise ArgumentError.new("algorithm not set")
|
||||
end
|
||||
end
|
||||
|
||||
# Must set a mode before calling.
|
||||
def key_derive(salt, pass, key_bytes)
|
||||
key_derive salt.to_slice, pass.to_slice, key_bytes
|
||||
end
|
||||
|
||||
def key_derive(salt : Bytes, pass : Bytes, key_bytes) : Bytes
|
||||
raise "salt expected #{SALT_SIZE} bytes, got #{salt.bytesize} " if salt.bytesize != SALT_SIZE
|
||||
|
||||
if m = mode
|
||||
key = Bytes.new key_bytes
|
||||
if LibSodium.crypto_pwhash(key, key.bytesize, pass, pass.bytesize, salt, @opslimit, @memlimit, m) != 0
|
||||
raise Sodium::Error.new("crypto_pwhash_str")
|
||||
end
|
||||
key
|
||||
else
|
||||
raise ArgumentError.new("mode not set")
|
||||
end
|
||||
end
|
||||
|
||||
# Returns a random salt for use with #key_derive
|
||||
def salt
|
||||
Random::Secure.random_bytes LibSodium.crypto_pwhash_saltbytes
|
||||
Random::Secure.random_bytes SALT_SIZE
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -1,5 +1,6 @@
|
||||
require "./lib_sodium"
|
||||
require "./key"
|
||||
require "./nonce"
|
||||
|
||||
module Sodium
|
||||
# [https://libsodium.gitbook.io/doc/secret-key_cryptography](https://libsodium.gitbook.io/doc/secret-key_cryptography)
|
||||
|
Loading…
Reference in New Issue
Block a user