Add unauthenticated secret/public key encryption.
This commit is contained in:
parent
162cd72b0c
commit
f038f9b52e
@ -27,7 +27,7 @@ describe Sodium::CryptoBox::SecretKey do
|
||||
key1.public_key.bytes.should eq key2.public_key.bytes
|
||||
end
|
||||
|
||||
it "easy encrypt/decrypt" do
|
||||
it "authenticated easy encrypt/decrypt" do
|
||||
data = "Hello World!"
|
||||
|
||||
# Alice is the sender
|
||||
@ -50,6 +50,21 @@ describe Sodium::CryptoBox::SecretKey do
|
||||
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 "wipes keys" do
|
||||
check_wiped new_key_bytes
|
||||
end
|
||||
|
@ -4,6 +4,8 @@ module Sodium::CryptoBox
|
||||
class Box
|
||||
include Wipe
|
||||
|
||||
MAC_SIZE = LibSodium.crypto_box_macbytes
|
||||
|
||||
# BUG: precompute size
|
||||
@[Wipe::Var]
|
||||
@bytes = Bytes.new(1)
|
||||
@ -16,14 +18,14 @@ module Sodium::CryptoBox
|
||||
encrypt_easy src.to_slice
|
||||
end
|
||||
|
||||
def encrypt_easy(src : Bytes, dst = Bytes.new(src.bytesize + LibSodium::MAC_SIZE), nonce = Nonce.new)
|
||||
def encrypt_easy(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
|
||||
{nonce, dst}
|
||||
end
|
||||
|
||||
def decrypt_easy(src : Bytes, dst = Bytes.new(src.bytesize - LibSodium::MAC_SIZE), nonce = Nonce.new) : Bytes
|
||||
def decrypt_easy(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
|
||||
|
@ -3,7 +3,8 @@ require "../lib_sodium"
|
||||
module Sodium::CryptoBox
|
||||
class PublicKey < Key
|
||||
include Wipe
|
||||
KEY_SIZE = LibSodium.crypto_box_publickeybytes
|
||||
KEY_SIZE = LibSodium.crypto_box_publickeybytes
|
||||
SEAL_SIZE = LibSodium.crypto_box_sealbytes
|
||||
|
||||
getter bytes : Bytes
|
||||
|
||||
@ -18,5 +19,18 @@ module Sodium::CryptoBox
|
||||
raise ArgumentError.new("Public key must be #{KEY_SIZE} bytes, got #{bytes.bytesize}")
|
||||
end
|
||||
end
|
||||
|
||||
# Anonymously send messages to a recipient given its public key.
|
||||
# For authenticated message use `secret_key.box(recipient_public_key).encrypt`.
|
||||
def encrypt(src)
|
||||
encrypt src.to_slice
|
||||
end
|
||||
|
||||
def encrypt(src : Bytes, dst : Bytes = Bytes.new(src.bytesize + SEAL_SIZE)) : Bytes
|
||||
if LibSodium.crypto_box_seal(dst, src, src.bytesize, @bytes) != 0
|
||||
raise Sodium::Error.new("crypto_box_seal")
|
||||
end
|
||||
dst
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -7,7 +7,7 @@ module Sodium::CryptoBox
|
||||
include Wipe
|
||||
KEY_SIZE = LibSodium.crypto_box_secretkeybytes
|
||||
SEED_SIZE = LibSodium.crypto_box_seedbytes
|
||||
MAC_SIZE = LibSodium::MAC_SIZE
|
||||
SEAL_SIZE = LibSodium.crypto_box_sealbytes
|
||||
|
||||
getter public_key : PublicKey
|
||||
|
||||
@ -51,7 +51,7 @@ module Sodium::CryptoBox
|
||||
end
|
||||
end
|
||||
|
||||
# Return a Box containing a precomputed shared secret for use with encryption/decryption.
|
||||
# Return a Box containing a precomputed shared secret for use with authenticated encryption/decryption.
|
||||
def box(public_key) : Box
|
||||
Box.new self, public_key
|
||||
end
|
||||
@ -65,5 +65,18 @@ module Sodium::CryptoBox
|
||||
b.close
|
||||
end
|
||||
end
|
||||
|
||||
# Anonymously receive messages without signatures.
|
||||
# For authenticated messages use `secret_key.box(recipient_public_key).decrypt`.
|
||||
def decrypt(src)
|
||||
encrypt src.to_slice
|
||||
end
|
||||
|
||||
def decrypt(src : Bytes, dst : Bytes = Bytes.new(src.bytesize - SEAL_SIZE)) : Bytes
|
||||
if LibSodium.crypto_box_seal_open(dst, src, src.bytesize, @public_key.bytes, @bytes) != 0
|
||||
raise Sodium::Error.new("crypto_box_seal_open")
|
||||
end
|
||||
dst
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -7,6 +7,7 @@ module Sodium
|
||||
fun crypto_box_secretkeybytes : LibC::SizeT
|
||||
fun crypto_box_seedbytes : LibC::SizeT
|
||||
fun crypto_box_noncebytes : LibC::SizeT
|
||||
fun crypto_box_sealbytes : LibC::SizeT
|
||||
fun crypto_box_macbytes : LibC::SizeT
|
||||
fun crypto_sign_publickeybytes : LibC::SizeT
|
||||
fun crypto_sign_secretkeybytes : LibC::SizeT
|
||||
@ -42,9 +43,7 @@ module Sodium
|
||||
fun crypto_generichash_blake2b_personalbytes : LibC::SizeT
|
||||
fun sodium_memzero(Pointer(LibC::UChar), LibC::SizeT) : Nil
|
||||
|
||||
NONCE_SIZE = crypto_box_noncebytes()
|
||||
MAC_SIZE = crypto_box_macbytes()
|
||||
SIGNATURE_SIZE = crypto_sign_bytes()
|
||||
NONCE_SIZE = crypto_box_noncebytes()
|
||||
|
||||
fun crypto_secretbox_easy(
|
||||
output : Pointer(LibC::UChar),
|
||||
@ -225,8 +224,4 @@ module Sodium
|
||||
if LibSodium.crypto_secretbox_noncebytes != LibSodium.crypto_box_noncebytes
|
||||
raise "Assumptions in this library regarding nonce sizes may not be valid"
|
||||
end
|
||||
|
||||
if LibSodium.crypto_secretbox_macbytes != LibSodium.crypto_box_macbytes
|
||||
raise "Assumptions in this library regarding mac sizes may not be valid"
|
||||
end
|
||||
end
|
||||
|
@ -15,7 +15,7 @@ module Sodium
|
||||
class SecretBox < Key
|
||||
KEY_SIZE = LibSodium.crypto_secretbox_keybytes
|
||||
NONCE_SIZE = LibSodium.crypto_secretbox_noncebytes
|
||||
MAC_SIZE = LibSodium::MAC_SIZE
|
||||
MAC_SIZE = LibSodium.crypto_secretbox_macbytes
|
||||
|
||||
@[Wipe::Var]
|
||||
property bytes : Bytes
|
||||
|
@ -4,6 +4,7 @@ module Sodium
|
||||
class Sign::PublicKey < Key
|
||||
include Wipe
|
||||
KEY_SIZE = LibSodium.crypto_sign_publickeybytes
|
||||
SIG_SIZE = LibSodium.crypto_sign_bytes
|
||||
|
||||
getter bytes : Bytes
|
||||
|
||||
@ -26,7 +27,7 @@ module Sodium
|
||||
end
|
||||
|
||||
def verify_detached(message : Bytes, sig : Bytes)
|
||||
raise ArgumentError.new("Signature must be #{LibSodium::SIGNATURE_SIZE} bytes, got #{sig.bytesize}") if sig.bytesize != LibSodium::SIGNATURE_SIZE
|
||||
raise ArgumentError.new("Signature must be #{SIG_SIZE} bytes, got #{sig.bytesize}") if sig.bytesize != SIG_SIZE
|
||||
|
||||
v = LibSodium.crypto_sign_verify_detached sig, message, message.bytesize, @bytes
|
||||
if v != 0
|
||||
|
@ -9,6 +9,7 @@ module Sodium
|
||||
# ```
|
||||
class Sign::SecretKey < Sodium::Key
|
||||
KEY_SIZE = LibSodium.crypto_sign_secretkeybytes
|
||||
SIG_SIZE = LibSodium.crypto_sign_bytes
|
||||
SEED_SIZE = LibSodium.crypto_sign_seedbytes
|
||||
|
||||
getter public_key : PublicKey
|
||||
@ -61,7 +62,7 @@ module Sodium
|
||||
end
|
||||
|
||||
def sign_detached(message : Bytes)
|
||||
sig = Bytes.new(LibSodium::SIGNATURE_SIZE)
|
||||
sig = Bytes.new(SIG_SIZE)
|
||||
if LibSodium.crypto_sign_detached(sig, out sig_len, message, message.bytesize, @bytes) != 0
|
||||
raise Error.new("crypto_sign_detached")
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user