README.md: How? When?

master
Didactic Drunk 2021-06-14 00:29:23 -07:00
parent fd26f11489
commit f13bd8de9c
1 changed files with 66 additions and 11 deletions

View File

@ -6,7 +6,7 @@
Secrets hold sensitive information Secrets hold sensitive information
The Secret interface manages limited time access to the secret and securely erasing the secret when no longer needed. The Secret interface manages limited time access to a secret and securely erases the secret when no longer needed.
Secret providers may implement additional protections via: Secret providers may implement additional protections via:
* `#noaccess`, `#readonly` or `readwrite`. * `#noaccess`, `#readonly` or `readwrite`.
@ -35,15 +35,17 @@ Secret providers may implement additional protections via:
```crystal ```crystal
require "crypto-secret/not" require "crypto-secret/not"
not_secret = Crypto::Secret::Not.new 32 # `Not` isn't actually a secret and does none of what the comments say
not_secret.wipe do # Replace `Not` with a secure implementation like [Sodium::SecureBuffer](https://didactic-drunk.github.io/sodium.cr/master/Sodium/SecureBuffer.html)
not_secret.readonly do |slice| secret = Crypto::Secret::Not.new 32
secret.wipe do
secret.readonly do |slice|
# May only read slice # May only read slice
end end
not_secret.readwrite do |slice| secret.readwrite do |slice|
# May read or write to slice # May read or write to slice
end end
end # Secret is erased end # secret is erased
``` ```
## What is a Secret? ## What is a Secret?
@ -58,7 +60,7 @@ That's complicated and specific to the application. Some examples:
Not secrets: Not secrets:
* Digest output. Except when used for key derivation, then it's a Secret, including the Digest state * Digest output. Except when used for key derivation, then it's a Secret, including the Digest state
* IO::Memory or writing a file. Except when the file is a password vault, cryptocurrency wallet, encrypted mail/messages, goat porn, maybe normal porn, sometimes scat porn, occassionally furry, not vanilla porn * IO::Memory or writing a file. Except when the file is a password vault, cryptocurrency wallet, encrypted mail/messages, goat porn, maybe "normal" porn, sometimes scat porn, occassionally furry, not vanilla porn
## Why? ## Why?
@ -67,10 +69,62 @@ The Secret interface is designed to handle varied levels of confidentiality with
There is no one size fits all solution. Different applications have different security requirements. Sometimes for the same algorithm. There is no one size fits all solution. Different applications have different security requirements. Sometimes for the same algorithm.
A master key (kgk) may reside on a HSM and generate subkeys on demand. A master key (kgk) may reside on a HSM and generate subkeys on demand.
Or for most applications the master key may use best effort protection using a combination of [guard pages, mlock, mprotect]. Or for most applications the master key may use a best effort approach using a combination of [guard pages, mlock, mprotect].
Other keys in the same application may handle a high volume of messages where [guard pages, mlock, mprotect] overhead is too high. Other keys in the same application may handle a high volume of messages where [guard pages, mlock, mprotect] overhead is too high.
A key verifying a public key signature may not be Secret. A key verifying a public key signature may not be Secret (but is a Secret::Not).
## How do I use a Secret returned by a shard?
That depends on what you use it for.
#### Using a Secret key
TODO
#### Using a Secret to hold decrypted file contents:
```
key = ...another Secret...
encrypted_str = File.read("filename")
decrypted_size = encrypted_str.bytesize - mac_size
file_secret = Crypto::Secret::Default.new decrypted_size
file_secret.wipe do
file_secrets.readwrite do |slice|
decrypt(key: key, src: encrypted_str, dst: slice)
# Do something with file contents in slice
end
end # Decrypted data is erased
```
## When should I use a Secret?
When implementing an encryption class return `Secret` keys with a sane default implementation that suits the average use for your class. Several default implementations will be provided.
Allow overriding the default returned key and/or allow users of your class to provide their own `Secret` for cases where they need more or less protection.
Example:
```
class SimplifiedEncryption
# Allow users of your library to provide their own Secret key. Also provide a sane default.
def encrypt(data : Bytes | String, key : Secret? = nil) : {Secret, Bytes}
key ||= Crypto::Secret::Default.random
...
{key, encrypted_slice}
end
end
```
## What attacks does a Secret protect against?
TODO: describe implementations
## Other languages/libraries
* rust: [secrets](https://github.com/stouset/secrets/)
* c: [libsodium](https://github.com/jedisct1/libsodium-doc/blob/master/helpers/memory_management.md#guarded_heap_allocations)
* go: [memguard](https://github.com/awnumar/memguard)
* haskell: [securemem](https://hackage.haskell.org/package/securemem)
* c#: [SecureString](https://docs.microsoft.com/en-us/dotnet/api/system.security.securestring)
## Implementing a new Secret holding class ## Implementing a new Secret holding class
@ -86,6 +140,7 @@ class MySecret
end end
def to_slice(& : Bytes -> Nil) def to_slice(& : Bytes -> Nil)
# The yielded Slice only needs to be valid within the block
# yield Slice.new(pointer, size) # yield Slice.new(pointer, size)
ensure ensure
# optionally reencrypt or signal HSM # optionally reencrypt or signal HSM
@ -96,14 +151,14 @@ class MySecret
end end
# optionally override [noaccess, readonly, readwrite] # optionally override [noaccess, readonly, readwrite]
# optionally override (almost) any other method with implementation specific version # optionally override (almost) any other method with an implementation specific version
end end
``` ```
## Contributing ## Contributing
**Open a discussion before creating PR's** **Open a discussion or issue before creating PR's**
1. Fork it (<https://github.com/your-github-user/crypto-secret/fork>) 1. Fork it (<https://github.com/your-github-user/crypto-secret/fork>)
2. Create your feature branch (`git checkout -b my-new-feature`) 2. Create your feature branch (`git checkout -b my-new-feature`)