Secret interface changes

master
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
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
(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

View File

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

View File

@ -4,59 +4,101 @@ require "crypto/subtle"
#
# **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]
module Crypto::Secret
abstract def to_slice : Bytes
class Error < Exception
class KeyWiped < Error
end
end
def readwrite
end
# Yields a Slice that is readable and writable
#
# `slice` is only available within the block
#
# Not thread safe
def readwrite
yield
to_slice do |slice|
yield slice
end
end
def readonly
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
yield
to_slice do |slice|
yield slice
end
end
def noaccess
end
# Not thread safe
def noaccess
yield
end
# For debugging.
# Returned String **not** tracked or wiped
def hexstring : String
readonly &.hexstring
end
def wipe
# Todo: implement wiping. Needs crystal support
end
# Secret is wiped after exiting the block
def wipe
yield
ensure
wipe
end
def reset
end
def finalize
wipe
end
# Timing safe memory compare
def ==(other : Secret): Bool
readonly do
other.readonly do
Crypto::Subtle.constant_time_compare to_slice, other.to_slice
def ==(other : Secret) : Bool
readonly do |s1|
other.readonly do |s2|
Crypto::Subtle.constant_time_compare s1, s2
end
end
end
# Timing safe memory compare
def ==(other : Bytes) : Bool
readonly do
Crypto::Subtle.constant_time_compare to_slice, other.to_slice
readonly do |s1|
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