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**
|
**Only intended for use by crypto library authors**
|
||||||
|
|
||||||
```
|
```
|
||||||
class MySecret
|
class MySecret < Crypto::Secret
|
||||||
# Choose one
|
# Choose one
|
||||||
include Crypto::Secret::Stateless
|
include Crypto::Secret::Stateless
|
||||||
include Crypto::Secret::Stateful
|
include Crypto::Secret::Stateful
|
||||||
|
|
||||||
def initialize(size)
|
def initialize(size : Int32)
|
||||||
# allocate or reference storage
|
# allocate or reference storage
|
||||||
# optionally mlock
|
# optionally mlock
|
||||||
end
|
end
|
||||||
@ -209,7 +209,7 @@ class MySecret
|
|||||||
# optionally reencrypt or signal HSM
|
# optionally reencrypt or signal HSM
|
||||||
end
|
end
|
||||||
|
|
||||||
def bytesize : Int32
|
def buffer_bytesize : Int32
|
||||||
# return the size
|
# return the size
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
require "./spec_helper"
|
require "./spec_helper"
|
||||||
require "../src/crypto-secret/test"
|
require "../src/crypto-secret/test"
|
||||||
require "../src/crypto-secret"
|
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::Not
|
||||||
test_secret_class Crypto::Secret::Bidet
|
test_secret_class Crypto::Secret::Bidet
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
require "./stateless"
|
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.
|
# 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
|
# * Wipes on finalize but should not be relied on
|
||||||
@ -8,7 +8,7 @@ module Crypto::Secret
|
|||||||
# * Not access protected
|
# * Not access protected
|
||||||
# * No guard pages
|
# * No guard pages
|
||||||
# * Hours of fun
|
# * Hours of fun
|
||||||
class Bidet < Base
|
class Bidet < Secret
|
||||||
include Stateless
|
include Stateless
|
||||||
|
|
||||||
def self.new(size : Int32)
|
def self.new(size : Int32)
|
||||||
@ -20,6 +20,6 @@ module Crypto::Secret
|
|||||||
end
|
end
|
||||||
|
|
||||||
delegate_to_slice @bytes
|
delegate_to_slice @bytes
|
||||||
delegate_to_bytesize @bytes.bytesize
|
delegate_buffer_bytesize_to @bytes.bytesize
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
require "./not"
|
||||||
|
require "./bidet"
|
||||||
|
|
||||||
{% if @type.has_constant?("Sodium") %}
|
{% if @type.has_constant?("Sodium") %}
|
||||||
CRYPTO_SECRET_KEY_CLASS = Sodium::SecureBuffer
|
CRYPTO_SECRET_KEY_CLASS = Sodium::SecureBuffer
|
||||||
{% else %}
|
{% else %}
|
||||||
@ -12,23 +15,23 @@ module Crypto::Secret::Config
|
|||||||
Paranoid
|
Paranoid
|
||||||
Default
|
Default
|
||||||
Lax
|
Lax
|
||||||
None
|
# None
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.setup(how : SecurityLevel = SecurityLevel::Default) : Nil
|
def self.setup(level : SecurityLevel = SecurityLevel::Default) : Nil
|
||||||
case how
|
register_use Not, :not
|
||||||
|
|
||||||
|
case level
|
||||||
in SecurityLevel::Paranoid
|
in SecurityLevel::Paranoid
|
||||||
register_use Bidet, :not
|
register_use Bidet, :not
|
||||||
register_use CRYPTO_SECRET_KEY_CLASS, :kgk, :key, :data
|
register_use CRYPTO_SECRET_KEY_CLASS, :kgk, :key, :data
|
||||||
in SecurityLevel::Default
|
in SecurityLevel::Default
|
||||||
register_use Not, :not
|
register_use Crypto::Secret::Bidet, :data
|
||||||
register_use Bidet, :data
|
|
||||||
register_use CRYPTO_SECRET_KEY_CLASS, :kgk, :key
|
register_use CRYPTO_SECRET_KEY_CLASS, :kgk, :key
|
||||||
in SecurityLevel::Lax
|
in SecurityLevel::Lax
|
||||||
register_use Not, :not
|
|
||||||
register_use Bidet, :kgk, :key, :data
|
register_use Bidet, :kgk, :key, :data
|
||||||
in SecurityLevel::None
|
# in SecurityLevel::None
|
||||||
register_use Not, :kgk, :key, :data, :not
|
# register_use Not, :kgk, :key, :data
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1,4 +1 @@
|
|||||||
#require "./not"
|
|
||||||
require "./secret"
|
require "./secret"
|
||||||
# require "./large"
|
|
||||||
# require "./key"
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
module Crypto
|
module Crypto
|
||||||
module Secret
|
abstract class Secret
|
||||||
module Stateless
|
module Stateless
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
require "./stateless"
|
require "./stateless"
|
||||||
|
|
||||||
module Crypto::Secret
|
abstract class Crypto::Secret
|
||||||
# A not very secret `Secret`, but fast
|
# A not very secret `Secret`, but fast
|
||||||
#
|
#
|
||||||
# Suitable uses:
|
# Suitable uses:
|
||||||
@ -12,7 +12,7 @@ module Crypto::Secret
|
|||||||
# * Not access protected
|
# * Not access protected
|
||||||
# * No guard pages
|
# * No guard pages
|
||||||
# * No wiping
|
# * No wiping
|
||||||
struct Not
|
class Not < Secret
|
||||||
include Stateless
|
include Stateless
|
||||||
|
|
||||||
def self.new(size : Int32)
|
def self.new(size : Int32)
|
||||||
@ -25,7 +25,7 @@ module Crypto::Secret
|
|||||||
end
|
end
|
||||||
|
|
||||||
delegate_to_slice @bytes
|
delegate_to_slice @bytes
|
||||||
delegate_to_bytesize @bytes.bytesize
|
delegate_buffer_bytesize_to @bytes.bytesize
|
||||||
|
|
||||||
def wipe
|
def wipe
|
||||||
end
|
end
|
||||||
|
@ -10,7 +10,7 @@ require "./class_methods"
|
|||||||
#
|
#
|
||||||
# Other shards may provide additional `Secret` types ([sodium.cr](https://github.com/didactic-drunk/sodium.cr))
|
# Other shards may provide additional `Secret` types ([sodium.cr](https://github.com/didactic-drunk/sodium.cr))
|
||||||
@[Experimental]
|
@[Experimental]
|
||||||
module Crypto::Secret
|
abstract class Crypto::Secret
|
||||||
class Error < Exception
|
class Error < Exception
|
||||||
class KeyWiped < Error
|
class KeyWiped < Error
|
||||||
end
|
end
|
||||||
@ -162,7 +162,11 @@ module Crypto::Secret
|
|||||||
abstract def readonly(& : Bytes -> U) forall U
|
abstract def readonly(& : Bytes -> U) forall U
|
||||||
|
|
||||||
protected abstract def to_slice(& : 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)
|
macro delegate_to_slice(to object)
|
||||||
def to_slice(& : Bytes -> U) forall U
|
def to_slice(& : Bytes -> U) forall U
|
||||||
@ -170,8 +174,8 @@ module Crypto::Secret
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
macro delegate_to_bytesize(to object)
|
macro delegate_buffer_bytesize_to(to object)
|
||||||
def bytesize : Int32
|
def buffer_bytesize : Int32
|
||||||
{{object.id}}
|
{{object.id}}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -181,13 +185,4 @@ module Crypto::Secret
|
|||||||
end
|
end
|
||||||
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"
|
require "./config"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
require "./secret"
|
require "./secret"
|
||||||
|
|
||||||
module Crypto::Secret
|
abstract class Crypto::Secret
|
||||||
# Development guide:
|
# Development guide:
|
||||||
# 1. Create your initialize method and optionally allocate memory
|
# 1. Create your initialize method and optionally allocate memory
|
||||||
# 2. Create a finalize method to deallocate memory if necessary
|
# 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.
|
# 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
|
module Stateful
|
||||||
include Crypto::Secret
|
|
||||||
|
|
||||||
macro included
|
|
||||||
extend ClassMethods
|
|
||||||
end
|
|
||||||
|
|
||||||
@state = State::Readwrite
|
@state = State::Readwrite
|
||||||
@pre_wipe_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
|
# 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
|
module Crypto::Secret::Stateless
|
||||||
include Crypto::Secret
|
|
||||||
|
|
||||||
macro included
|
|
||||||
extend ClassMethods
|
|
||||||
end
|
|
||||||
|
|
||||||
# Not thread safe
|
# Not thread safe
|
||||||
def readwrite : Secret
|
def readwrite : Secret
|
||||||
self
|
self
|
||||||
|
Loading…
Reference in New Issue
Block a user