From 98c3a2bff4aea16ef4c00fc1bcb104020011735d Mon Sep 17 00:00:00 2001 From: Didactic Drunk <1479616+didactic-drunk@users.noreply.github.com> Date: Thu, 28 Apr 2022 01:54:46 -0700 Subject: [PATCH] Sign experimental combined signatures --- src/sodium/sign/public_key.cr | 37 +++++++++++++++++++++++------------ src/sodium/sign/secret_key.cr | 7 ++++--- 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/src/sodium/sign/public_key.cr b/src/sodium/sign/public_key.cr index 3a838cd..e21ad68 100644 --- a/src/sodium/sign/public_key.cr +++ b/src/sodium/sign/public_key.cr @@ -10,24 +10,40 @@ module Sodium # :nodoc: # Only used by SecretKey - def initialize - @bytes = Bytes.new(KEY_SIZE) + def self.new + new Bytes.new(KEY_SIZE) end + # Maintains reference to *bytes* def initialize(@bytes : Bytes) if bytes.bytesize != KEY_SIZE raise ArgumentError.new("Public key must be #{KEY_SIZE} bytes, got #{bytes.bytesize}") end end - # Verify signature made by `secret_key.sign(message)` + # Verify and return a copy of the message data # Raises on verification failure. - # - # WARNING: returns pointer to message within messagesig (zerocopy) - # If you reuse messagesig, `#dup` the returned message - # `secret_key.verify(messagesig).dup` @[Experimental] - def verify(messagesig) : Bytes + def verify(message) : Bytes + verify_zc(message).dup + end + + # Verify and return a String with the copied message data + # Raises on verification failure. + @[Experimental] + def verify_string(message) : String + String.new(verify_zc(message)) + end + + # Verify and return a zero copy reference to the message data + # Raises on verification failure. + @[Experimental] + def verify_zc(message) : Bytes + verify message.to_slice + end + + # :nodoc: + def verify_zc(messagesig) : Bytes messagesig = messagesig.to_slice bs = messagesig.bytesize raise Sodium::Error::VerificationFailed.new("message shorter than SIG_SIZE") unless bs >= SIG_SIZE @@ -39,11 +55,6 @@ module Sodium message end - @[Experimental] - def verify_string(messagesig) : String - String.new(verify(messagesig)) - end - # Verify signature made by `secret_key.sign_detached(message)` # Raises on verification failure. def verify_detached(message, sig) : Nil diff --git a/src/sodium/sign/secret_key.cr b/src/sodium/sign/secret_key.cr index 5d1938b..523039d 100644 --- a/src/sodium/sign/secret_key.cr +++ b/src/sodium/sign/secret_key.cr @@ -64,6 +64,7 @@ module Sodium end # Derive a new secret/public key pair based on a consistent seed. + # References passed SecureBuffer def initialize(*, seed : SecureBuffer) raise ArgumentError.new("Secret sign seed must be #{SEED_SIZE}, got #{seed.bytesize}") unless seed.bytesize == SEED_SIZE @seed = seed @@ -79,7 +80,7 @@ module Sodium end end - getter seed : Crypto::Secret? do + getter seed : Crypto::Secret do SecureBuffer.new(SEED_SIZE).tap do |seed_buf| @key.readonly do |kslice| seed_buf.readwrite do |seed_slice| @@ -92,8 +93,8 @@ module Sodium end # Signs message and returns a combined signature. - # Verify using `secret_key.public_key.verify(messagesig).dup` - # See warning about object reuse in `#verify` if you don't `#dup` + # Verify using `secret_key.public_key.verify(messagesig)` + # Other `verify` methods exist. Review the docs and choose carefully @[Experimental] def sign(message) : Bytes message = message.to_slice