From 9247d739ac127eaa5abc54064095c81cbff3daaa Mon Sep 17 00:00:00 2001 From: Didactic Drunk <1479616+didactic-drunk@users.noreply.github.com> Date: Sat, 27 Jul 2019 00:35:27 -0700 Subject: [PATCH] Allow dup of Sodium::SecureBuffer. Sodium::Digest::Blake2b use to_slice internally. --- benchmarks/crypto_box.cr | 43 ++++++++++++++++++++++++++++++++++++ src/sodium/digest/blake2b.cr | 10 +++++---- src/sodium/secure_buffer.cr | 14 +++++++++++- 3 files changed, 62 insertions(+), 5 deletions(-) create mode 100644 benchmarks/crypto_box.cr diff --git a/benchmarks/crypto_box.cr b/benchmarks/crypto_box.cr new file mode 100644 index 0000000..8b3c2a9 --- /dev/null +++ b/benchmarks/crypto_box.cr @@ -0,0 +1,43 @@ +require "benchmark" +require "../src/sodium/crypto_box" + +bob = Sodium::CryptoBox::SecretKey.new +alice = Sodium::CryptoBox::SecretKey.new +to_alice = bob.box alice.public_key +from_bob = alice.box bob.public_key + +nonce = Sodium::Nonce.new + +sizes = [256, 65536, 1024*1024] +dbufs1 = sizes.map { |size| Bytes.new(size) }.to_a +ebufs1 = sizes.map { |size| Bytes.new(size + Sodium::CryptoBox::MAC_SIZE) }.to_a +dbufs2 = sizes.map { |size| Bytes.new(size) }.to_a +ebufs2 = sizes.map { |size| Bytes.new(size + Sodium::CryptoBox::PublicKey::SEAL_SIZE) }.to_a + +Benchmark.ips do |bm| + sizes.each_with_index do |size, i| + dbuf = dbufs1[i] + ebuf = ebufs1[i] + + bm.report "box encrypt #{size}" do + to_alice.encrypt_easy dbuf, ebuf, nonce: nonce + end + + bm.report "box decrypt #{size}" do + from_bob.decrypt_easy ebuf, dbuf, nonce: nonce + end + end + + sizes.each_with_index do |size, i| + dbuf = dbufs2[i] + ebuf = ebufs2[i] + + bm.report "anon encrypt #{size}" do + alice.public_key.encrypt dbuf, ebuf + end + + bm.report "anon decrypt #{size}" do + alice.decrypt ebuf, dbuf + end + end +end diff --git a/src/sodium/digest/blake2b.cr b/src/sodium/digest/blake2b.cr index 22caee2..69e8487 100644 --- a/src/sodium/digest/blake2b.cr +++ b/src/sodium/digest/blake2b.cr @@ -1,5 +1,6 @@ require "../lib_sodium" require "../wipe" +require "../secure_buffer" require "openssl/digest/digest_base" module Sodium::Digest @@ -76,13 +77,13 @@ module Sodium::Digest salt = @salt.to_unsafe personal = @personal.to_unsafe - if LibSodium.crypto_generichash_blake2b_init_salt_personal(@state, key, @key_size, @digest_size, salt, personal) != 0 + if LibSodium.crypto_generichash_blake2b_init_salt_personal(@state.to_slice, key, @key_size, @digest_size, salt, personal) != 0 raise Sodium::Error.new("blake2b_init_key_salt_personal") end end def update(data : Bytes) - if LibSodium.crypto_generichash_blake2b_update(@state, data, data.bytesize) != 0 + if LibSodium.crypto_generichash_blake2b_update(@state.to_slice, data, data.bytesize) != 0 raise Sodium::Error.new("crypto_generichash_blake2b_update") end @@ -100,8 +101,9 @@ module Sodium::Digest # Destructive operation. Assumes you know what you are doing. # Use .digest or .hexdigest instead. def finish(dst : Bytes) : Bytes - if LibSodium.crypto_generichash_blake2b_final(@state, dst, dst.bytesize) != 0 - raise Sodium::Error.new("crypto_generichash_blake2b_final") + ret = LibSodium.crypto_generichash_blake2b_final(@state.to_slice, dst, dst.bytesize) + if ret != 0 + raise Sodium::Error.new("crypto_generichash_blake2b_final #{ret.inspect}") end dst diff --git a/src/sodium/secure_buffer.cr b/src/sodium/secure_buffer.cr index b3fda58..dbc1fa4 100644 --- a/src/sodium/secure_buffer.cr +++ b/src/sodium/secure_buffer.cr @@ -5,7 +5,7 @@ module Sodium class SecureBuffer getter bytesize - delegate :+, :[], to: to_slice + delegate :+, :[], :[]=, to: to_slice # Allocate guarded memory using [sodium_malloc](https://libsodium.gitbook.io/doc/memory_management) def initialize(@bytesize : Int32) @@ -28,6 +28,14 @@ module Sodium readonly end + # :nodoc: + # For .dup + def initialize(sbuf : self) + initialize sbuf.bytesize + sbuf.to_slice.copy_to self.to_slice + readonly + end + def wipe readwrite Sodium.memzero self.to_slice @@ -45,6 +53,10 @@ module Sodium @ptr end + def dup + self.class.new self + end + # Makes a region allocated using sodium_malloc() or sodium_allocarray() inaccessible. It cannot be read or written, but the data are preserved. def noaccess if LibSodium.sodium_mprotect_noaccess(@ptr) != 0