Go to file
Didactic Drunk 848cf3e3e2 Breaking API changes:
SecretKey renamed to SecretBox.

Start of automatic wiping.
Documentation additions and corrections.
2019-06-28 05:20:56 -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 Breaking API changes: 2019-06-28 05:20:56 -07:00
src Breaking API changes: 2019-06-28 05:20:56 -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 Breaking API changes: 2019-06-28 05:20:56 -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

README.md

cox

Build Status Docs

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

CryptoBox easy encryption

require "cox"

data = "Hello World!"

# Alice is the sender
alice = Cox::CryptoBox::SecretKey.new

# Bob is the recipient
bob = Cox::CryptoBox::SecretKey.new

# Precompute a shared secret between alice and bob.
pair = alice.pair bob.public_key

# Encrypt a message for Bob using his public key, signing it with Alice's
# secret key
nonce, encrypted = pair.encrypt data

# Precompute within a block.  The shared secret is wiped when the block exits.
bob.pair alice.public_key do |pair|
  # 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!"
end

Public key signing

message = "Hello World!"

secret_key = Cox::Sign::SecretKey.new

# Sign the message
signature = secret_key.sign_detached message

# Send secret_key.public_key to the recipient

public_key = Cox::Sign::PublicKey.new key_bytes

# raises Cox::Error::VerificationFailed on failure.
public_key.verify_detached message, signature

Secret Key Encryption

key = Cox::SecretKey.new

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