Internal switch to Crypto::Secret
This commit is contained in:
parent
0e1b64b1bf
commit
bd5e89dcd4
@ -89,15 +89,20 @@ end
|
|||||||
end
|
end
|
||||||
|
|
||||||
it "dups" do
|
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
|
box2 = box1.dup
|
||||||
|
|
||||||
key1 = box1.key
|
key1 = box1.key
|
||||||
key2 = box2.key
|
key2 = box2.key
|
||||||
key2.readwrite
|
key1.should eq key2
|
||||||
|
key2.readwrite do |ks|
|
||||||
key2.to_slice[0] = 1_u8
|
ks[0] = 1_u8
|
||||||
key1.to_slice[0].should eq 0_u8
|
end
|
||||||
|
key1.readonly do |ks|
|
||||||
|
ks[0].should eq 0_u8
|
||||||
|
end
|
||||||
|
key1.should_not eq key2
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -26,8 +26,14 @@ require "../../../src/sodium/cipher/chalsa"
|
|||||||
key1 = cipher1.key
|
key1 = cipher1.key
|
||||||
key2 = cipher2.key
|
key2 = cipher2.key
|
||||||
|
|
||||||
key2.to_slice[0] = 1_u8
|
key1.should eq key2
|
||||||
key1.to_slice[0].should eq 0_u8
|
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
|
end
|
||||||
{% end %}
|
{% end %}
|
||||||
|
@ -34,14 +34,12 @@ private def box_from_vec(vec)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
private def new_key_bytes
|
|
||||||
Sodium::CryptoBox::SecretKey.new.to_slice
|
|
||||||
end
|
|
||||||
|
|
||||||
describe Sodium::CryptoBox::SecretKey do
|
describe Sodium::CryptoBox::SecretKey do
|
||||||
it "loads keys" do
|
it "loads keys" do
|
||||||
key1 = Sodium::CryptoBox::SecretKey.new
|
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.to_slice.should eq key2.to_slice
|
||||||
key1.public_key.to_slice.should eq key2.public_key.to_slice
|
key1.public_key.to_slice.should eq key2.public_key.to_slice
|
||||||
end
|
end
|
||||||
|
@ -15,7 +15,6 @@ module Sodium::Cipher
|
|||||||
def initialize(key : Crypto::Secret | Bytes, nonce = nil)
|
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
|
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)
|
@key = key.is_a?(Crypto::Secret) ? key : Sodium::SecureBuffer.new(key)
|
||||||
# self.key = key if key
|
|
||||||
self.nonce = nonce if nonce
|
self.nonce = nonce if nonce
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -116,9 +115,12 @@ module Sodium::Cipher
|
|||||||
def update(src : Bytes, dst : Bytes) : Bytes
|
def update(src : Bytes, dst : Bytes) : Bytes
|
||||||
if (k = @key) && (n = @nonce)
|
if (k = @key) && (n = @nonce)
|
||||||
raise ArgumentError.new("src and dst bytesize must be identical") if src.bytesize != dst.bytesize
|
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
|
|
||||||
|
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")
|
raise Sodium::Error.new("crypto_stream_{{ val.id }}_xor_ic")
|
||||||
end
|
end
|
||||||
|
end
|
||||||
@offset += src.bytesize
|
@offset += src.bytesize
|
||||||
dst
|
dst
|
||||||
else
|
else
|
||||||
|
@ -39,37 +39,42 @@ class Sodium::CryptoBox
|
|||||||
SEED_SIZE = LibSodium.crypto_box_seedbytes.to_i
|
SEED_SIZE = LibSodium.crypto_box_seedbytes.to_i
|
||||||
SEAL_SIZE = LibSodium.crypto_box_sealbytes.to_i
|
SEAL_SIZE = LibSodium.crypto_box_sealbytes.to_i
|
||||||
|
|
||||||
|
getter key : Crypto::Secret
|
||||||
getter public_key : PublicKey
|
getter public_key : PublicKey
|
||||||
|
|
||||||
# Returns key
|
# 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.
|
# Generate a new random secret/public key pair.
|
||||||
def initialize
|
def initialize
|
||||||
@sbuf = SecureBuffer.new KEY_SIZE
|
@key = SecureBuffer.new KEY_SIZE
|
||||||
@public_key = PublicKey.new
|
@public_key = PublicKey.new
|
||||||
if LibSodium.crypto_box_keypair(@public_key.to_slice, self.to_slice) != 0
|
@key.readwrite do |kslice|
|
||||||
|
if LibSodium.crypto_box_keypair(@public_key.to_slice, kslice) != 0
|
||||||
raise Sodium::Error.new("crypto_box_keypair")
|
raise Sodium::Error.new("crypto_box_keypair")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# Use existing secret and public keys.
|
# Use existing secret and public keys.
|
||||||
#
|
#
|
||||||
# Takes ownership of an existing key in a SecureBuffer.
|
# Takes ownership of an existing key in a SecureBuffer.
|
||||||
# Recomputes the public key from a secret key if missing.
|
# Recomputes the public key from a secret key if missing.
|
||||||
def initialize(@sbuf : SecureBuffer, pkey : Bytes? = nil)
|
def initialize(@key : Crypto::Secret, pkey : Bytes? = nil)
|
||||||
raise ArgumentError.new("Secret key must be #{KEY_SIZE} bytes, got #{@sbuf.bytesize}") if @sbuf.bytesize != KEY_SIZE
|
raise ArgumentError.new("Secret key must be #{KEY_SIZE} bytes, got #{@key.bytesize}") if @key.bytesize != KEY_SIZE
|
||||||
if pk = pkey
|
if pk = pkey
|
||||||
@public_key = PublicKey.new pk
|
@public_key = PublicKey.new pk
|
||||||
else
|
else
|
||||||
@public_key = PublicKey.new
|
@public_key = PublicKey.new
|
||||||
if LibSodium.crypto_scalarmult_base(@public_key.to_slice, self.to_slice) != 0
|
@key.readonly do |kslice|
|
||||||
|
if LibSodium.crypto_scalarmult_base(@public_key.to_slice, kslice) != 0
|
||||||
raise Sodium::Error.new("crypto_scalarmult_base")
|
raise Sodium::Error.new("crypto_scalarmult_base")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# Use existing secret and public keys.
|
# Use existing secret and public keys.
|
||||||
#
|
#
|
||||||
@ -77,46 +82,56 @@ class Sodium::CryptoBox
|
|||||||
# Recomputes the public key from a secret key if missing.
|
# Recomputes the public key from a secret key if missing.
|
||||||
def initialize(bytes : Bytes, pkey : Bytes? = nil)
|
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
|
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
|
if pk = pkey
|
||||||
@public_key = PublicKey.new pk
|
@public_key = PublicKey.new pk
|
||||||
else
|
else
|
||||||
@public_key = PublicKey.new
|
@public_key = PublicKey.new
|
||||||
if LibSodium.crypto_scalarmult_base(@public_key.to_slice, self.to_slice) != 0
|
@key.readonly do |kslice|
|
||||||
|
if LibSodium.crypto_scalarmult_base(@public_key.to_slice, kslice) != 0
|
||||||
raise Sodium::Error.new("crypto_scalarmult_base")
|
raise Sodium::Error.new("crypto_scalarmult_base")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# Derive a new secret/public key pair based on a consistent seed.
|
# Derive a new secret/public key pair based on a consistent seed.
|
||||||
#
|
#
|
||||||
# Copies seed to a SecureBuffer.
|
# Copies seed to a SecureBuffer.
|
||||||
def initialize(*, seed : Bytes, erase = false)
|
def initialize(*, seed : Bytes, erase = false)
|
||||||
raise ArgumentError.new("Secret sign seed must be #{SEED_SIZE}, got #{seed.bytesize}") unless seed.bytesize == SEED_SIZE
|
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
|
@public_key = PublicKey.new
|
||||||
if LibSodium.crypto_box_seed_keypair(@public_key.to_slice, self.to_slice, seed) != 0
|
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")
|
raise Sodium::Error.new("crypto_box_seed_keypair")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# Derive a new secret/public key pair based on a consistent seed.
|
# 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
|
raise ArgumentError.new("Secret sign seed must be #{SEED_SIZE}, got #{seed.bytesize}") unless seed.bytesize == SEED_SIZE
|
||||||
@seed = seed
|
@seed = seed
|
||||||
|
|
||||||
@sbuf = SecureBuffer.new KEY_SIZE
|
@key = SecureBuffer.new KEY_SIZE
|
||||||
@public_key = PublicKey.new
|
@public_key = PublicKey.new
|
||||||
if LibSodium.crypto_box_seed_keypair(@public_key.to_slice, self.to_slice, seed) != 0
|
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")
|
raise Sodium::Error.new("crypto_box_seed_keypair")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def seed
|
def seed : Crypto::Secret
|
||||||
# BUG: Generate seed if not set.
|
# BUG: Generate seed if not set.
|
||||||
@seed.not_nil!.to_slice
|
@seed.not_nil!
|
||||||
end
|
end
|
||||||
|
|
||||||
# Return a Box containing a precomputed shared secret for use with authenticated encryption/decryption.
|
# Return a Box containing a precomputed shared secret for use with authenticated encryption/decryption.
|
||||||
@ -159,9 +174,11 @@ class Sodium::CryptoBox
|
|||||||
dst ||= Bytes.new dst_size
|
dst ||= Bytes.new dst_size
|
||||||
raise ArgumentError.new("dst.bytesize must be src.bytesize - SEAL_SIZE, got #{dst.bytesize}") unless dst.bytesize == 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
|
@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")
|
raise Sodium::Error.new("crypto_box_seal_open")
|
||||||
end
|
end
|
||||||
|
end
|
||||||
dst
|
dst
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -62,15 +62,23 @@ module Sodium::Digest
|
|||||||
#
|
#
|
||||||
# `key`, `salt`, and `personal` are all optional. Many other libsodium bindings don't support them.
|
# `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.
|
# 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
|
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
|
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?
|
# 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
|
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
|
# raise ArgumentError.new("key smaller than KEY_SIZE_MIN(#{KEY_SIZE_MIN}), got #{k.bytesize}") if k.bytesize < KEY_SIZE_MIN
|
||||||
@key_size = k.bytesize
|
|
||||||
|
case k
|
||||||
|
in Bytes
|
||||||
k.copy_to @key.to_slice
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
if sa = salt
|
if sa = salt
|
||||||
|
Loading…
Reference in New Issue
Block a user