diff --git a/spec/crypto_secret_spec.cr b/spec/crypto_secret_spec.cr index 26bfff1..051b2ed 100644 --- a/spec/crypto_secret_spec.cr +++ b/spec/crypto_secret_spec.cr @@ -8,8 +8,24 @@ test_secret_class Crypto::Secret::Bidet describe Crypto::Secret do it ".for" do [:kgk, :key, :data, :not].each do |sym| - secret = Crypto::Secret.for sym, 2 + secret = Crypto::Secret.for 2, sym secret.bytesize.should eq 2 end end + + it ".for fallback" do + secret = Crypto::Secret.for 2, :a, :b, :not + secret.bytesize.should eq 2 + end + + it ".for missing" do + expect_raises(KeyError) do + Crypto::Secret.for 2, :a + end + end + + it ".random" do + secret = Crypto::Secret.random 2, :a, :b, :not + secret.bytesize.should eq 2 + end end diff --git a/src/crypto-secret/secret.cr b/src/crypto-secret/secret.cr index 79eae42..c11bf8b 100644 --- a/src/crypto-secret/secret.cr +++ b/src/crypto-secret/secret.cr @@ -31,7 +31,9 @@ abstract class Crypto::Secret Readwrite end - extend ClassMethods + macro inherited + extend ClassMethods + end def self.new(size : Int32) raise NotImplementedError.new("workaround for lack of `abstract def self.new`") @@ -41,12 +43,23 @@ abstract class Crypto::Secret secret end - def self.for(use : Symbol, size : Int32) : Crypto::Secret - for(use).new(size) + + def self.for(size : Int32, *uses) : Crypto::Secret + for(*uses).new(size) end - def self.for(use : Symbol) : Crypto::Secret.class - Config::USES[use] + def self.for(size : Int32, secret : Crypto::Secret) : Crypto::Secret + raise ArgumentError.new("") unless size == secret.bytesize + secret + end + + def self.for(*uses) : Crypto::Secret.class + uses.each do |use| + if klass = Config::USES[use]? + return klass + end + end + raise KeyError.new("missing #{uses}, have #{Config::USES.keys}") end # For debugging. Leaks the secret