Partial internal switch to Crypto::Secret API
parent
fca40d7764
commit
0e1b64b1bf
|
@ -7,15 +7,8 @@ require "../../../src/sodium/cipher/chalsa"
|
|||
it "xors" do
|
||||
data = Bytes.new(100)
|
||||
|
||||
cipher1 = Sodium::Cipher::{{ name.id }}.new
|
||||
cipher2 = Sodium::Cipher::{{ name.id }}.new
|
||||
|
||||
key = cipher1.random_key
|
||||
cipher2.key = key
|
||||
|
||||
nonce = cipher1.random_nonce
|
||||
cipher2.nonce = nonce
|
||||
|
||||
cipher1 = Sodium::Cipher::{{ name.id }}.random
|
||||
cipher2 = Sodium::Cipher::{{ name.id }}.new key: cipher1.key, nonce: cipher1.nonce
|
||||
|
||||
output = cipher1.update data
|
||||
output.should_not eq data # Verify encryption did something.
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
require "../spec_helper"
|
||||
require "../../src/sodium/secure_buffer"
|
||||
require "crypto-secret/test"
|
||||
|
||||
class FakeError < Exception
|
||||
end
|
||||
|
||||
test_secret_class Sodium::SecureBuffer
|
||||
|
||||
describe Sodium::SecureBuffer do
|
||||
it "allocates empty" do
|
||||
buf = Sodium::SecureBuffer.new 5
|
||||
|
@ -18,13 +21,6 @@ describe Sodium::SecureBuffer do
|
|||
buf.readwrite
|
||||
end
|
||||
|
||||
it "allocates random" do
|
||||
buf1 = Sodium::SecureBuffer.random 5
|
||||
buf2 = Sodium::SecureBuffer.random 5
|
||||
(buf1 == buf2).should be_false
|
||||
buf1.wipe
|
||||
end
|
||||
|
||||
it "copies and erases" do
|
||||
bytes = Bytes.new(5) { 1_u8 }
|
||||
|
||||
|
|
|
@ -20,40 +20,48 @@ detached_test_vectors = [
|
|||
|
||||
private def sign_from_vec(vec)
|
||||
seckey = Sodium::Sign::SecretKey.new seed: vec[:seed].hexbytes
|
||||
seckey.to_slice.should eq vec[:secret_key].hexbytes
|
||||
seckey.key.readonly do |sslice|
|
||||
sslice.should eq vec[:secret_key].hexbytes
|
||||
end
|
||||
seckey.public_key.to_slice.should eq vec[:public_key].hexbytes
|
||||
plaintext = vec[:plaintext].hexbytes
|
||||
signature = vec[:signature].hexbytes
|
||||
{seckey, plaintext, signature}
|
||||
end
|
||||
|
||||
private def new_sign_key_to_slice
|
||||
Sodium::Sign::SecretKey.new.to_slice
|
||||
end
|
||||
|
||||
describe Sodium::Sign::SecretKey do
|
||||
it "loads keys" do
|
||||
key1 = Sodium::Sign::SecretKey.new
|
||||
key2 = Sodium::Sign::SecretKey.new key1.to_slice, key1.public_key.to_slice
|
||||
key1.to_slice.should eq key2.to_slice
|
||||
key2 = key1.key.readonly do |kslice|
|
||||
Sodium::Sign::SecretKey.new kslice, 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::Sign::SecretKey.new
|
||||
key2 = Sodium::Sign::SecretKey.new key1.to_slice
|
||||
key1.to_slice.should eq key2.to_slice
|
||||
key2 = key1.key.readonly do |kslice|
|
||||
Sodium::Sign::SecretKey.new kslice
|
||||
end
|
||||
key1.key.should eq key2.key
|
||||
key1.public_key.to_slice.should eq key2.public_key.to_slice
|
||||
end
|
||||
|
||||
it "seed keys" do
|
||||
it "loading seed -> key -> seed" do
|
||||
seed = Bytes.new Sodium::Sign::SecretKey::SEED_SIZE
|
||||
key1 = Sodium::Sign::SecretKey.new seed: seed
|
||||
key2 = Sodium::Sign::SecretKey.new seed: Sodium::Sign::SecretKey.new(key1.to_slice).seed
|
||||
key1.to_slice.should eq key2.to_slice
|
||||
key2 = key1.key.readonly do |kslice|
|
||||
Sodium::Sign::SecretKey.new kslice
|
||||
end
|
||||
key3 = Sodium::Sign::SecretKey.new seed: key2.seed
|
||||
key1.key.should eq key2.key
|
||||
key1.key.should eq key3.key
|
||||
key1.public_key.to_slice.should eq key2.public_key.to_slice
|
||||
key1.public_key.to_slice.should eq key3.public_key.to_slice
|
||||
key1.seed.should eq seed
|
||||
key1.seed.should eq key2.seed
|
||||
key1.seed.should eq key3.seed
|
||||
end
|
||||
|
||||
it "signs and verifies" do
|
||||
|
|
|
@ -12,7 +12,7 @@ module Sodium::Cipher::Aead
|
|||
@key = SecureBuffer.random key_size
|
||||
end
|
||||
|
||||
# Initializes with a reference to an existing ky.
|
||||
# Initializes with a reference to an existing key.
|
||||
def initialize(@key : SecureBuffer)
|
||||
raise ArgumentError.new("key size mismatch, got #{@key.bytesize}, wanted #{key_size}") if @key.bytesize != key_size
|
||||
@key.readonly
|
||||
|
@ -30,6 +30,7 @@ module Sodium::Cipher::Aead
|
|||
offset = src.bytesize
|
||||
dst ||= Bytes.new (offset + mac_size)
|
||||
mac = dst[offset, mac_size]
|
||||
|
||||
_, _, nonce = encrypt_detached src.to_slice, dst[0, offset], mac: mac, nonce: nonce, additional: additional
|
||||
{dst, nonce}
|
||||
end
|
||||
|
@ -114,8 +115,8 @@ module Sodium::Cipher::Aead
|
|||
ad_len = additional.try(&.bytesize) || 0
|
||||
|
||||
nonce.used!
|
||||
@key.readonly do
|
||||
r = LibSodium.crypto_aead{{ val.id }}_encrypt_detached(dst, mac, out mac_len, src, src.bytesize, additional, ad_len, nil, nonce.to_slice, @key.to_slice)
|
||||
@key.readonly do |kslice|
|
||||
r = LibSodium.crypto_aead{{ val.id }}_encrypt_detached(dst, mac, out mac_len, src, src.bytesize, additional, ad_len, nil, nonce.to_slice, kslice)
|
||||
raise Sodium::Error.new("crypto_aead_{{ val.id }}_encrypt_detached") if r != 0
|
||||
raise Sodium::Error.new("crypto_aead_{{ val.id }}_encrypt_detached mac size mismatch") if mac_len != MAC_SIZE
|
||||
end
|
||||
|
@ -134,8 +135,9 @@ module Sodium::Cipher::Aead
|
|||
|
||||
ad_len = additional.try(&.bytesize) || 0
|
||||
|
||||
r = @key.readonly do
|
||||
LibSodium.crypto_aead{{ val.id }}_decrypt_detached(dst, nil, src, src.bytesize, mac, additional, ad_len, nonce.to_slice, @key.to_slice)
|
||||
r = @key.readonly do |kslice|
|
||||
LibSodium.crypto_aead{{ val.id }}_decrypt_detached(dst, nil, src, src.bytesize, mac, additional, ad_len, nonce.
|
||||
to_slice, kslice)
|
||||
end
|
||||
raise Sodium::Error::DecryptionFailed.new("crypto_aead_{{ val.id }}_decrypt_detached") if r != 0
|
||||
dst
|
||||
|
|
|
@ -6,27 +6,29 @@ module Sodium::Cipher
|
|||
#
|
||||
# What? They're both dance?
|
||||
abstract class Chalsa
|
||||
@key : Bytes | SecureBuffer | Nil
|
||||
@nonce : Bytes?
|
||||
getter key : Crypto::Secret
|
||||
getter! nonce : Bytes?
|
||||
|
||||
# Advanced usage. Don't touch.
|
||||
property offset = 0
|
||||
|
||||
getter! key
|
||||
getter! nonce
|
||||
|
||||
def initialize
|
||||
end
|
||||
|
||||
def initialize(key = nil, nonce = nil)
|
||||
self.key = key if key
|
||||
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
|
||||
|
||||
def key=(key : Bytes | SecureBuffer)
|
||||
@[Deprecated("Use constructor to set key")]
|
||||
def key=(key : Bytes | Crypto::Secret) : Crypto::Secret
|
||||
raise ArgumentError.new("key must be #{key_size} bytes, got #{key.bytesize}") if key.bytesize != key_size
|
||||
@key = key
|
||||
key
|
||||
@key = case key
|
||||
in Crypto::Secret
|
||||
key
|
||||
in Bytes
|
||||
Sodium::SecureBuffer.new key
|
||||
end
|
||||
@key.not_nil!
|
||||
end
|
||||
|
||||
def nonce=(nonce : Bytes)
|
||||
|
@ -35,6 +37,7 @@ module Sodium::Cipher
|
|||
nonce
|
||||
end
|
||||
|
||||
@[Deprecated("Use constructor to set key")]
|
||||
def random_key
|
||||
self.key = SecureBuffer.random key_size
|
||||
end
|
||||
|
@ -103,6 +106,10 @@ module Sodium::Cipher
|
|||
KEY_SIZE = LibSodium.crypto_stream_chacha20_{{ ietf ? "ietf_".id : "".id }}keybytes.to_i32
|
||||
NONCE_SIZE = LibSodium.crypto_stream_chacha20_{{ ietf ? "ietf_".id : "".id }}noncebytes.to_i32
|
||||
|
||||
def self.random
|
||||
new key: Sodium::SecureBuffer.random(KEY_SIZE), nonce: Random::Secure.random_bytes(NONCE_SIZE)
|
||||
end
|
||||
|
||||
# Xor's src with the cipher output and places in dst.
|
||||
#
|
||||
# src and dst may be the same object but should not overlap.
|
||||
|
|
|
@ -3,7 +3,7 @@ require "../secure_buffer"
|
|||
|
||||
module Sodium::Cipher
|
||||
abstract class SecretStream
|
||||
@state : SecureBuffer
|
||||
@state : Crypto::Secret
|
||||
@encrypt_decrypt = 0
|
||||
@initialized = false
|
||||
|
||||
|
@ -17,7 +17,7 @@ module Sodium::Cipher
|
|||
# * This property is set to nil after calling .update.
|
||||
property additional : Bytes? = nil
|
||||
|
||||
@key : Bytes | SecureBuffer | Nil = nil
|
||||
@key : Crypto::Secret | Nil = nil
|
||||
|
||||
def initialize
|
||||
@state = SecureBuffer.new state_size
|
||||
|
@ -31,15 +31,18 @@ module Sodium::Cipher
|
|||
@encrypt_decrypt = -1
|
||||
end
|
||||
|
||||
def key=(key : Bytes | SecureBuffer)
|
||||
def key=(key : Bytes | Crypto::Secret) : Crypto::Secret
|
||||
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
|
||||
key
|
||||
end
|
||||
|
||||
# Returns a random key in a SecureBuffer.
|
||||
def random_key
|
||||
self.key = SecureBuffer.random key_size
|
||||
def random_key : Crypto::Secret
|
||||
k = SecureBuffer.random key_size
|
||||
self.key = k
|
||||
k
|
||||
end
|
||||
|
||||
# Only used for encryption.
|
||||
|
@ -102,15 +105,21 @@ module Sodium::Cipher
|
|||
|
||||
case @encrypt_decrypt
|
||||
when 1
|
||||
if LibSodium.crypto_secretstream_{{ val.id }}_push(@state.to_slice, dst.to_slice, out dst_size, src, src.bytesize, ad, ad_size, @tag) != 0
|
||||
raise Sodium::Error.new("crypto_streamsecret_{{ val.id }}_xor_ic")
|
||||
dst_size = @state.readwrite do |stslice|
|
||||
if LibSodium.crypto_secretstream_{{ val.id }}_push(stslice, dst.to_slice, out dsize, src, src.bytesize, ad, ad_size, @tag) != 0
|
||||
raise Sodium::Error.new("crypto_streamsecret_{{ val.id }}_xor_ic")
|
||||
end
|
||||
dsize
|
||||
end
|
||||
@tag = 0
|
||||
@additional = nil
|
||||
dst[0, dst_size]
|
||||
when -1
|
||||
if LibSodium.crypto_secretstream_{{ val.id }}_pull(@state.to_slice, dst.to_slice, out dst_size2, out @tag, src, src.bytesize, ad, ad_size) != 0
|
||||
raise Sodium::Error.new("crypto_streamsecret_{{ val.id }}_xor_ic")
|
||||
dst_size2 = @state.readwrite do |stslice|
|
||||
if LibSodium.crypto_secretstream_{{ val.id }}_pull(stslice, dst.to_slice, out dsize2, out @tag, src, src.bytesize, ad, ad_size) != 0
|
||||
raise Sodium::Error.new("crypto_streamsecret_{{ val.id }}_xor_ic")
|
||||
end
|
||||
dsize2
|
||||
end
|
||||
@additional = nil
|
||||
dst[0, dst_size2]
|
||||
|
@ -123,19 +132,25 @@ module Sodium::Cipher
|
|||
raise Sodium::Error.new("can't initialize more than once") if @initialized
|
||||
|
||||
if k = @key
|
||||
case @encrypt_decrypt
|
||||
when 1
|
||||
if LibSodium.crypto_secretstream_xchacha20poly1305_init_push(@state.to_slice, header_buf.to_slice, k.to_slice) != 0
|
||||
raise Sodium::Error.new("crypto_secretstream_xchacha20poly1305_init_push")
|
||||
k.readonly do |kslice|
|
||||
case @encrypt_decrypt
|
||||
when 1
|
||||
@state.readwrite do |stslice|
|
||||
if LibSodium.crypto_secretstream_xchacha20poly1305_init_push(stslice, header_buf.to_slice, kslice) != 0
|
||||
raise Sodium::Error.new("crypto_secretstream_xchacha20poly1305_init_push")
|
||||
end
|
||||
end
|
||||
when -1
|
||||
@state.readwrite do |stslice|
|
||||
if LibSodium.crypto_secretstream_xchacha20poly1305_init_pull(stslice, header_buf.to_slice, kslice) != 0
|
||||
raise Sodium::Error.new("crypto_secretstream_xchacha20poly1305_init_push")
|
||||
end
|
||||
end
|
||||
when 0
|
||||
raise Sodium::Error.new("must call .encrypt or .decrypt first")
|
||||
else
|
||||
abort "invalid encrypt_decrypt state #{@encrypt_decrypt}"
|
||||
end
|
||||
when -1
|
||||
if LibSodium.crypto_secretstream_xchacha20poly1305_init_pull(@state.to_slice, header_buf.to_slice, k.to_slice) != 0
|
||||
raise Sodium::Error.new("crypto_secretstream_xchacha20poly1305_init_push")
|
||||
end
|
||||
when 0
|
||||
raise Sodium::Error.new("must call .encrypt or .decrypt first")
|
||||
else
|
||||
abort "invalid encrypt_decrypt state #{@encrypt_decrypt}"
|
||||
end
|
||||
else
|
||||
raise Sodium::Error.new("must set an encryption/decryption key")
|
||||
|
|
|
@ -38,6 +38,8 @@ module Sodium
|
|||
# Returns key
|
||||
delegate_to_slice to: @sbuf
|
||||
|
||||
@sbuf : Crypto::Secret
|
||||
|
||||
# Use an existing KDF key.
|
||||
#
|
||||
# * Copies key to a new SecureBuffer
|
||||
|
@ -50,8 +52,8 @@ module Sodium
|
|||
@sbuf = SecureBuffer.new(bytes, erase).noaccess
|
||||
end
|
||||
|
||||
# Use an existing KDF SecureBuffer key.
|
||||
def initialize(@sbuf : SecureBuffer)
|
||||
# Use an existing KDF Crypto::Secret key.
|
||||
def initialize(@sbuf : Crypto::Secret)
|
||||
if @sbuf.bytesize != KEY_SIZE
|
||||
raise ArgumentError.new("bytes must be #{KEY_SIZE}, got #{sbuf.bytesize}")
|
||||
end
|
||||
|
|
|
@ -25,7 +25,7 @@ module Sodium::Password
|
|||
end
|
||||
|
||||
# :nodoc:
|
||||
def derive_key(key : SecureBuffer, pass : Bytes | String, *, salt : Bytes? = nil) : Nil
|
||||
def derive_key(key : Crypto::Secret, pass : Bytes | String, *, salt : Bytes? = nil) : Nil
|
||||
m = mode || raise ArgumentError.new("mode not set")
|
||||
|
||||
salt ||= @salt
|
||||
|
@ -33,8 +33,10 @@ module Sodium::Password
|
|||
salt = salt.not_nil!
|
||||
raise "salt expected #{SALT_SIZE} bytes, got #{salt.bytesize} " if salt.bytesize != SALT_SIZE
|
||||
|
||||
if LibSodium.crypto_pwhash(key.to_slice, key.bytesize, pass.to_slice, pass.bytesize, salt.to_slice, @ops, @mem, m) != 0
|
||||
raise Sodium::Error.new("crypto_pwhash")
|
||||
key.readwrite do |key_slice|
|
||||
if LibSodium.crypto_pwhash(key_slice, key_slice.bytesize, pass.to_slice, pass.bytesize, salt.to_slice, @ops, @mem, m) != 0
|
||||
raise Sodium::Error.new("crypto_pwhash")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -19,19 +19,19 @@ module Sodium
|
|||
NONCE_SIZE = LibSodium.crypto_secretbox_noncebytes.to_i
|
||||
MAC_SIZE = LibSodium.crypto_secretbox_macbytes.to_i
|
||||
|
||||
# Returns key
|
||||
@[Deprecated("Use `key.readonly` or `key.readwrite`")]
|
||||
delegate_to_slice to: @key
|
||||
|
||||
# Encryption key
|
||||
getter key : SecureBuffer
|
||||
getter key : Crypto::Secret
|
||||
|
||||
# Generate a new random key held in a SecureBuffer.
|
||||
def initialize
|
||||
@key = SecureBuffer.random KEY_SIZE
|
||||
end
|
||||
|
||||
# Use an existing SecureBuffer.
|
||||
def initialize(@key : SecureBuffer)
|
||||
# Use an existing Crypto::Secret.
|
||||
def initialize(@key : Crypto::Secret)
|
||||
if @key.bytesize != KEY_SIZE
|
||||
raise ArgumentError.new("Secret key must be #{KEY_SIZE} bytes, got #{@key.bytesize}")
|
||||
end
|
||||
|
@ -91,8 +91,8 @@ module Sodium
|
|||
dst ||= Bytes.new dst_size
|
||||
raise ArgumentError.new("dst.bytesize must be src.bytesize - MAC_SIZE, got #{dst.bytesize}") if dst.bytesize != (src.bytesize - MAC_SIZE)
|
||||
|
||||
r = @key.readonly do
|
||||
LibSodium.crypto_secretbox_open_easy(dst, src, src.bytesize, nonce.to_slice, @key)
|
||||
r = @key.readonly do |kslice|
|
||||
LibSodium.crypto_secretbox_open_easy(dst, src, src.bytesize, nonce.to_slice, kslice)
|
||||
end
|
||||
raise Sodium::Error::DecryptionFailed.new("crypto_secretbox_easy") if r != 0
|
||||
dst
|
||||
|
|
|
@ -10,8 +10,6 @@ module Sodium
|
|||
class SecureBuffer
|
||||
include Crypto::Secret::Stateful
|
||||
|
||||
# @state = State::Readwrite
|
||||
|
||||
getter bytesize : Int32
|
||||
|
||||
def initialize(@bytesize : Int32)
|
||||
|
@ -31,13 +29,13 @@ module Sodium
|
|||
|
||||
# :nodoc:
|
||||
# For .dup
|
||||
def initialize(sbuf : self)
|
||||
def initialize(sbuf : Crypto::Secret)
|
||||
initialize sbuf.bytesize
|
||||
|
||||
# Maybe not thread safe
|
||||
sbuf.readonly do |s1|
|
||||
self.to_slice do |s2|
|
||||
s1.copy_to s2.to_slice
|
||||
sbuf.readonly do |sslice|
|
||||
readwrite do |dslice|
|
||||
s1.copy_to s2
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -63,8 +61,9 @@ module Sodium
|
|||
Slice(UInt8).new @ptr, @bytesize
|
||||
end
|
||||
|
||||
def to_slice(& : Bytes -> Nil)
|
||||
yield Bytes.new @ptr, @bytesize
|
||||
protected def to_slice(& : Bytes -> Nil)
|
||||
ro = @state < State::Readonly
|
||||
yield Bytes.new(@ptr, @bytesize, read_only: ro)
|
||||
end
|
||||
|
||||
# :nodoc:
|
||||
|
@ -72,11 +71,6 @@ module Sodium
|
|||
@ptr
|
||||
end
|
||||
|
||||
# WARNING: Not thread safe unless this object is readonly or readwrite
|
||||
def dup
|
||||
self.class.new self
|
||||
end
|
||||
|
||||
protected def readwrite_impl : Nil
|
||||
if LibSodium.sodium_mprotect_readwrite(@ptr) != 0
|
||||
raise "sodium_mprotect_readwrite"
|
||||
|
|
|
@ -20,15 +20,20 @@ module Sodium
|
|||
|
||||
getter public_key : PublicKey
|
||||
|
||||
# Returns key
|
||||
delegate_to_slice to: @sbuf
|
||||
@[Deprecated("Switching to Crypto::Secret. Use `key.readonly` or `key.readwrite`")]
|
||||
delegate_to_slice to: @key
|
||||
|
||||
getter key : Crypto::Secret
|
||||
@seed : Crypto::Secret?
|
||||
|
||||
# Generates 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_sign_keypair(@public_key.to_slice, self.to_slice) != 0
|
||||
raise Sodium::Error.new("crypto_sign_keypair")
|
||||
@key.readwrite do |kslice|
|
||||
if LibSodium.crypto_sign_keypair(@public_key.to_slice, kslice) != 0
|
||||
raise Sodium::Error.new("crypto_sign_keypair")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -38,13 +43,15 @@ module Sodium
|
|||
def initialize(bytes : Bytes, pkey : Bytes? = nil, *, erase = false)
|
||||
raise ArgumentError.new("Secret sign key must be #{KEY_SIZE}, got #{bytes.bytesize}") unless bytes.bytesize == KEY_SIZE
|
||||
|
||||
@sbuf = SecureBuffer.new bytes, erase: erase
|
||||
@key = SecureBuffer.new bytes, erase: erase
|
||||
if pk = pkey
|
||||
@public_key = PublicKey.new pk
|
||||
else
|
||||
@public_key = PublicKey.new
|
||||
if LibSodium.crypto_sign_ed25519_sk_to_pk(@public_key.to_slice, self.to_slice) != 0
|
||||
raise Sodium::Error.new("crypto_sign_ed25519_sk_to_pk")
|
||||
@key.readwrite do |kslice|
|
||||
if LibSodium.crypto_sign_ed25519_sk_to_pk(@public_key.to_slice, kslice) != 0
|
||||
raise Sodium::Error.new("crypto_sign_ed25519_sk_to_pk")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -61,17 +68,25 @@ module Sodium
|
|||
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_sign_seed_keypair(@public_key.to_slice, self.to_slice, seed.to_slice) != 0
|
||||
raise Sodium::Error.new("crypto_sign_seed_keypair")
|
||||
seed.readonly do |seed_slice|
|
||||
@key.readwrite do |kslice|
|
||||
if LibSodium.crypto_sign_seed_keypair(@public_key.to_slice, kslice, seed_slice) != 0
|
||||
raise Sodium::Error.new("crypto_sign_seed_keypair")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
getter seed : SecureBuffer? do
|
||||
SecureBuffer.new(SEED_SIZE).tap do |s|
|
||||
if LibSodium.crypto_sign_ed25519_sk_to_seed(s.to_slice, self.to_slice) != 0
|
||||
raise Sodium::Error.new("crypto_sign_ed25519_sk_to_seed")
|
||||
getter seed : Crypto::Secret? do
|
||||
SecureBuffer.new(SEED_SIZE).tap do |seed_buf|
|
||||
@key.readonly do |kslice|
|
||||
seed_buf.readwrite do |seed_slice|
|
||||
if LibSodium.crypto_sign_ed25519_sk_to_seed(seed_slice, kslice) != 0
|
||||
raise Sodium::Error.new("crypto_sign_ed25519_sk_to_seed")
|
||||
end
|
||||
end
|
||||
end
|
||||
end.readonly
|
||||
end
|
||||
|
@ -84,17 +99,24 @@ module Sodium
|
|||
|
||||
def sign_detached(message : Bytes)
|
||||
sig = Bytes.new(SIG_SIZE)
|
||||
if LibSodium.crypto_sign_detached(sig, out sig_len, message, message.bytesize, self.to_slice) != 0
|
||||
raise Error.new("crypto_sign_detached")
|
||||
@key.readonly do |kslice|
|
||||
if LibSodium.crypto_sign_detached(sig, out sig_len, message, message.bytesize, kslice) != 0
|
||||
raise Error.new("crypto_sign_detached")
|
||||
end
|
||||
raise "expected #{sig.bytesize}, got #{sig_len}" if sig.bytesize != sig_len
|
||||
end
|
||||
sig
|
||||
end
|
||||
|
||||
def to_curve25519 : CryptoBox::SecretKey
|
||||
key = SecureBuffer.new CryptoBox::SecretKey::KEY_SIZE
|
||||
LibSodium.crypto_sign_ed25519_sk_to_curve25519 key.to_slice, @sbuf.to_slice
|
||||
key.readonly
|
||||
CryptoBox::SecretKey.new key
|
||||
sbuf = SecureBuffer.new CryptoBox::SecretKey::KEY_SIZE
|
||||
sbuf.readwrite do |sbuf_slice|
|
||||
@key.readonly do |kslice|
|
||||
LibSodium.crypto_sign_ed25519_sk_to_curve25519 sbuf_slice, kslice
|
||||
end
|
||||
end
|
||||
sbuf.readonly
|
||||
CryptoBox::SecretKey.new sbuf
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue