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