sodium.cr/spec/sodium/crypto_box/secret_key_spec.cr
2021-06-21 17:54:23 -07:00

128 lines
4.3 KiB
Crystal

require "../../spec_helper"
require "../../../src/sodium/crypto_box/secret_key"
combined_test_vectors = [
{
alice_sec: "77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a",
alice_pub: "8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a",
bob_sec: "5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb",
bob_pub: "de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f",
nonce: "69696ee955b62b73cd62bda875fc73d68219e0036b7a0b37",
plaintext: "be075fc53c81f2d5cf141316ebeb0c7b5228c52a4c62cbd44b66849b64244ffce5e" \
"cbaaf33bd751a1ac728d45e6c61296cdc3c01233561f41db66cce314adb310e3be8" \
"250c46f06dceea3a7fa1348057e2f6556ad6b1318a024a838f21af1fde048977eb4" \
"8f59ffd4924ca1c60902e52f0a089bc76897040e082f937763848645e0705",
ciphertext: "f3ffc7703f9400e52a7dfb4b3d3305d98e993b9f48681273c29650ba32fc76ce483" \
"32ea7164d96a4476fb8c531a1186ac0dfc17c98dce87b4da7f011ec48c97271d2c2" \
"0f9b928fe2270d6fb863d51738b48eeee314a7cc8ab932164548e526ae902243685" \
"17acfeabd6bb3732bc0e9da99832b61ca01b6de56244a9e88d5f9b37973f622a43d" \
"14a6599b1f654cb45a74e355a5",
},
]
private def box_from_vec(vec)
alice = Sodium::CryptoBox::SecretKey.new vec[:alice_sec].hexbytes, vec[:alice_pub].hexbytes
bob = Sodium::CryptoBox::SecretKey.new vec[:bob_sec].hexbytes, vec[:bob_pub].hexbytes
nonce = Sodium::Nonce.new vec[:nonce].hexbytes
plaintext = vec[:plaintext].hexbytes
ciphertext = vec[:ciphertext].hexbytes
alice.box(bob.public_key) do |box1|
bob.box(alice.public_key) do |box2|
yield box1, box2, nonce, plaintext, ciphertext
end
end
end
describe Sodium::CryptoBox::SecretKey do
it "loads keys" do
key1 = Sodium::CryptoBox::SecretKey.new
key2 = key1.key.readonly do |ks|
Sodium::CryptoBox::SecretKey.new ks, key1.public_key.to_slice
end
key1.key.should eq key2.key
key1.public_key.to_slice.should eq key2.public_key.to_slice
end
it "recomputes the public_key" do
key1 = Sodium::CryptoBox::SecretKey.new
key2 = key1.key.readonly do |ks|
Sodium::CryptoBox::SecretKey.new ks
end
key1.key.should eq key2.key
key1.public_key.to_slice.should eq key2.public_key.to_slice
end
it "seed keys" do
seed = Bytes.new Sodium::CryptoBox::SecretKey::SEED_SIZE
key1 = Sodium::CryptoBox::SecretKey.new seed: seed
key2 = Sodium::CryptoBox::SecretKey.new seed: seed
key1.key.should eq key2.key
key1.public_key.to_slice.should eq key2.public_key.to_slice
end
it "authenticated easy encrypt/decrypt" do
data = "Hello World!"
# Alice is the sender
alice = Sodium::CryptoBox::SecretKey.new
# Bob is the recipient
bob = Sodium::CryptoBox::SecretKey.new
# 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 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 encrypted, nonce: nonce
String.new(decrypted).should eq(data)
end
end
it "unauthenticated seal encrypt/decrypt" do
data = "foo bar"
# Bob is the recipient
bob = Sodium::CryptoBox::SecretKey.new
# Encrypt a message for Bob using his public key. No signature.
encrypted = bob.public_key.encrypt data
# Decrypt the message using Bob's secret key.
decrypted = bob.decrypt encrypted
String.new(decrypted).should eq(data)
end
it "can't encrypt twice using the same nonce" do
data = "Hello World!".to_slice
alice = Sodium::CryptoBox::SecretKey.new
bob = Sodium::CryptoBox::SecretKey.new
alice.box bob.public_key do |box|
encrypted, nonce = box.encrypt data
expect_raises Sodium::Nonce::Error::Reused do
box.encrypt data, nonce: nonce
end
end
end
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 plaintext, nonce: nonce
encrypted.should eq ciphertext
decrypted = box2.decrypt ciphertext, nonce: nonce
decrypted.should eq plaintext
end
end
end
end