Go to file
2019-06-27 21:47:09 -07:00
benchmarks Add blake2b benchmark and examples/pwhash_selector.cr 2019-06-25 19:24:21 -07:00
build Automatically detect and build libsodium from source on systems with old or missing libsodium's. 2019-06-26 18:28:08 -07:00
examples Formatting 2019-06-27 17:20:02 -07:00
scripts/git Switch .to_unsafe to .to_slice 2019-06-27 17:42:49 -07:00
spec Formatting 2019-06-27 17:20:02 -07:00
src Switch .to_unsafe to .to_slice 2019-06-27 17:42:49 -07:00
.editorconfig Initial commit 2017-07-11 22:15:35 -05:00
.gitignore Travis Github Pages configuration 2019-06-27 21:47:09 -07:00
.travis.yml Travis Github Pages configuration 2019-06-27 21:47:09 -07:00
LICENSE Initial commit 2017-07-11 22:15:35 -05:00
README.md Formatting 2019-06-27 17:20:02 -07:00
shard.yml Automatically detect and build libsodium from source on systems with old or missing libsodium's. 2019-06-26 18:28:08 -07:00

cox

Build Status

Updated Crystal bindings for the libsodium API

Features

☑ Indicate specs are compared against test vectors from another source.

Several features in libsodium are already provided by Crystal:

Installation

Optionally Install libsodium. A recent version of libsodium is automatically downloaded and compiled if you don't install your own version.

Add this to your application's shard.yml:

dependencies:
  cox:
    github: didactic-drunk/cox

Usage

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!"

Public key signing

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

Secret Key Encryption

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

Blake2b

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

Key derivation

kdf = Cox::Kdf.new

# kdf.derive(8_byte_context, subkey_id, subkey_size)
subkey1 = kdf.derive "context1", 0, 16
subkey2 = kdf.derive "context1", 1, 16
subkey3 = kdf.derive "context2", 0, 32
subkey4 = kdf.derive "context2", 1, 64

Password Hashing

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

Use examples/pwhash_selector.cr to help choose ops/mem limits.

Example output: Ops limit →

1 4 16 64 256 1024 4096 16384 65536 262144 1048576
8K 0.542s 2.114s
32K 0.513s 2.069s
128K 0.530s 2.121s
512K 0.566s 2.237s
2048K 0.567s 2.290s
8192K 0.670s 2.542s
32768K 0.684s 2.777s
131072K 0.805s 3.106s
524288K 0.504s 1.135s 3.661s
2097152K 2.119s
Memory

Contributing

  1. Fork it ( https://github.com/didactic-drunk/cox/fork )
  2. Install a formatting check git hook (ln -sf ../../scripts/git/pre-commit .git/hooks)
  3. Create your feature branch (git checkout -b my-new-feature)
  4. Commit your changes (git commit -am 'Add some feature')
  5. Push to the branch (git push origin my-new-feature)
  6. Create a new Pull Request

Contributors