Secret interface changes

This commit is contained in:
Didactic Drunk 2021-06-13 18:54:45 -07:00
parent f6737a766f
commit 46f53c8e89
3 changed files with 62 additions and 12 deletions

View File

@ -8,11 +8,15 @@ describe Crypto::Secret::Not do
key[1] = 1_u8 key[1] = 1_u8
secret1 = Crypto::Secret::Not.new key.dup secret1 = Crypto::Secret::Not.new key.dup
secret1.to_slice.should eq key secret1.to_slice { |s| s.should eq key }
secret2 = Crypto::Secret::Not.new key.dup secret2 = Crypto::Secret::Not.new key.dup
(secret1 == secret2).should be_true (secret1 == secret2).should be_true
(secret1 == secret2.to_slice).should be_true secret1.to_slice do |s1|
secret2.to_slice do |s2|
(s1 == s2).should be_true
end
end
end end
end end

View File

@ -13,4 +13,8 @@ struct Crypto::Secret::Not
def to_slice : Bytes def to_slice : Bytes
@bytes @bytes
end end
delegate_to_slice @bytes
delegate_to_bytesize @bytes
end end

View File

@ -4,59 +4,101 @@ require "crypto/subtle"
# #
# **Only for direct use by cryptographic library authors** # **Only for direct use by cryptographic library authors**
# #
# For all other applications use a preexisting class that include `Crypto::Secret` # For all other applications use a preexisting class that includes `Crypto::Secret`
@[Experimental] @[Experimental]
module Crypto::Secret module Crypto::Secret
abstract def to_slice : Bytes class Error < Exception
class KeyWiped < Error
end
end
def readwrite def readwrite
end end
# Yields a Slice that is readable and writable
#
# `slice` is only available within the block
#
# Not thread safe
def readwrite def readwrite
yield to_slice do |slice|
yield slice
end
end end
def readonly def readonly
end end
# Yields a Slice that is readable possibly writable depending on the prior protection level and underlying implementation
# Don't write to it
#
# Not thread safe
def readonly def readonly
yield to_slice do |slice|
yield slice
end
end end
def noaccess def noaccess
end end
# Not thread safe
def noaccess def noaccess
yield yield
end end
# For debugging.
# Returned String **not** tracked or wiped
def hexstring : String
readonly &.hexstring
end
def wipe def wipe
# Todo: implement wiping. Needs crystal support # Todo: implement wiping. Needs crystal support
end end
# Secret is wiped after exiting the block
def wipe def wipe
yield yield
ensure ensure
wipe wipe
end end
def reset
end
def finalize def finalize
wipe wipe
end end
# Timing safe memory compare # Timing safe memory compare
def ==(other : Secret) : Bool def ==(other : Secret) : Bool
readonly do readonly do |s1|
other.readonly do other.readonly do |s2|
Crypto::Subtle.constant_time_compare to_slice, other.to_slice Crypto::Subtle.constant_time_compare s1, s2
end end
end end
end end
# Timing safe memory compare # Timing safe memory compare
def ==(other : Bytes) : Bool def ==(other : Bytes) : Bool
readonly do readonly do |s1|
Crypto::Subtle.constant_time_compare to_slice, other.to_slice Crypto::Subtle.constant_time_compare s1, other
end
end
abstract def to_slice(& : Bytes -> Nil)
abstract def bytesize : Int32
macro delegate_to_slice(to object)
def to_slice(& : Bytes -> Nil)
yield {{object.id}}.to_slice
end
end
macro delegate_to_bytesize(to object)
def bytesize : Int32
{{object.id}}.bytesize
end end
end end
end end