crypto-secret.cr/README.md

117 lines
3.7 KiB
Markdown
Raw Normal View History

2021-06-13 02:42:07 +02:00
# crypto-secret.cr
[![Crystal CI](https://github.com/didactic-drunk/crypto-secret.cr/actions/workflows/crystal.yml/badge.svg)](https://github.com/didactic-drunk/crypto-secret.cr/actions/workflows/crystal.yml)
[![GitHub release](https://img.shields.io/github/release/didactic-drunk/crypto-secret.cr.svg)](https://github.com/didactic-drunk/crypto-secret.cr/releases)
![GitHub commits since latest release (by date) for a branch](https://img.shields.io/github/commits-since/didactic-drunk/crypto-secret.cr/latest)
2021-06-13 02:43:35 +02:00
[![Docs](https://img.shields.io/badge/docs-available-brightgreen.svg)](https://didactic-drunk.github.io/crypto-secret.cr/main)
2021-06-13 01:03:59 +02:00
2021-06-14 04:00:53 +02:00
Secrets hold sensitive information
The Secret interface manages limited time access to the secret and securely erasing the secret when no longer needed.
Secret providers may implement additional protections via:
* `#noaccess`, `#readonly` or `readwrite`.
* Using [mprotect]() to control access
* Encrypting the data when not in use
* Deriving keys on demand from a HSM
* Preventing the Secret from entering swap ([mlock]())
* Preventing the Secret from entering core dumps
* Other
2021-06-13 01:03:59 +02:00
## Installation
1. Add the dependency to your `shard.yml`:
```yaml
dependencies:
2021-06-13 02:42:07 +02:00
crypto-secret:
github: didactic-drunk/crypto-secret
2021-06-13 01:03:59 +02:00
```
2. Run `shards install`
## Usage
```crystal
2021-06-13 02:42:07 +02:00
require "crypto-secret/not"
2021-06-13 01:03:59 +02:00
not_secret = Crypto::Secret::Not.new 32
2021-06-14 04:00:53 +02:00
not_secret.wipe do
not_secret.readonly do |slice|
# May only read slice
end
not_secret.readwrite do |slice|
# May read or write to slice
end
end # Secret is erased
2021-06-13 01:03:59 +02:00
```
2021-06-14 04:00:53 +02:00
## What is a Secret?
<strike>Secrets are Keys</strike>
That's complicated and specific to the application. Some examples:
* Passwords
* A crypto key is always a Secret. Except when used for verification (sometimes)
* A decrypted password vault (but it's not a Key)
Not secrets:
* 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
## Why?
The Secret interface is designed to handle varied levels of confidentiality with a unified API for cryptography libraries.
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.
Or for most applications the master key may use best effort protection 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.
A key verifying a public key signature may not be Secret.
2021-06-13 01:03:59 +02:00
## Implementing a new Secret holding class
2021-06-14 04:00:53 +02:00
**Only intended for use by crypto library authors**
2021-06-13 01:03:59 +02:00
```
class MySecret
include Crypto::Secret
def initialize(size)
# allocate storage
# optionally mlock
end
2021-06-14 04:00:53 +02:00
def to_slice(& : Bytes -> Nil)
# yield Slice.new(pointer, size)
ensure
# optionally reencrypt or signal HSM
end
def bytesize : Int32
# return the size
2021-06-13 01:03:59 +02:00
end
# optionally override [noaccess, readonly, readwrite]
2021-06-14 04:00:53 +02:00
# optionally override (almost) any other method with implementation specific version
2021-06-13 01:03:59 +02:00
end
```
## Contributing
2021-06-14 04:00:53 +02:00
**Open a discussion before creating PR's**
2021-06-13 02:42:07 +02:00
1. Fork it (<https://github.com/your-github-user/crypto-secret/fork>)
2021-06-13 01:03:59 +02:00
2. Create your feature branch (`git checkout -b my-new-feature`)
3. Commit your changes (`git commit -am 'Add some feature'`)
4. Push to the branch (`git push origin my-new-feature`)
5. Create a new Pull Request
## Contributors
- [didactic-drunk](https://github.com/didactic-drunk) - current maintainer