From fde955c5093cddb8b7ace0a1bb098ef0be86f4d0 Mon Sep 17 00:00:00 2001 From: Didactic Drunk <1479616+didactic-drunk@users.noreply.github.com> Date: Tue, 6 Aug 2019 03:30:16 -0700 Subject: [PATCH] Rename Sodium::Pwhash#store to #create. Rename Sodium::Pwhash#key_derive to #derive_key. Rename Sodium::Pwhash#kdf_derive to #derive_kdf. Rename Sodium::CryptoBox#encrypt_easy to #encrypt. Rename Sodium::CryptoBox#decrypt_easy to #decrypt. Rename Sodium::SecretBox#encrypt_easy to #encrypt. Rename Sodium::SecretBox#decrypt_easy to #decrypt. Remove redundant Sodium::SecretBox#encrypt methods. --- README.md | 4 +-- spec/sodium/crypto_box/secret_key_spec.cr | 8 ++--- spec/sodium/pwhash_spec.cr | 26 +++++++++------ spec/sodium/secret_box_spec.cr | 10 +++--- src/sodium/crypto_box.cr | 12 +++---- src/sodium/pwhash.cr | 23 ++++++------- src/sodium/secret_box.cr | 39 +++++++---------------- 7 files changed, 58 insertions(+), 64 deletions(-) diff --git a/README.md b/README.md index 241cd92..780cd74 100644 --- a/README.md +++ b/README.md @@ -184,11 +184,11 @@ public_key.verify_detached message, signature key = Sodium::SecretKey.new message = "foobar" -encrypted, nonce = key.encrypt_easy message +encrypted, nonce = key.encrypt message # On the other side. key = Sodium::SecretKey.new key -message = key.decrypt_easy encrypted, nonce +message = key.decrypt encrypted, nonce ``` ### Blake2b diff --git a/spec/sodium/crypto_box/secret_key_spec.cr b/spec/sodium/crypto_box/secret_key_spec.cr index 6ba4eb3..f1323a3 100644 --- a/spec/sodium/crypto_box/secret_key_spec.cr +++ b/spec/sodium/crypto_box/secret_key_spec.cr @@ -73,12 +73,12 @@ 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 - encrypted, nonce = box.encrypt_easy data + encrypted, nonce = box.encrypt data # Decrypt the message using Bob's secret key, and verify its signature against # Alice's public key bob.box alice.public_key do |box| - decrypted = box.decrypt_easy encrypted, nonce: nonce + decrypted = box.decrypt encrypted, nonce: nonce String.new(decrypted).should eq(data) end @@ -102,10 +102,10 @@ describe Sodium::CryptoBox::SecretKey do it "PyNaCl combined test vectors" do combined_test_vectors.each do |vec| box_from_vec(vec) do |box1, box2, nonce, plaintext, ciphertext| - encrypted, _ = box1.encrypt_easy plaintext, nonce: nonce + encrypted, _ = box1.encrypt plaintext, nonce: nonce encrypted.should eq ciphertext - decrypted = box2.decrypt_easy ciphertext, nonce: nonce + decrypted = box2.decrypt ciphertext, nonce: nonce decrypted.should eq plaintext end end diff --git a/spec/sodium/pwhash_spec.cr b/spec/sodium/pwhash_spec.cr index 45048d1..f09040f 100644 --- a/spec/sodium/pwhash_spec.cr +++ b/spec/sodium/pwhash_spec.cr @@ -1,5 +1,6 @@ require "../spec_helper" require "../../src/sodium/pwhash" +require "../../src/sodium/kdf" require "json" def test_vectors(filename, pwmode) @@ -32,7 +33,7 @@ def test_vectors(filename, pwmode) 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 = pwhash.derive_key salt: h[:salt].to_slice, pass: h[:pass], key_bytes: h[:dgst_len] key.should eq h[:hash].hexbytes else # p h @@ -57,7 +58,7 @@ describe Sodium::Pwhash do pwhash = pw_min pass = "1234" - hash = pwhash.store pass + hash = pwhash.create pass pwhash.verify hash, pass expect_raises(Sodium::Pwhash::PasswordVerifyError) do pwhash.verify hash, "5678" @@ -68,10 +69,10 @@ describe Sodium::Pwhash do pwhash.needs_rehash?(hash).should be_true end - it "key_derive fails without a mode" do + it "derive_key fails without a mode" do pwhash = pw_min expect_raises(ArgumentError) do - pwhash.key_derive pwhash.random_salt, "foo", 16 + pwhash.derive_key pwhash.random_salt, "foo", 16 end end @@ -79,10 +80,10 @@ describe Sodium::Pwhash do pwhash = pw_min pwhash.mode = Sodium::Pwhash::Mode::Argon2id13 salt = pwhash.random_salt - key1 = pwhash.key_derive salt, "foo", 16 - key2 = pwhash.key_derive salt, "foo", 16 - key3 = pwhash.key_derive salt, "bar", 16 - key4 = pwhash.key_derive pwhash.random_salt, "foo", 16 + key1 = pwhash.derive_key salt, "foo", 16 + key2 = pwhash.derive_key salt, "foo", 16 + key3 = pwhash.derive_key salt, "bar", 16 + key4 = pwhash.derive_key pwhash.random_salt, "foo", 16 key1.bytesize.should eq 16 key1.should eq key2 @@ -90,6 +91,13 @@ describe Sodium::Pwhash do key1.should_not eq key4 end + it "derives a kdf from a password" do + pwhash = pw_min + pwhash.mode = Sodium::Pwhash::Mode::Argon2id13 + salt = pwhash.random_salt + kdf = pwhash.derive_kdf salt, "foo", 32 + 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 @@ -116,7 +124,7 @@ describe Sodium::Pwhash do "fd9fe49ece7e1f79f3ad6e9b23e0277c8ecc4b313225748dd2a80f5679534a0700e" \ "246a79a49b3f74eb89ec6205fe1eeb941c73b1fcf1".hexbytes - key = pwhash.key_derive salt, pass, key_len + key = pwhash.derive_key salt, pass, key_len key.should eq expected end end diff --git a/spec/sodium/secret_box_spec.cr b/spec/sodium/secret_box_spec.cr index a43b495..eb71975 100644 --- a/spec/sodium/secret_box_spec.cr +++ b/spec/sodium/secret_box_spec.cr @@ -31,12 +31,12 @@ describe Sodium::SecretBox do box = Sodium::SecretBox.new message = "foobar" - encrypted, nonce = box.encrypt_easy message - decrypted = box.decrypt_easy encrypted, nonce + encrypted, nonce = box.encrypt message + decrypted = box.decrypt encrypted, nonce: nonce message.should eq String.new(decrypted) expect_raises(Sodium::Error::DecryptionFailed) do - box.decrypt_easy "badmsgbadmsgbadmsgbadmsgbadmsg".to_slice, nonce + box.decrypt "badmsgbadmsgbadmsgbadmsgbadmsg".to_slice, nonce end end @@ -44,10 +44,10 @@ describe Sodium::SecretBox do combined_test_vectors.each do |vec| box, nonce, plaintext, ciphertext = box_from_test_vector vec - encrypted = box.encrypt_easy plaintext, nonce + encrypted, _ = box.encrypt plaintext, nonce: nonce encrypted.should eq ciphertext - decrypted = box.decrypt_easy encrypted, nonce + decrypted = box.decrypt encrypted, nonce: nonce plaintext.should eq decrypted end end diff --git a/src/sodium/crypto_box.cr b/src/sodium/crypto_box.cr index 2bed26b..b7216f1 100644 --- a/src/sodium/crypto_box.cr +++ b/src/sodium/crypto_box.cr @@ -17,22 +17,22 @@ module Sodium # TODO: precompute using crypto_box_beforenm end - def encrypt_easy(src) - encrypt_easy src.to_slice + def encrypt(src) + encrypt src.to_slice end - def encrypt_easy(src : Bytes, dst = Bytes.new(src.bytesize + MAC_SIZE), nonce = Nonce.new) + def encrypt(src : Bytes, dst = Bytes.new(src.bytesize + MAC_SIZE), nonce = Nonce.new) 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 {dst, nonce} end - def decrypt_easy(src) - decrypt_easy src.to_slice + def decrypt(src) + decrypt src.to_slice end - def decrypt_easy(src : Bytes, dst = Bytes.new(src.bytesize - MAC_SIZE), nonce = Nonce.new) : Bytes + def decrypt(src : Bytes, dst = Bytes.new(src.bytesize - MAC_SIZE), nonce = Nonce.new) : Bytes if LibSodium.crypto_box_open_easy(dst, src, src.bytesize, nonce.to_slice, @public_key.to_slice, @secret_key.to_slice) != 0 raise Error::DecryptionFailed.new("crypto_box_open_easy") end diff --git a/src/sodium/pwhash.cr b/src/sodium/pwhash.cr index b1d9a17..ff011e1 100644 --- a/src/sodium/pwhash.cr +++ b/src/sodium/pwhash.cr @@ -4,7 +4,7 @@ require "./secure_buffer" module Sodium # [Argon2 Password Hashing](https://libsodium.gitbook.io/doc/password_hashing/the_argon2i_function) # * #store #verify #needs_rehash? are used together for password verification. - # * #key_derive is used on it's own to generate password based keys. + # * #derive_key is used on it's own to generate password based keys. # # **See `examples/pwhash_selector.cr` for help on selecting parameters.** class Pwhash @@ -19,7 +19,8 @@ module Sodium MEMLIMIT_MIN = LibSodium.crypto_pwhash_memlimit_min 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. + # Don't use this. Maximum of the library which is more ram than any computer. + MEMLIMIT_MAX = LibSodium.crypto_pwhash_memlimit_max SALT_SIZE = LibSodium.crypto_pwhash_saltbytes STR_SIZE = LibSodium.crypto_pwhash_strbytes @@ -34,7 +35,7 @@ module Sodium # Specified in bytes. property memlimit = MEMLIMIT_INTERACTIVE - # Used by and must be set before calling #key_derive + # Used by and must be set before calling #derive_key property mode : Mode? # Apply the most recent password hashing algorithm agains a password. @@ -42,7 +43,7 @@ module Sodium # * the result of a memory-hard, CPU-intensive hash function applied to the password # * the automatically generated salt used for the previous computation # * the other parameters required to verify the password, including the algorithm identifier, its version, opslimit and memlimit. - def store(pass) + def create(pass) outstr = Bytes.new STR_SIZE if LibSodium.crypto_pwhash_str(outstr, pass, pass.bytesize, @opslimit, @memlimit) != 0 raise Sodium::Error.new("crypto_pwhash_str") @@ -78,11 +79,11 @@ module Sodium # Returns a consistent key based on [salt, pass, key_bytes, mode, ops_limit, mem_limit] in a SecureBuffer # # Must set a mode before calling. - def key_derive(salt, pass, key_bytes) - key_derive salt.to_slice, pass.to_slice, key_bytes + def derive_key(salt, pass, key_bytes) + derive_key salt.to_slice, pass.to_slice, key_bytes end - def key_derive(salt : Bytes, pass : Bytes, key_bytes) : SecureBuffer + def derive_key(salt : Bytes, pass : Bytes, key_bytes) : SecureBuffer raise "salt expected #{SALT_SIZE} bytes, got #{salt.bytesize} " if salt.bytesize != SALT_SIZE if m = mode @@ -96,13 +97,13 @@ module Sodium end end - # Derives a key using key_derive and returns KDF.new(key) - def kdf_derive(salt, pass, key_bytes) : Kdf - key = key_derive salt, pass, key_bytes + # Derives a key using derive_key and returns KDF.new(key) + def derive_kdf(salt, pass, key_bytes) : Kdf + key = derive_key salt, pass, key_bytes Kdf.new key end - # Returns a random salt for use with #key_derive + # Returns a random salt for use with #derive_key def random_salt Random::Secure.random_bytes SALT_SIZE end diff --git a/src/sodium/secret_box.cr b/src/sodium/secret_box.cr index 4f2ea34..e18f7e5 100644 --- a/src/sodium/secret_box.cr +++ b/src/sodium/secret_box.cr @@ -9,11 +9,11 @@ module Sodium # ```crystal # key = Sodium::SecretBox.new # message = "foobar" - # encrypted, nonce = key.encrypt_easy message + # encrypted, nonce = key.encrypt message # # # On the other side. # key = Sodium::SecretBox.new key - # message = key.decrypt_easy encrypted, nonce + # message = key.decrypt encrypted, nonce # ``` class SecretBox < Key KEY_SIZE = LibSodium.crypto_secretbox_keybytes.to_i @@ -45,43 +45,28 @@ module Sodium @buf = SecureBuffer.new bytes, erase: erase end - def encrypt_easy(data) - encrypt_easy data.to_slice + def encrypt(data) + encrypt data.to_slice end - def encrypt_easy(data, nonce : Nonce) - encrypt_easy data.to_slice, nonce - end - - def encrypt_easy(data : Bytes) - nonce = Nonce.new - output = encrypt_easy data, nonce - {output, nonce} - end - - def encrypt_easy(data : Bytes, nonce : Nonce) : Bytes - output = Bytes.new(data.bytesize + MAC_SIZE) - encrypt_easy(data, output, nonce) - end - - def encrypt_easy(src : Bytes, dst : Bytes, nonce : Nonce) : Bytes + def encrypt(src : Bytes, dst : Bytes = Bytes.new(src.bytesize + MAC_SIZE), nonce : Nonce = Nonce.new) : {Bytes, Nonce} if dst.bytesize != (src.bytesize + MAC_SIZE) raise ArgumentError.new("dst.bytesize must be src.bytesize + MAC_SIZE, got #{dst.bytesize}") end if LibSodium.crypto_secretbox_easy(dst, src, src.bytesize, nonce.to_slice, self.to_slice) != 0 raise Sodium::Error.new("crypto_secretbox_easy") end - dst + {dst, nonce} end - def decrypt_easy(data : Bytes, nonce : Nonce) : Bytes - output_size = data.bytesize - MAC_SIZE - raise Sodium::Error::DecryptionFailed.new("encrypted data too small #{data.bytesize}") if output_size <= 0 - output = Bytes.new output_size - decrypt_easy(data, output, nonce) + def decrypt(src : Bytes, nonce : Nonce) : Bytes + dst_size = src.bytesize - MAC_SIZE + raise Sodium::Error::DecryptionFailed.new("encrypted data too small #{src.bytesize}") if dst_size <= 0 + dst = Bytes.new dst_size + decrypt(src, dst, nonce) end - def decrypt_easy(src : Bytes, dst : Bytes, nonce : Nonce) : Bytes + def decrypt(src : Bytes, dst : Bytes, nonce : Nonce) : Bytes if dst.bytesize != (src.bytesize - MAC_SIZE) raise ArgumentError.new("dst.bytesize must be src.bytesize - MAC_SIZE, got #{dst.bytesize}") end