From 695bad83471111ba18894a93d41795eeb5c1e0bc Mon Sep 17 00:00:00 2001 From: Didactic Drunk <1479616+didactic-drunk@users.noreply.github.com> Date: Tue, 15 Jun 2021 15:42:01 -0700 Subject: [PATCH] Add default dup implementation --- spec/crypto_secret_spec.cr | 11 +++--- src/crypto-secret/secret.cr | 11 ++++++ src/crypto-secret/test.cr | 78 +++++++++++++++++++++++++++++++++++++ 3 files changed, 95 insertions(+), 5 deletions(-) create mode 100644 src/crypto-secret/test.cr diff --git a/spec/crypto_secret_spec.cr b/spec/crypto_secret_spec.cr index 72f5072..ee47810 100644 --- a/spec/crypto_secret_spec.cr +++ b/spec/crypto_secret_spec.cr @@ -1,7 +1,8 @@ require "./spec_helper" +require "../src/crypto-secret/test" +require "../src/crypto-secret/not" +require "../src/crypto-secret/bidet" + +test_secret_class Crypto::Secret::Not +test_secret_class Crypto::Secret::Bidet -describe Crypto::Secret do - pending "works" do - false.should eq(true) - end -end diff --git a/src/crypto-secret/secret.cr b/src/crypto-secret/secret.cr index fc48a23..f6b21c1 100644 --- a/src/crypto-secret/secret.cr +++ b/src/crypto-secret/secret.cr @@ -75,6 +75,17 @@ module Crypto::Secret io << self.class.to_s << "(***SECRET***)" end + def dup + readonly do |sslice| + obj = self.class.new sslice.bytesize + obj.readwrite do |dslice| + sslice.copy_to dslice + end + # TODO: copy state if possible + obj + end + end + abstract def readwrite abstract def readonly abstract def noaccess diff --git a/src/crypto-secret/test.cr b/src/crypto-secret/test.cr new file mode 100644 index 0000000..6582319 --- /dev/null +++ b/src/crypto-secret/test.cr @@ -0,0 +1,78 @@ +macro test_secret_class(to sclass) + describe {{sclass}} do + sclass = {{sclass}} + + it "returns a random secret" do + secret1 = sclass.new 8 + secret2 = sclass.random 8 + secret1.should_not eq secret2 + end + + it "copies & wipes on .move" do + ksize = 4 + key1 = Bytes.new ksize + key1[1] = 1_u8 + key2 = key1.dup + secret = sclass.move_from key2 + + secret.readonly { |s| s.should eq key1 } + key2.should eq Bytes.new(ksize) + end + + it "copies & preserves on .copy" do + ksize = 2 + key1 = Bytes.new ksize + key1[1] = 1_u8 + key2 = key1.dup + secret = sclass.copy_from key2 + + secret.readonly { |s| s.should eq key1 } + key2.should eq key1 + end + + it "compares with ==" do + ksize = 32 + key = Bytes.new ksize + key[1] = 1_u8 + + secret1 = sclass.copy_from key + secret1.readonly { |s| s.should eq key } + + secret2 = sclass.copy_from key + + (secret1 == secret2).should be_true + secret1.readonly do |s1| + secret2.readonly do |s2| + (s1 == s2).should be_true + end + end + end + + it "dups" do + ksize = 2 + key = Bytes.new ksize + key[1] = 1_u8 + + secret1 = sclass.copy_from key + secret2 = secret1.dup + (secret1 == secret2).should be_true + end + + pending "check dup state" { } + + it "bytesize" do + secret = sclass.new 5 + secret.bytesize.should eq 5 + secret.readonly { |s| s.bytesize.should eq 5 } + end + + it "doesn't leak key material when inspecting" do + secret = sclass.new 5 + + secret.to_s.should_not match /Bytes|Slice|StaticArray/ + secret.inspect.should_not match /Bytes|Slice|StaticArray/ + + secret.inspect.should match /\(\*\*\*SECRET\*\*\*\)$/ + end + end +end