Skip to content

Commit

Permalink
Sign:
Browse files Browse the repository at this point in the history
  Add `.copy_from` `.move_from` instead of *erase*
  Prefer `.random`
  Deprecate old `.initialize`
  • Loading branch information
didactic-drunk committed Apr 28, 2022
1 parent 98c3a2b commit f036295
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 38 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Crystal bindings for the [libsodium API](https://libsodium.gitbook.io/doc/)
- [Public-Key Cryptography](https://libsodium.gitbook.io/doc/public-key_cryptography)
- [x][Crypto Box Easy](https://libsodium.gitbook.io/doc/public-key_cryptography/authenticated_encryption)
- [x] [Sealed Box](https://libsodium.gitbook.io/doc/public-key_cryptography/sealed_boxes)
- [ ] [Combined Signatures](https://libsodium.gitbook.io/doc/public-key_cryptography/public-key_signatures)
- [x] [Combined Signatures](https://libsodium.gitbook.io/doc/public-key_cryptography/public-key_signatures)
- [x][Detached Signatures](https://libsodium.gitbook.io/doc/public-key_cryptography/public-key_signatures)
- [ ] [Pre-hashed Signatures](https://libsodium.gitbook.io/doc/public-key_cryptography/public-key_signatures)
- [Secret-Key Cryptography](https://libsodium.gitbook.io/doc/secret-key_cryptography)
Expand Down
23 changes: 7 additions & 16 deletions spec/sodium/sign/secret_key_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,9 @@ end

describe Sodium::Sign::SecretKey do
it "loads keys" do
key1 = Sodium::Sign::SecretKey.new
key1 = Sodium::Sign::SecretKey.random
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 = key1.key.readonly do |kslice|
Sodium::Sign::SecretKey.new kslice
Sodium::Sign::SecretKey.copy_from kslice
end
key1.key.should eq key2.key
key1.public_key.to_slice.should eq key2.public_key.to_slice
Expand All @@ -52,7 +43,7 @@ describe Sodium::Sign::SecretKey do
seed = Bytes.new Sodium::Sign::SecretKey::SEED_SIZE
key1 = Sodium::Sign::SecretKey.new seed: seed
key2 = key1.key.readonly do |kslice|
Sodium::Sign::SecretKey.new kslice
Sodium::Sign::SecretKey.copy_from kslice
end
key3 = Sodium::Sign::SecretKey.new seed: key2.seed
key1.key.should eq key2.key
Expand All @@ -66,7 +57,7 @@ describe Sodium::Sign::SecretKey do

it "signs and verifies combined" do
message = "foo"
skey = Sodium::Sign::SecretKey.new
skey = Sodium::Sign::SecretKey.random
sig = skey.sign message

message2 = skey.public_key.verify_string sig
Expand All @@ -75,15 +66,15 @@ describe Sodium::Sign::SecretKey do

it "signs and verifies detached" do
message = "foo"
skey = Sodium::Sign::SecretKey.new
skey = Sodium::Sign::SecretKey.random
sig = skey.sign_detached message

skey.public_key.verify_detached message, sig
end

it "signs and fails" do
message = "foo"
skey = Sodium::Sign::SecretKey.new
skey = Sodium::Sign::SecretKey.random
sig = skey.sign_detached message

expect_raises Sodium::Error::VerificationFailed do
Expand All @@ -93,7 +84,7 @@ describe Sodium::Sign::SecretKey do

it "to_curve25519" do
message = "foo"
sskey = Sodium::Sign::SecretKey.new
sskey = Sodium::Sign::SecretKey.random
cskey = sskey.to_curve25519

spkey = sskey.public_key
Expand Down
68 changes: 47 additions & 21 deletions src/sodium/sign/secret_key.cr
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ module Sodium
SIG_SIZE = LibSodium.crypto_sign_bytes.to_i
SEED_SIZE = LibSodium.crypto_sign_seedbytes.to_i

getter public_key : PublicKey

@[Deprecated("Switching to Crypto::Secret. Use `key.readonly` or `key.readwrite`")]
delegate_to_slice to: @key

getter key : Crypto::Secret
getter public_key = PublicKey.new

@seed : Crypto::Secret?

# Generates a new random secret/public key pair.
Expand All @@ -37,40 +37,54 @@ module Sodium
end
end

# Use existing secret and public keys.
# Copies secret key to a SecureBuffer.
# Recomputes the public key from a secret key if missing.
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

@key = SecureBuffer.new bytes, erase: erase
if pk = pkey
@public_key = PublicKey.new pk
# Copies secret *key* to a `SecureBuffer`
def self.copy_from(key : Bytes)
new SecureBuffer.copy_from(key)
end

# Copies secret *key* to a `SecureBuffer`
# Erases *key*
def self.move_from(key : Bytes)
new SecureBuffer.move_from(key)
end

# Copies secret *key* to a `SecureBuffer`
@[Deprecated("Use .copy_from or .move_from")]
def self.new(key : Bytes, erase = false)
raise ArgumentError.new("Secret sign key must be #{KEY_SIZE}, got #{key.bytesize}") unless key.bytesize == KEY_SIZE

if erase
move_from key
else
@public_key = PublicKey.new
@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
copy_from key
end
end

# References existing Crypto::Secret
def initialize(@key : Crypto::Secret)
# Set @public_key
@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

# Derive a new secret/public key pair based on a consistent seed.
# Copies seed to a SecureBuffer.
def initialize(*, seed : Bytes, erase = false)
# Copies seed to a `SecureBuffer`
def self.new(*, seed : Bytes, erase = false)
raise ArgumentError.new("Secret sign seed must be #{SEED_SIZE}, got #{seed.bytesize}") unless seed.bytesize == SEED_SIZE
initialize(seed: SecureBuffer.new(seed, erase: erase))
new(seed: SecureBuffer.new(seed, erase: erase))
end

# Derive a new secret/public key pair based on a consistent seed.
# References passed SecureBuffer
def initialize(*, seed : SecureBuffer)
# References passed `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

@key = SecureBuffer.new KEY_SIZE
@public_key = PublicKey.new
seed.readonly do |seed_slice|
@key.readwrite do |kslice|
if LibSodium.crypto_sign_seed_keypair(@public_key.to_slice, kslice, seed_slice) != 0
Expand All @@ -80,6 +94,18 @@ module Sodium
end
end

# :nodoc:
def initialize(random : Bool)
@key = SecureBuffer.new KEY_SIZE
@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



getter seed : Crypto::Secret do
SecureBuffer.new(SEED_SIZE).tap do |seed_buf|
@key.readonly do |kslice|
Expand Down

0 comments on commit f036295

Please sign in to comment.