sodium.cr/README.md

157 lines
4.0 KiB
Markdown
Raw Normal View History

2017-07-12 05:13:52 +02:00
# cox
2019-06-25 22:19:59 +02:00
[![Build Status](https://travis-ci.org/didactic-drunk/cox.svg?branch=master)](https://travis-ci.org/didactic-drunk/cox)
2017-07-12 05:13:52 +02:00
2019-06-25 22:19:59 +02:00
Updated Crystal bindings for the [libsodium API](https://libsodium.gitbook.io/doc/)
2017-07-12 05:13:52 +02:00
Given a recipients public key, you can encrypt and sign a message for them. Upon
receipt, they can decrypt and authenticate the message as having come from you.
## Installation
2019-06-27 06:10:42 +02:00
**[Optionally Install libsodium.](https://download.libsodium.org/doc/installation/)**
A recent version of libsodium is automatically downloaded and compiled if you don't install your own version.
2017-07-12 05:30:58 +02:00
2017-07-12 05:13:52 +02:00
Add this to your application's `shard.yml`:
```yaml
dependencies:
cox:
2019-06-25 22:19:59 +02:00
github: didactic-drunk/cox
2017-07-12 05:13:52 +02:00
```
2019-06-27 06:10:42 +02:00
## Features
- Public-Key Cryptography
- [x] Crypto Box Easy
- [ ] Sealed Box
- [x] Combined Signatures
- [x] Detached Signatures
- Secret-Key Cryptography
- [x] Secret Box
- [ ] Salsa20
- [ ] XSalsa20
- [ ] ChaCha20
- [ ] XChaCha20
- Hashing
- [x] Blake2b
- [ ] SipHash
- Password Hashing
- [x] Argon2 (Use for new applications)
- [ ] Scrypt (For compatibility with older applications)
- Other
- [x] Key Derivation
- [ ] One time auth
Several libsodium API's are already provided by Crystal:
* SHA-2 (Use [OpenSSL::Digest](https://crystal-lang.org/api/latest/OpenSSL/Digest.html))
* HMAC SHA-2 (Use [OpenSSL::HMAC](https://crystal-lang.org/api/latest/OpenSSL/HMAC.html))
* Random (Use [Random::Secure](https://crystal-lang.org/api/latest/Random/Secure.html))
2017-07-12 05:13:52 +02:00
## Usage
```crystal
require "cox"
data = "Hello World!"
# Alice is the sender
alice = Cox::KeyPair.new
# Bob is the recipient
bob = Cox::KeyPair.new
# Encrypt a message for Bob using his public key, signing it with Alice's
# secret key
nonce, encrypted = Cox.encrypt(data, bob.public, alice.secret)
# Decrypt the message using Bob's secret key, and verify its signature against
# Alice's public key
decrypted = Cox.decrypt(encrypted, nonce, alice.public, bob.secret)
String.new(decrypted) # => "Hello World!"
2019-06-19 10:46:42 +02:00
```
2019-06-27 06:10:42 +02:00
### Public key signing
2019-06-19 10:46:42 +02:00
```crystal
message = "Hello World!"
signing_pair = Cox::SignKeyPair.new
# Sign the message
signature = Cox.sign_detached(message, signing_pair.secret)
# And verify
Cox.verify_detached(signature, message, signing_pair.public) # => true
2017-07-12 05:13:52 +02:00
```
2019-06-27 06:10:42 +02:00
### Secret Key Encryption
2019-06-19 10:46:42 +02:00
```crystal
key = Cox::SecretKey.random
message = "foobar"
encrypted, nonce = key.encrypt_easy message
# On the other side.
key = Cox::SecretKey.new key
message = key.decrypt_easy encrypted, nonce
```
2019-06-27 06:10:42 +02:00
### Blake2b
2019-06-19 10:46:42 +02:00
```crystal
key = Bytes.new Cox::Blake2B::KEY_SIZE
salt = Bytes.new Cox::Blake2B::SALT_SIZE
personal = Bytes.new Cox::Blake2B::PERSONAL_SIZE
out_size = 64 # bytes between Cox::Blake2B::OUT_SIZE_MIN and Cox::Blake2B::OUT_SIZE_MAX
data = "data".to_slice
# output_size, key, salt, and personal are optional.
digest = Cox::Blake2b.new out_size, key: key, salt: salt, personal: personal
digest.update data
output = d.hexdigest
digest.reset # Reuse existing object to hash again.
digest.update data
output = d.hexdigest
```
2019-06-27 06:10:42 +02:00
### Key derivation
2019-06-19 10:46:42 +02:00
```crystal
2019-05-28 23:31:31 +02:00
kdf = Cox::Kdf.new
# kdf.derive(8_byte_context, subkey_size, subkey_id)
subkey1 = kdf.derive "context1", 16, 0
subkey2 = kdf.derive "context1", 16, 1
subkey3 = kdf.derive "context2", 32, 0
subkey4 = kdf.derive "context2", 64, 1
2019-06-19 10:46:42 +02:00
```
2019-06-27 06:10:42 +02:00
### Password Hashing
2019-06-19 10:46:42 +02:00
```crystal
pwhash = Cox::Pwhash.new
pwhash.memlimit = Cox::Pwhash::MEMLIMIT_MIN
pwhash.opslimit = Cox::Pwhash::OPSLIMIT_MIN
pass = "1234"
hash = pwhash.hash_str pass
pwhash.verify hash, pass
```
2019-05-28 23:31:31 +02:00
Use `examples/pwhash_selector.cr` to help choose ops/mem limits.
2017-07-12 05:13:52 +02:00
## Contributing
2019-06-25 22:19:59 +02:00
1. Fork it ( https://github.com/didactic-drunk/cox/fork )
2017-07-12 05:13:52 +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
2019-06-25 22:19:59 +02:00
- [andrewhamon](https://github.com/andrewhamon) Andrew Hamon - creator, former maintainer
- [dorkrawk](https://github.com/dorkrawk) Dave Schwantes - contributor
2019-06-25 22:19:59 +02:00
- [didactic-drunk](https://github.com/didactic-drunk) - current maintainer