Internal switch to Crypto::Secret
parent
0e1b64b1bf
commit
bd5e89dcd4
|
@ -89,15 +89,20 @@ end
|
|||
end
|
||||
|
||||
it "dups" do
|
||||
box1 = Sodium::Cipher::Aead::{{ name.id }}.new Bytes.new(Sodium::Cipher::Aead::{{ name.id }}::KEY_SIZE)
|
||||
key = Bytes.new Sodium::Cipher::Aead::{{ name.id }}::KEY_SIZE
|
||||
box1 = Sodium::Cipher::Aead::{{ name.id }}.new key
|
||||
box2 = box1.dup
|
||||
|
||||
key1 = box1.key
|
||||
key2 = box2.key
|
||||
key2.readwrite
|
||||
|
||||
key2.to_slice[0] = 1_u8
|
||||
key1.to_slice[0].should eq 0_u8
|
||||
key1.should eq key2
|
||||
key2.readwrite do |ks|
|
||||
ks[0] = 1_u8
|
||||
end
|
||||
key1.readonly do |ks|
|
||||
ks[0].should eq 0_u8
|
||||
end
|
||||
key1.should_not eq key2
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -26,8 +26,14 @@ require "../../../src/sodium/cipher/chalsa"
|
|||
key1 = cipher1.key
|
||||
key2 = cipher2.key
|
||||
|
||||
key2.to_slice[0] = 1_u8
|
||||
key1.to_slice[0].should eq 0_u8
|
||||
key1.should eq key2
|
||||
key2.readwrite do |ks|
|
||||
ks[0] = 1_u8
|
||||
end
|
||||
key1.readonly do |ks|
|
||||
ks[0].should eq 0_u8
|
||||
end
|
||||
key1.should_not eq key2
|
||||
end
|
||||
end
|
||||
{% end %}
|
||||
|
|
|
@ -34,14 +34,12 @@ private def box_from_vec(vec)
|
|||
end
|
||||
end
|
||||
|
||||
private def new_key_bytes
|
||||
Sodium::CryptoBox::SecretKey.new.to_slice
|
||||
end
|
||||
|
||||
describe Sodium::CryptoBox::SecretKey do
|
||||
it "loads keys" do
|
||||
key1 = Sodium::CryptoBox::SecretKey.new
|
||||
key2 = Sodium::CryptoBox::SecretKey.new key1.to_slice, key1.public_key.to_slice
|
||||
key2 = key1.key.readonly do |ks|
|
||||
Sodium::CryptoBox::SecretKey.new ks, key1.public_key.to_slice
|
||||
end
|
||||
key1.to_slice.should eq key2.to_slice
|
||||
key1.public_key.to_slice.should eq key2.public_key.to_slice
|
||||
end
|
||||
|
|
|
@ -15,7 +15,6 @@ module Sodium::Cipher
|
|||
def initialize(key : Crypto::Secret | Bytes, nonce = nil)
|
||||
raise ArgumentError.new("key must be #{key_size} bytes, got #{key.bytesize}") if key.bytesize != key_size
|
||||
@key = key.is_a?(Crypto::Secret) ? key : Sodium::SecureBuffer.new(key)
|
||||
# self.key = key if key
|
||||
self.nonce = nonce if nonce
|
||||
end
|
||||
|
||||
|
@ -116,8 +115,11 @@ module Sodium::Cipher
|
|||
def update(src : Bytes, dst : Bytes) : Bytes
|
||||
if (k = @key) && (n = @nonce)
|
||||
raise ArgumentError.new("src and dst bytesize must be identical") if src.bytesize != dst.bytesize
|
||||
if LibSodium.crypto_stream_{{ val.id }}_xor_ic(dst, src, src.bytesize, n, @offset, k.to_slice) != 0
|
||||
raise Sodium::Error.new("crypto_stream_{{ val.id }}_xor_ic")
|
||||
|
||||
k.readonly do |kslice|
|
||||
if LibSodium.crypto_stream_{{ val.id }}_xor_ic(dst, src, src.bytesize, n, @offset, kslice) != 0
|
||||
raise Sodium::Error.new("crypto_stream_{{ val.id }}_xor_ic")
|
||||
end
|
||||
end
|
||||
@offset += src.bytesize
|
||||
dst
|
||||
|
|
|
@ -39,19 +39,22 @@ class Sodium::CryptoBox
|
|||
SEED_SIZE = LibSodium.crypto_box_seedbytes.to_i
|
||||
SEAL_SIZE = LibSodium.crypto_box_sealbytes.to_i
|
||||
|
||||
getter key : Crypto::Secret
|
||||
getter public_key : PublicKey
|
||||
|
||||
# Returns key
|
||||
delegate_to_slice to: @sbuf
|
||||
delegate_to_slice to: @key
|
||||
|
||||
@seed : SecureBuffer?
|
||||
@seed : Crypto::Secret?
|
||||
|
||||
# Generate a new random secret/public key pair.
|
||||
def initialize
|
||||
@sbuf = SecureBuffer.new KEY_SIZE
|
||||
@key = SecureBuffer.new KEY_SIZE
|
||||
@public_key = PublicKey.new
|
||||
if LibSodium.crypto_box_keypair(@public_key.to_slice, self.to_slice) != 0
|
||||
raise Sodium::Error.new("crypto_box_keypair")
|
||||
@key.readwrite do |kslice|
|
||||
if LibSodium.crypto_box_keypair(@public_key.to_slice, kslice) != 0
|
||||
raise Sodium::Error.new("crypto_box_keypair")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -59,14 +62,16 @@ class Sodium::CryptoBox
|
|||
#
|
||||
# Takes ownership of an existing key in a SecureBuffer.
|
||||
# Recomputes the public key from a secret key if missing.
|
||||
def initialize(@sbuf : SecureBuffer, pkey : Bytes? = nil)
|
||||
raise ArgumentError.new("Secret key must be #{KEY_SIZE} bytes, got #{@sbuf.bytesize}") if @sbuf.bytesize != KEY_SIZE
|
||||
def initialize(@key : Crypto::Secret, pkey : Bytes? = nil)
|
||||
raise ArgumentError.new("Secret key must be #{KEY_SIZE} bytes, got #{@key.bytesize}") if @key.bytesize != KEY_SIZE
|
||||
if pk = pkey
|
||||
@public_key = PublicKey.new pk
|
||||
else
|
||||
@public_key = PublicKey.new
|
||||
if LibSodium.crypto_scalarmult_base(@public_key.to_slice, self.to_slice) != 0
|
||||
raise Sodium::Error.new("crypto_scalarmult_base")
|
||||
@key.readonly do |kslice|
|
||||
if LibSodium.crypto_scalarmult_base(@public_key.to_slice, kslice) != 0
|
||||
raise Sodium::Error.new("crypto_scalarmult_base")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -77,13 +82,15 @@ class Sodium::CryptoBox
|
|||
# Recomputes the public key from a secret key if missing.
|
||||
def initialize(bytes : Bytes, pkey : Bytes? = nil)
|
||||
raise ArgumentError.new("Secret key must be #{KEY_SIZE} bytes, got #{bytes.bytesize}") if bytes.bytesize != KEY_SIZE
|
||||
@sbuf = SecureBuffer.new bytes
|
||||
@key = SecureBuffer.new bytes
|
||||
if pk = pkey
|
||||
@public_key = PublicKey.new pk
|
||||
else
|
||||
@public_key = PublicKey.new
|
||||
if LibSodium.crypto_scalarmult_base(@public_key.to_slice, self.to_slice) != 0
|
||||
raise Sodium::Error.new("crypto_scalarmult_base")
|
||||
@key.readonly do |kslice|
|
||||
if LibSodium.crypto_scalarmult_base(@public_key.to_slice, kslice) != 0
|
||||
raise Sodium::Error.new("crypto_scalarmult_base")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -93,30 +100,38 @@ class Sodium::CryptoBox
|
|||
# Copies seed to a SecureBuffer.
|
||||
def initialize(*, seed : Bytes, erase = false)
|
||||
raise ArgumentError.new("Secret sign seed must be #{SEED_SIZE}, got #{seed.bytesize}") unless seed.bytesize == SEED_SIZE
|
||||
@seed = SecureBuffer.new seed, erase: erase
|
||||
@seed = seed = SecureBuffer.new seed, erase: erase
|
||||
|
||||
@sbuf = SecureBuffer.new KEY_SIZE
|
||||
@key = SecureBuffer.new KEY_SIZE
|
||||
@public_key = PublicKey.new
|
||||
if LibSodium.crypto_box_seed_keypair(@public_key.to_slice, self.to_slice, seed) != 0
|
||||
raise Sodium::Error.new("crypto_box_seed_keypair")
|
||||
seed.readonly do |seed_slice|
|
||||
@key.readwrite do |kslice|
|
||||
if LibSodium.crypto_box_seed_keypair(@public_key.to_slice, kslice, seed_slice) != 0
|
||||
raise Sodium::Error.new("crypto_box_seed_keypair")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Derive a new secret/public key pair based on a consistent seed.
|
||||
def initialize(*, seed : SecureBuffer)
|
||||
def initialize(*, seed : Crypto::Secret)
|
||||
raise ArgumentError.new("Secret sign seed must be #{SEED_SIZE}, got #{seed.bytesize}") unless seed.bytesize == SEED_SIZE
|
||||
@seed = seed
|
||||
|
||||
@sbuf = SecureBuffer.new KEY_SIZE
|
||||
@key = SecureBuffer.new KEY_SIZE
|
||||
@public_key = PublicKey.new
|
||||
if LibSodium.crypto_box_seed_keypair(@public_key.to_slice, self.to_slice, seed) != 0
|
||||
raise Sodium::Error.new("crypto_box_seed_keypair")
|
||||
seed.readonly do |seed_slice|
|
||||
@key.readwrite do |kslice|
|
||||
if LibSodium.crypto_box_seed_keypair(@public_key.to_slice, kslice, seed_slice) != 0
|
||||
raise Sodium::Error.new("crypto_box_seed_keypair")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def seed
|
||||
def seed : Crypto::Secret
|
||||
# BUG: Generate seed if not set.
|
||||
@seed.not_nil!.to_slice
|
||||
@seed.not_nil!
|
||||
end
|
||||
|
||||
# Return a Box containing a precomputed shared secret for use with authenticated encryption/decryption.
|
||||
|
@ -159,8 +174,10 @@ class Sodium::CryptoBox
|
|||
dst ||= Bytes.new dst_size
|
||||
raise ArgumentError.new("dst.bytesize must be src.bytesize - SEAL_SIZE, got #{dst.bytesize}") unless dst.bytesize == dst_size
|
||||
|
||||
if LibSodium.crypto_box_seal_open(dst, src, src.bytesize, @public_key.to_slice, self.to_slice) != 0
|
||||
raise Sodium::Error.new("crypto_box_seal_open")
|
||||
@key.readonly do |kslice|
|
||||
if LibSodium.crypto_box_seal_open(dst, src, src.bytesize, @public_key.to_slice, kslice) != 0
|
||||
raise Sodium::Error.new("crypto_box_seal_open")
|
||||
end
|
||||
end
|
||||
dst
|
||||
end
|
||||
|
|
|
@ -62,15 +62,23 @@ module Sodium::Digest
|
|||
#
|
||||
# `key`, `salt`, and `personal` are all optional. Many other libsodium bindings don't support them.
|
||||
# Check the other implementation(s) you need to interoperate with before using.
|
||||
def initialize(@digest_size : Int32 = OUT_SIZE, key : Bytes? | SecureBuffer? = nil, salt : Bytes? = nil, personal : Bytes? = nil)
|
||||
def initialize(@digest_size : Int32 = OUT_SIZE, key : Bytes? | Crypto::Secret? = nil, salt : Bytes? = nil, personal : Bytes? = nil)
|
||||
if (k = key) && k.bytesize > 0
|
||||
k = k.to_slice
|
||||
raise ArgumentError.new("key larger than KEY_SIZE_MAX(#{KEY_SIZE_MAX}), got #{k.bytesize}") if k.bytesize > KEY_SIZE_MAX
|
||||
# Test vectors contain small key sizes. Small keys shouldn't be used... Wtf?
|
||||
Log.warn &.emit("key smaller than KEY_SIZE_MIN(#{KEY_SIZE_MIN}), got #{k.bytesize}") if k.bytesize < KEY_SIZE_MIN
|
||||
# raise ArgumentError.new("key smaller than KEY_SIZE_MIN(#{KEY_SIZE_MIN}), got #{k.bytesize}") if k.bytesize < KEY_SIZE_MIN
|
||||
|
||||
case k
|
||||
in Bytes
|
||||
k.copy_to @key.to_slice
|
||||
in Crypto::Secret
|
||||
k.readonly do |k_slice|
|
||||
k_slice.copy_to @key.to_slice
|
||||
end
|
||||
end
|
||||
|
||||
@key_size = k.bytesize
|
||||
k.copy_to @key.to_slice
|
||||
end
|
||||
|
||||
if sa = salt
|
||||
|
|
Loading…
Reference in New Issue