Switch Crypto::Secret from module to abstract class
This commit is contained in:
parent
bfbaacab4d
commit
80a47aa966
@ -192,12 +192,12 @@ Each implementation may add additional protections
|
||||
**Only intended for use by crypto library authors**
|
||||
|
||||
```
|
||||
class MySecret
|
||||
class MySecret < Crypto::Secret
|
||||
# Choose one
|
||||
include Crypto::Secret::Stateless
|
||||
include Crypto::Secret::Stateful
|
||||
|
||||
def initialize(size)
|
||||
def initialize(size : Int32)
|
||||
# allocate or reference storage
|
||||
# optionally mlock
|
||||
end
|
||||
@ -209,7 +209,7 @@ class MySecret
|
||||
# optionally reencrypt or signal HSM
|
||||
end
|
||||
|
||||
def bytesize : Int32
|
||||
def buffer_bytesize : Int32
|
||||
# return the size
|
||||
end
|
||||
|
||||
|
@ -1,8 +1,6 @@
|
||||
require "./spec_helper"
|
||||
require "../src/crypto-secret/test"
|
||||
require "../src/crypto-secret"
|
||||
#require "../src/crypto-secret/not"
|
||||
#require "../src/crypto-secret/bidet"
|
||||
|
||||
test_secret_class Crypto::Secret::Not
|
||||
test_secret_class Crypto::Secret::Bidet
|
||||
|
@ -1,6 +1,6 @@
|
||||
require "./stateless"
|
||||
|
||||
module Crypto::Secret
|
||||
abstract class Crypto::Secret
|
||||
# Leaves less sh** around if you forget to wipe. A safer default for large secrets that may stress mlock limits or low confidentiality secrets.
|
||||
#
|
||||
# * Wipes on finalize but should not be relied on
|
||||
@ -8,7 +8,7 @@ module Crypto::Secret
|
||||
# * Not access protected
|
||||
# * No guard pages
|
||||
# * Hours of fun
|
||||
class Bidet < Base
|
||||
class Bidet < Secret
|
||||
include Stateless
|
||||
|
||||
def self.new(size : Int32)
|
||||
@ -20,6 +20,6 @@ module Crypto::Secret
|
||||
end
|
||||
|
||||
delegate_to_slice @bytes
|
||||
delegate_to_bytesize @bytes.bytesize
|
||||
delegate_buffer_bytesize_to @bytes.bytesize
|
||||
end
|
||||
end
|
||||
|
@ -1,3 +1,6 @@
|
||||
require "./not"
|
||||
require "./bidet"
|
||||
|
||||
{% if @type.has_constant?("Sodium") %}
|
||||
CRYPTO_SECRET_KEY_CLASS = Sodium::SecureBuffer
|
||||
{% else %}
|
||||
@ -12,23 +15,23 @@ module Crypto::Secret::Config
|
||||
Paranoid
|
||||
Default
|
||||
Lax
|
||||
None
|
||||
# None
|
||||
end
|
||||
|
||||
def self.setup(how : SecurityLevel = SecurityLevel::Default) : Nil
|
||||
case how
|
||||
in SecurityLevel::Paranoid
|
||||
register_use Bidet, :not
|
||||
register_use CRYPTO_SECRET_KEY_CLASS, :kgk, :key, :data
|
||||
in SecurityLevel::Default
|
||||
register_use Not, :not
|
||||
register_use Bidet, :data
|
||||
register_use CRYPTO_SECRET_KEY_CLASS, :kgk, :key
|
||||
in SecurityLevel::Lax
|
||||
register_use Not, :not
|
||||
register_use Bidet, :kgk, :key, :data
|
||||
in SecurityLevel::None
|
||||
register_use Not, :kgk, :key, :data, :not
|
||||
def self.setup(level : SecurityLevel = SecurityLevel::Default) : Nil
|
||||
register_use Not, :not
|
||||
|
||||
case level
|
||||
in SecurityLevel::Paranoid
|
||||
register_use Bidet, :not
|
||||
register_use CRYPTO_SECRET_KEY_CLASS, :kgk, :key, :data
|
||||
in SecurityLevel::Default
|
||||
register_use Crypto::Secret::Bidet, :data
|
||||
register_use CRYPTO_SECRET_KEY_CLASS, :kgk, :key
|
||||
in SecurityLevel::Lax
|
||||
register_use Bidet, :kgk, :key, :data
|
||||
# in SecurityLevel::None
|
||||
# register_use Not, :kgk, :key, :data
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1,4 +1 @@
|
||||
#require "./not"
|
||||
require "./secret"
|
||||
# require "./large"
|
||||
# require "./key"
|
||||
|
@ -1,5 +1,5 @@
|
||||
module Crypto
|
||||
module Secret
|
||||
abstract class Secret
|
||||
module Stateless
|
||||
end
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
require "./stateless"
|
||||
|
||||
module Crypto::Secret
|
||||
abstract class Crypto::Secret
|
||||
# A not very secret `Secret`, but fast
|
||||
#
|
||||
# Suitable uses:
|
||||
@ -12,7 +12,7 @@ module Crypto::Secret
|
||||
# * Not access protected
|
||||
# * No guard pages
|
||||
# * No wiping
|
||||
struct Not
|
||||
class Not < Secret
|
||||
include Stateless
|
||||
|
||||
def self.new(size : Int32)
|
||||
@ -25,7 +25,7 @@ module Crypto::Secret
|
||||
end
|
||||
|
||||
delegate_to_slice @bytes
|
||||
delegate_to_bytesize @bytes.bytesize
|
||||
delegate_buffer_bytesize_to @bytes.bytesize
|
||||
|
||||
def wipe
|
||||
end
|
||||
|
@ -10,7 +10,7 @@ require "./class_methods"
|
||||
#
|
||||
# Other shards may provide additional `Secret` types ([sodium.cr](https://github.com/didactic-drunk/sodium.cr))
|
||||
@[Experimental]
|
||||
module Crypto::Secret
|
||||
abstract class Crypto::Secret
|
||||
class Error < Exception
|
||||
class KeyWiped < Error
|
||||
end
|
||||
@ -162,7 +162,11 @@ module Crypto::Secret
|
||||
abstract def readonly(& : Bytes -> U) forall U
|
||||
|
||||
protected abstract def to_slice(& : Bytes -> U) forall U
|
||||
abstract def bytesize : Int32
|
||||
abstract def buffer_bytesize : Int32
|
||||
|
||||
def bytesize : Int32
|
||||
buffer_bytesize
|
||||
end
|
||||
|
||||
macro delegate_to_slice(to object)
|
||||
def to_slice(& : Bytes -> U) forall U
|
||||
@ -170,8 +174,8 @@ module Crypto::Secret
|
||||
end
|
||||
end
|
||||
|
||||
macro delegate_to_bytesize(to object)
|
||||
def bytesize : Int32
|
||||
macro delegate_buffer_bytesize_to(to object)
|
||||
def buffer_bytesize : Int32
|
||||
{{object.id}}
|
||||
end
|
||||
end
|
||||
@ -181,13 +185,4 @@ module Crypto::Secret
|
||||
end
|
||||
end
|
||||
|
||||
macro finished
|
||||
{% for key, klass in Crypto::Secret::REGISTERED_USES %}
|
||||
#puts "{{key}}={{klass}}"
|
||||
puts "key=klass"
|
||||
require {{ Crypto::Secret::REGISTERED_LOAD_PATHS[klass] }}
|
||||
Crypto::Secret::REGISTERED[:{{key.id}}] = {{klass.id}}
|
||||
{% end %}
|
||||
end
|
||||
|
||||
require "./config"
|
||||
|
@ -1,6 +1,6 @@
|
||||
require "./secret"
|
||||
|
||||
module Crypto::Secret
|
||||
abstract class Crypto::Secret
|
||||
# Development guide:
|
||||
# 1. Create your initialize method and optionally allocate memory
|
||||
# 2. Create a finalize method to deallocate memory if necessary
|
||||
@ -10,12 +10,6 @@ module Crypto::Secret
|
||||
#
|
||||
# When state changes are required (such as using #noaccess) and the buffer is accessed from multiple threads wrap each #readonly/#readwrite block in a lock.
|
||||
module Stateful
|
||||
include Crypto::Secret
|
||||
|
||||
macro included
|
||||
extend ClassMethods
|
||||
end
|
||||
|
||||
@state = State::Readwrite
|
||||
@pre_wipe_state = State::Readwrite
|
||||
|
||||
|
@ -2,14 +2,11 @@ require "./secret"
|
||||
|
||||
# Provides a 0 overhead implementation of [#readwrite, #readonly, #noaccess, #reset] with no protection
|
||||
#
|
||||
# Data is erased when #wipe is out of scope, manual #wipe, or finalized except for `Not`
|
||||
# Data is erased when (except for `Crypto::Secret::Not`):
|
||||
# * #wipe(&block) goes out of scope
|
||||
# * manual #wipe
|
||||
# * finalized
|
||||
module Crypto::Secret::Stateless
|
||||
include Crypto::Secret
|
||||
|
||||
macro included
|
||||
extend ClassMethods
|
||||
end
|
||||
|
||||
# Not thread safe
|
||||
def readwrite : Secret
|
||||
self
|
||||
|
Loading…
Reference in New Issue
Block a user