Rename project from "cox" to "sodium.cr".

master
Didactic Drunk 2019-06-28 16:17:09 -07:00
parent 8e939b9518
commit a4b1b8071c
33 changed files with 135 additions and 136 deletions

View File

@ -3,7 +3,7 @@ os:
- linux - linux
- osx - osx
install: install:
- COX_BUILD_DEBUG=1 LIBSODIUM_BUILD_DIR=$HOME/libsodium ./build/libsodium_install.sh - SODIUM_BUILD_DEBUG=1 LIBSODIUM_BUILD_DIR=$HOME/libsodium ./build/libsodium_install.sh
before_script: before_script:
- export LIBSODIUM_BUILD_DIR=$HOME/libsodium - export LIBSODIUM_BUILD_DIR=$HOME/libsodium
after_failure: after_failure:

View File

@ -1,6 +1,6 @@
# cox # sodium.cr
[![Build Status](https://travis-ci.org/didactic-drunk/cox.svg?branch=master)](https://travis-ci.org/didactic-drunk/cox) [![Build Status](https://travis-ci.org/didactic-drunk/sodium.cr.svg?branch=master)](https://travis-ci.org/didactic-drunk/sodium.cr)
[![Docs](https://img.shields.io/badge/docs-available-brightgreen.svg)](https://didactic-drunk.github.io/cox/) [![Docs](https://img.shields.io/badge/docs-available-brightgreen.svg)](https://didactic-drunk.github.io/sodium.cr/)
Updated Crystal bindings for the [libsodium API](https://libsodium.gitbook.io/doc/) Updated Crystal bindings for the [libsodium API](https://libsodium.gitbook.io/doc/)
@ -56,8 +56,8 @@ Add this to your application's `shard.yml`:
```yaml ```yaml
dependencies: dependencies:
cox: sodium.cr:
github: didactic-drunk/cox github: didactic-drunk/sodium.cr
``` ```
## What should I use for my application? ## What should I use for my application?
@ -65,16 +65,16 @@ dependencies:
| Class | | | Class | |
| --- | --- | | --- | --- |
| `CryptoBox` `Sign` `SecretBox` | I don't know much about crypto. | | `CryptoBox` `Sign` `SecretBox` | I don't know much about crypto. |
| [`Cox::CryptoBox::SecretKey`](https://didactic-drunk.github.io/cox/Cox/CryptoBox/SecretKey.html) | I want to encrypt + authenticate data using public key encryption. | | [`Sodium::CryptoBox::SecretKey`](https://didactic-drunk.github.io/sodium.cr/Sodium/CryptoBox/SecretKey.html) | I want to encrypt + authenticate data using public key encryption. |
| [`Cox::Sign::SecretKey`](https://didactic-drunk.github.io/cox/Cox/Sign/SecretKey.html) | I want to sign or verify messages without encryption. | | [`Sodium::Sign::SecretKey`](https://didactic-drunk.github.io/sodium.cr/Sodium/Sign/SecretKey.html) | I want to sign or verify messages without encryption. |
| [`Cox::SecretBox`](https://didactic-drunk.github.io/cox/Cox/SecretBox.html) | I have a shared key and want to encrypt + authenticate data. | | [`Sodium::SecretBox`](https://didactic-drunk.github.io/sodium.cr/Sodium/SecretBox.html) | I have a shared key and want to encrypt + authenticate data. |
| AEAD | I have a shared key and want encrypt + authenticate streamed data. (Not implemented yet) | | AEAD | I have a shared key and want encrypt + authenticate streamed data. (Not implemented yet) |
| [`Cox::Digest::Blake2b`](https://didactic-drunk.github.io/cox/Cox/Digest::Blake2b.html) | I want to hash data fast and securely. | | [`Sodium::Digest::Blake2b`](https://didactic-drunk.github.io/sodium.cr/Sodium/Digest::Blake2b.html) | I want to hash data fast and securely. |
| `Cox::Digest::SipHash` | I want to hash data really fast and less securely. (Not implemented yet) | | `Sodium::Digest::SipHash` | I want to hash data really fast and less securely. (Not implemented yet) |
| `Cox::Pwhash` | I want to hash a password and store it. | | `Sodium::Pwhash` | I want to hash a password and store it. |
| `Cox::Pwhash` | I want to derive a key from a password. | | `Sodium::Pwhash` | I want to derive a key from a password. |
| `Cox::Kdf` | I have a high quality master key and want to make subkeys. | | `Sodium::Kdf` | I have a high quality master key and want to make subkeys. |
| [`Cox::Cipher::Chalsa`](https://didactic-drunk.github.io/cox/Cox/Cipher/Chalsa.html) | What goes with guacamole? | | [`Sodium::Cipher::Chalsa`](https://didactic-drunk.github.io/sodium.cr/Sodium/Cipher/Chalsa.html) | What goes with guacamole? |
| Everything else | I want to design my own crypto protocol and probably do it wrong. | | Everything else | I want to design my own crypto protocol and probably do it wrong. |
@ -84,15 +84,15 @@ The `specs` provide the best examples of how to use or misuse this shard.
### CryptoBox easy encryption ### CryptoBox easy encryption
```crystal ```crystal
require "cox" require "sodium"
data = "Hello World!" data = "Hello World!"
# Alice is the sender # Alice is the sender
alice = Cox::CryptoBox::SecretKey.new alice = Sodium::CryptoBox::SecretKey.new
# Bob is the recipient # Bob is the recipient
bob = Cox::CryptoBox::SecretKey.new bob = Sodium::CryptoBox::SecretKey.new
# Precompute a shared secret between alice and bob. # Precompute a shared secret between alice and bob.
pair = alice.pair bob.public_key pair = alice.pair bob.public_key
@ -105,7 +105,7 @@ nonce, encrypted = pair.encrypt data
bob.pair alice.public_key do |pair| bob.pair alice.public_key do |pair|
# Decrypt the message using Bob's secret key, and verify its signature against # Decrypt the message using Bob's secret key, and verify its signature against
# Alice's public key # Alice's public key
decrypted = Cox.decrypt(encrypted, nonce, alice.public, bob.secret) decrypted = Sodium.decrypt(encrypted, nonce, alice.public, bob.secret)
String.new(decrypted) # => "Hello World!" String.new(decrypted) # => "Hello World!"
end end
@ -115,41 +115,41 @@ end
```crystal ```crystal
message = "Hello World!" message = "Hello World!"
secret_key = Cox::Sign::SecretKey.new secret_key = Sodium::Sign::SecretKey.new
# Sign the message # Sign the message
signature = secret_key.sign_detached message signature = secret_key.sign_detached message
# Send secret_key.public_key to the recipient # Send secret_key.public_key to the recipient
public_key = Cox::Sign::PublicKey.new key_bytes public_key = Sodium::Sign::PublicKey.new key_bytes
# raises Cox::Error::VerificationFailed on failure. # raises Sodium::Error::VerificationFailed on failure.
public_key.verify_detached message, signature public_key.verify_detached message, signature
``` ```
### Secret Key Encryption ### Secret Key Encryption
```crystal ```crystal
key = Cox::SecretKey.new key = Sodium::SecretKey.new
message = "foobar" message = "foobar"
encrypted, nonce = key.encrypt_easy message encrypted, nonce = key.encrypt_easy message
# On the other side. # On the other side.
key = Cox::SecretKey.new key key = Sodium::SecretKey.new key
message = key.decrypt_easy encrypted, nonce message = key.decrypt_easy encrypted, nonce
``` ```
### Blake2b ### Blake2b
```crystal ```crystal
key = Bytes.new Cox::Digest::Blake2B::KEY_SIZE key = Bytes.new Sodium::Digest::Blake2B::KEY_SIZE
salt = Bytes.new Cox::Digest::Blake2B::SALT_SIZE salt = Bytes.new Sodium::Digest::Blake2B::SALT_SIZE
personal = Bytes.new Cox::Digest::Blake2B::PERSONAL_SIZE personal = Bytes.new Sodium::Digest::Blake2B::PERSONAL_SIZE
out_size = 64 # bytes between Cox::Digest::Blake2B::OUT_SIZE_MIN and Cox::Digest::Blake2B::OUT_SIZE_MAX out_size = 64 # bytes between Sodium::Digest::Blake2B::OUT_SIZE_MIN and Sodium::Digest::Blake2B::OUT_SIZE_MAX
data = "data".to_slice data = "data".to_slice
# output_size, key, salt, and personal are optional. # output_size, key, salt, and personal are optional.
digest = Cox::Digest::Blake2b.new out_size, key: key, salt: salt, personal: personal digest = Sodium::Digest::Blake2b.new out_size, key: key, salt: salt, personal: personal
digest.update data digest.update data
output = d.hexdigest output = d.hexdigest
@ -160,7 +160,7 @@ output = d.hexdigest
### Key derivation ### Key derivation
```crystal ```crystal
kdf = Cox::Kdf.new kdf = Sodium::Kdf.new
# kdf.derive(8_byte_context, subkey_id, subkey_size) # kdf.derive(8_byte_context, subkey_id, subkey_size)
subkey1 = kdf.derive "context1", 0, 16 subkey1 = kdf.derive "context1", 0, 16
@ -171,10 +171,10 @@ subkey4 = kdf.derive "context2", 1, 64
### Password Hashing ### Password Hashing
```crystal ```crystal
pwhash = Cox::Pwhash.new pwhash = Sodium::Pwhash.new
pwhash.memlimit = Cox::Pwhash::MEMLIMIT_MIN pwhash.memlimit = Sodium::Pwhash::MEMLIMIT_MIN
pwhash.opslimit = Cox::Pwhash::OPSLIMIT_MIN pwhash.opslimit = Sodium::Pwhash::OPSLIMIT_MIN
pass = "1234" pass = "1234"
hash = pwhash.hash_str pass hash = pwhash.hash_str pass
@ -203,7 +203,7 @@ Ops limit →
## Contributing ## Contributing
1. Fork it ( https://github.com/didactic-drunk/cox/fork ) 1. Fork it ( https://github.com/didactic-drunk/sodium.cr/fork )
2. **Install a formatting check git hook (ln -sf ../../scripts/git/pre-commit .git/hooks)** 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) 3. Create your feature branch (git checkout -b my-new-feature)
4. Commit your changes (git commit -am 'Add some feature') 4. Commit your changes (git commit -am 'Add some feature')

View File

@ -1,5 +1,5 @@
require "benchmark" require "benchmark"
require "../src/cox" require "../src/sodium"
require "openssl" require "openssl"
require "openssl/digest" require "openssl/digest"
@ -13,19 +13,19 @@ puts "'crystal run --release benchmarks/blake2b.cr sha1 sha256'"
Benchmark.ips(warmup: 0.5) do |bm| Benchmark.ips(warmup: 0.5) do |bm|
sizes.each_with_index do |size, i| sizes.each_with_index do |size, i|
bm.report "blake2b new obj per iter #{size}" do bm.report "blake2b new obj per iter #{size}" do
d = Cox::Digest::Blake2b.new 64 d = Sodium::Digest::Blake2b.new 64
d.update bufs[i] d.update bufs[i]
d.digest d.digest
end end
d = Cox::Digest::Blake2b.new output_size d = Sodium::Digest::Blake2b.new output_size
bm.report "blake2b reset per iter #{size}" do bm.report "blake2b reset per iter #{size}" do
d.reset d.reset
d.update bufs[i] d.update bufs[i]
d.digest d.digest
end end
d = Cox::Digest::Blake2b.new output_size d = Sodium::Digest::Blake2b.new output_size
dst = Bytes.new d.digest_size dst = Bytes.new d.digest_size
bm.report "blake2b reset reusing buffer per iter #{size}" do bm.report "blake2b reset reusing buffer per iter #{size}" do
d.reset d.reset

View File

@ -52,7 +52,7 @@ openssl speed -evp blake2b512 md5
Doing md5 for 3s on 16384 size blocks: 125954 md5's in 2.99s Doing md5 for 3s on 16384 size blocks: 125954 md5's in 2.99s
# In all tests crystal Cox::Blake2b(512) beats crystal OpenSSL::Digest::SHA256. # In all tests crystal Sodium::Digest::Blake2b(512) beats crystal OpenSSL::Digest::SHA256.
# Using .reset instead of creating new objects gives a significant performance boost when hashing small data sizes. # Using .reset instead of creating new objects gives a significant performance boost when hashing small data sizes.
# Reusing an output buffer with .reset gives a further performance boost when hashing small data sizes. # Reusing an output buffer with .reset gives a further performance boost when hashing small data sizes.
# New objects have a significant penalty for hashing small data sizes. Only problematic with iterative hashing or in a tight loop. # New objects have a significant penalty for hashing small data sizes. Only problematic with iterative hashing or in a tight loop.

View File

@ -9,7 +9,7 @@ export MIN_LIBSODIUM_VERSION=1.0.18
export LIBSODIUM_SHA256=6f504490b342a4f8a4c4a02fc9b866cbef8622d5df4e5452b46be121e46636c1 export LIBSODIUM_SHA256=6f504490b342a4f8a4c4a02fc9b866cbef8622d5df4e5452b46be121e46636c1
[ ! -z "$COX_BUILD_DEBUG" ] && export COX_BUILD_VERBOSE=1 [ ! -z "$SODIUM_BUILD_DEBUG" ] && export SODIUM_BUILD_VERBOSE=1
function version { echo "$@" | awk -F. '{ printf("%d%03d%03d%03d\n", $1,$2,$3,$4); }'; } function version { echo "$@" | awk -F. '{ printf("%d%03d%03d%03d\n", $1,$2,$3,$4); }'; }
@ -17,13 +17,13 @@ if `pkg-config libsodium --exists`; then
PKG_VER=`pkg-config libsodium --modversion` PKG_VER=`pkg-config libsodium --modversion`
if [ $(version "$PKG_VER") -ge $(version "$MIN_LIBSODIUM_VERSION") ]; then if [ $(version "$PKG_VER") -ge $(version "$MIN_LIBSODIUM_VERSION") ]; then
[ ! -z "$COX_BUILD_VERBOSE" ] && echo "Using packaged libsodium." [ ! -z "$SODIUM_BUILD_VERBOSE" ] && echo "Using packaged libsodium."
else else
[ ! -z "$COX_BUILD_VERBOSE" ] echo "System packaged libsodium is too old." [ ! -z "$SODIUM_BUILD_VERBOSE" ] echo "System packaged libsodium is too old."
export LIBSODIUM_INSTALL=1 export LIBSODIUM_INSTALL=1
fi fi
else else
[ ! -z "$COX_BUILD_VERBOSE" ] && echo "Missing libsodium system package." [ ! -z "$SODIUM_BUILD_VERBOSE" ] && echo "Missing libsodium system package."
export LIBSODIUM_INSTALL=1 export LIBSODIUM_INSTALL=1
fi fi

View File

@ -12,8 +12,8 @@ set -e
#export LIBSODIUM_INSTALL=1 #export LIBSODIUM_INSTALL=1
if [ "$LIBSODIUM_INSTALL" != "1" ]; then if [ "$LIBSODIUM_INSTALL" != "1" ]; then
[ ! -z "$COX_BUILD_VERBOSE" ] echo "Skipping libsodium build." [ ! -z "$SODIUM_BUILD_VERBOSE" ] && echo "Skipping libsodium build."
exit exit 0
fi fi
@ -22,7 +22,7 @@ cd "$LIBSODIUM_BUILD_DIR"
if [ ! -f "$LIBSODIUM_INSTALL_PATH/include/sodium.h" ]; then if [ ! -f "$LIBSODIUM_INSTALL_PATH/include/sodium.h" ]; then
[ ! -z "$COX_BUILD_DEBUG" ] && set -x [ ! -z "$SODIUM_BUILD_DEBUG" ] && set -x
DIRNAME=libsodium-"$MIN_LIBSODIUM_VERSION" DIRNAME=libsodium-"$MIN_LIBSODIUM_VERSION"
TGZ_FILENAME="$DIRNAME".tar.gz TGZ_FILENAME="$DIRNAME".tar.gz
@ -58,11 +58,11 @@ if [ ! -f "$LIBSODIUM_INSTALL_PATH/include/sodium.h" ]; then
touch .make.install.done touch .make.install.done
fi fi
[ ! -z "$COX_BUILD_VERBOSE" ] && echo "Finished building libsodium." [ ! -z "$SODIUM_BUILD_VERBOSE" ] && echo "Finished building libsodium."
else else
# find "$LIBSODIUM_INSTALL_PATH" # find "$LIBSODIUM_INSTALL_PATH"
[ ! -z "$COX_BUILD_VERBOSE" ] && echo "Using already built libsodium." [ ! -z "$SODIUM_BUILD_VERBOSE" ] && echo "Using already built libsodium."
fi fi
exit 0 exit 0

View File

@ -1,5 +1,4 @@
require "../src/cox" require "../src/sodium"
require "tallboy"
if ARGV.empty? if ARGV.empty?
puts "Help select Pwhash ops/mem limits for your application." puts "Help select Pwhash ops/mem limits for your application."
@ -15,8 +14,8 @@ time_limit = if t = ARGV.shift?
else else
time_min * 4 time_min * 4
end end
mem_limit = (ARGV.shift?.try &.to_i || (Cox::Pwhash::MEMLIMIT_MAX)).to_u64 mem_limit = (ARGV.shift?.try &.to_i || (Sodium::Pwhash::MEMLIMIT_MAX)).to_u64
pwhash = Cox::Pwhash.new pwhash = Sodium::Pwhash.new
pass = "1234" pass = "1234"
# data = Array(Array({UInt64, UInt64, Float64})).new # data = Array(Array({UInt64, UInt64, Float64})).new
@ -36,9 +35,9 @@ def bytes_str(b)
"%5d#{suffix}" % b "%5d#{suffix}" % b
end end
pwhash.memlimit = Cox::Pwhash::MEMLIMIT_MIN pwhash.memlimit = Sodium::Pwhash::MEMLIMIT_MIN
loop do loop do
pwhash.opslimit = Cox::Pwhash::OPSLIMIT_MIN pwhash.opslimit = Sodium::Pwhash::OPSLIMIT_MIN
row = ["%5dK" % (pwhash.memlimit / 1024)] row = ["%5dK" % (pwhash.memlimit / 1024)]
data << row data << row
@ -72,7 +71,7 @@ loop do
puts "" puts ""
break if pwhash.memlimit >= mem_limit break if pwhash.memlimit >= mem_limit
break if pwhash.opslimit == Cox::Pwhash::OPSLIMIT_MIN # Couldn't get past 1 iteration before going over time. break if pwhash.opslimit == Sodium::Pwhash::OPSLIMIT_MIN # Couldn't get past 1 iteration before going over time.
pwhash.memlimit *= 4 pwhash.memlimit *= 4
end end
# header << "Ops limit" # header << "Ops limit"

View File

@ -1,4 +1,4 @@
name: cox name: sodium.cr
version: 0.1.0 version: 0.1.0
authors: authors:
@ -8,6 +8,6 @@ development_dependencies:
ghshard: ghshard:
github: bcardiff/ghshard github: bcardiff/ghshard
crystal: 0.24.1 crystal: 0.28.0
license: MIT license: MIT

View File

@ -1,6 +1,6 @@
require "./spec_helper" require "./spec_helper"
describe Cox do describe Sodium do
# Finished in 71 microseconds # Finished in 71 microseconds
# 1 examples, 2 failures, 5 errors, 0 pending # 1 examples, 2 failures, 5 errors, 0 pending
# What a man. # What a man.

View File

@ -23,10 +23,10 @@ test_vectors = [
}, },
] ]
describe Cox::Digest::Blake2b do describe Sodium::Digest::Blake2b do
it "libsodium comparisons" do it "libsodium comparisons" do
libsodium_comparisons.each do |vec| libsodium_comparisons.each do |vec|
d = Cox::Digest::Blake2b.new vec[:out_size], key: vec[:key].try(&.hexbytes) d = Sodium::Digest::Blake2b.new vec[:out_size], key: vec[:key].try(&.hexbytes)
d.update vec[:input].hexbytes d.update vec[:input].hexbytes
d.hexdigest.should eq vec[:output] d.hexdigest.should eq vec[:output]
end end
@ -34,31 +34,31 @@ describe Cox::Digest::Blake2b do
it "test vectors" do it "test vectors" do
test_vectors.each do |vec| test_vectors.each do |vec|
d = Cox::Digest::Blake2b.new 64, key: vec[:key].hexbytes d = Sodium::Digest::Blake2b.new 64, key: vec[:key].hexbytes
d.update vec[:input].hexbytes d.update vec[:input].hexbytes
d.hexdigest.should eq vec[:output] d.hexdigest.should eq vec[:output]
end end
end end
it "produces different output with different salt or personal params" do it "produces different output with different salt or personal params" do
key = Bytes.new Cox::Digest::Blake2b::KEY_SIZE key = Bytes.new Sodium::Digest::Blake2b::KEY_SIZE
salt = Bytes.new Cox::Digest::Blake2b::SALT_SIZE salt = Bytes.new Sodium::Digest::Blake2b::SALT_SIZE
salt2 = Bytes.new Cox::Digest::Blake2b::SALT_SIZE salt2 = Bytes.new Sodium::Digest::Blake2b::SALT_SIZE
salt2 = salt.dup salt2 = salt.dup
salt2[0] = 1 salt2[0] = 1
personal = Bytes.new Cox::Digest::Blake2b::PERSONAL_SIZE personal = Bytes.new Sodium::Digest::Blake2b::PERSONAL_SIZE
personal2 = personal.dup personal2 = personal.dup
personal2[0] = 1 personal2[0] = 1
d = Cox::Digest::Blake2b.new key: key, salt: salt, personal: personal d = Sodium::Digest::Blake2b.new key: key, salt: salt, personal: personal
d.update "foo".to_slice d.update "foo".to_slice
output = d.hexdigest output = d.hexdigest
d = Cox::Digest::Blake2b.new key: key, salt: salt2, personal: personal d = Sodium::Digest::Blake2b.new key: key, salt: salt2, personal: personal
d.update "foo".to_slice d.update "foo".to_slice
saltout = d.hexdigest saltout = d.hexdigest
d = Cox::Digest::Blake2b.new key: key, salt: salt, personal: personal2 d = Sodium::Digest::Blake2b.new key: key, salt: salt, personal: personal2
d.update "foo".to_slice d.update "foo".to_slice
personalout = d.hexdigest personalout = d.hexdigest
@ -69,19 +69,19 @@ describe Cox::Digest::Blake2b do
it "raises on invalid " do it "raises on invalid " do
expect_raises ArgumentError do expect_raises ArgumentError do
Cox::Digest::Blake2b.new key: Bytes.new(128) Sodium::Digest::Blake2b.new key: Bytes.new(128)
end end
expect_raises ArgumentError do expect_raises ArgumentError do
Cox::Digest::Blake2b.new salt: Bytes.new(1) Sodium::Digest::Blake2b.new salt: Bytes.new(1)
end end
expect_raises ArgumentError do expect_raises ArgumentError do
Cox::Digest::Blake2b.new salt: Bytes.new(128) Sodium::Digest::Blake2b.new salt: Bytes.new(128)
end end
expect_raises ArgumentError do expect_raises ArgumentError do
Cox::Digest::Blake2b.new personal: Bytes.new(128) Sodium::Digest::Blake2b.new personal: Bytes.new(128)
end end
end end
end end

View File

@ -1,13 +1,13 @@
require "../../spec_helper" require "../../spec_helper"
require "../../../src/cox/cipher/chalsa" require "../../../src/sodium/cipher/chalsa"
{% for name in %w(XSalsa20 Salsa20 XChaCha20 ChaCha20Ietf ChaCha20) %} {% for name in %w(XSalsa20 Salsa20 XChaCha20 ChaCha20Ietf ChaCha20) %}
# TODO: verify against test vectors. # TODO: verify against test vectors.
describe Cox::Cipher::{{ name.id }} do describe Sodium::Cipher::{{ name.id }} do
it "xors" do it "xors" do
data = Bytes.new(100) data = Bytes.new(100)
cipher1 = Cox::Cipher::{{ name.id }}.new cipher1 = Sodium::Cipher::{{ name.id }}.new
cipher2 = Cox::Cipher::{{ name.id }}.new cipher2 = Sodium::Cipher::{{ name.id }}.new
key = cipher1.random_key key = cipher1.random_key
nonce = cipher1.random_nonce nonce = cipher1.random_nonce
output = cipher1.update data output = cipher1.update data

View File

@ -1,14 +1,14 @@
require "../../spec_helper" require "../../spec_helper"
describe Cox::CryptoBox::SecretKey do describe Sodium::CryptoBox::SecretKey do
it "easy encrypt/decrypt" do it "easy encrypt/decrypt" do
data = "Hello World!" data = "Hello World!"
# Alice is the sender # Alice is the sender
alice = Cox::CryptoBox::SecretKey.new alice = Sodium::CryptoBox::SecretKey.new
# Bob is the recipient # Bob is the recipient
bob = Cox::CryptoBox::SecretKey.new bob = Sodium::CryptoBox::SecretKey.new
# Encrypt a message for Bob using his public key, signing it with Alice's # Encrypt a message for Bob using his public key, signing it with Alice's
# secret key # secret key

View File

@ -2,12 +2,12 @@ require "../spec_helper"
CONTEXT = "8_bytess" CONTEXT = "8_bytess"
describe Cox::Kdf do describe Sodium::Kdf do
it "generates master key" do it "generates master key" do
kdf1 = Cox::Kdf.new kdf1 = Sodium::Kdf.new
# verify loading saved key # verify loading saved key
kdf2 = Cox::Kdf.from_base64 kdf1.to_base64 kdf2 = Sodium::Kdf.from_base64 kdf1.to_base64
# verify generated subkey's are the same after loading # verify generated subkey's are the same after loading
key1_s1 = kdf1.derive CONTEXT, 0, 16 key1_s1 = kdf1.derive CONTEXT, 0, 16
@ -16,7 +16,7 @@ describe Cox::Kdf do
end end
it "generates different keys" do it "generates different keys" do
kdf1 = Cox::Kdf.new kdf1 = Sodium::Kdf.new
subkey1 = kdf1.derive CONTEXT, 0, 16 subkey1 = kdf1.derive CONTEXT, 0, 16
subkey2 = kdf1.derive CONTEXT, 1, 16 subkey2 = kdf1.derive CONTEXT, 1, 16
subkey1.should_not eq subkey2 subkey1.should_not eq subkey2

View File

@ -1,27 +1,27 @@
require "../spec_helper" require "../spec_helper"
private def pw_min private def pw_min
pwhash = Cox::Pwhash.new pwhash = Sodium::Pwhash.new
# set to minimum to speed up tests # set to minimum to speed up tests
pwhash.memlimit = Cox::Pwhash::MEMLIMIT_MIN pwhash.memlimit = Sodium::Pwhash::MEMLIMIT_MIN
pwhash.opslimit = Cox::Pwhash::OPSLIMIT_MIN pwhash.opslimit = Sodium::Pwhash::OPSLIMIT_MIN
pwhash pwhash
end end
describe Cox::Pwhash do describe Sodium::Pwhash do
it "hashes and verifies a password" do it "hashes and verifies a password" do
pwhash = pw_min pwhash = pw_min
pass = "1234" pass = "1234"
hash = pwhash.store pass hash = pwhash.store pass
pwhash.verify hash, pass pwhash.verify hash, pass
expect_raises(Cox::Pwhash::PasswordVerifyError) do expect_raises(Sodium::Pwhash::PasswordVerifyError) do
pwhash.verify hash, "5678" pwhash.verify hash, "5678"
end end
pwhash.needs_rehash?(hash).should be_false pwhash.needs_rehash?(hash).should be_false
pwhash.opslimit = Cox::Pwhash::OPSLIMIT_MAX pwhash.opslimit = Sodium::Pwhash::OPSLIMIT_MAX
pwhash.needs_rehash?(hash).should be_true pwhash.needs_rehash?(hash).should be_true
end end
@ -34,7 +34,7 @@ describe Cox::Pwhash do
it "derives a key from a password" do it "derives a key from a password" do
pwhash = pw_min pwhash = pw_min
pwhash.algorithm = Cox::Pwhash::Algorithm::Argon2id13 pwhash.algorithm = Sodium::Pwhash::Algorithm::Argon2id13
salt = pwhash.salt salt = pwhash.salt
key1 = pwhash.key_derive salt, "foo", 16 key1 = pwhash.key_derive salt, "foo", 16
key2 = pwhash.key_derive salt, "foo", 16 key2 = pwhash.key_derive salt, "foo", 16

View File

@ -1,15 +1,15 @@
require "../spec_helper" require "../spec_helper"
describe Cox::SecretBox do describe Sodium::SecretBox do
it "encrypts/decrypts" do it "encrypts/decrypts" do
key = Cox::SecretBox.new key = Sodium::SecretBox.new
message = "foobar" message = "foobar"
encrypted, nonce = key.encrypt_easy message encrypted, nonce = key.encrypt_easy message
decrypted = key.decrypt_easy encrypted, nonce decrypted = key.decrypt_easy encrypted, nonce
message.should eq String.new(decrypted) message.should eq String.new(decrypted)
expect_raises(Cox::Error::DecryptionFailed) do expect_raises(Sodium::Error::DecryptionFailed) do
key.decrypt_easy "badmsgbadmsgbadmsgbadmsgbadmsg".to_slice, nonce key.decrypt_easy "badmsgbadmsgbadmsgbadmsgbadmsg".to_slice, nonce
end end
end end

View File

@ -1,10 +1,10 @@
require "../../spec_helper" require "../../spec_helper"
require "../../../src/cox/sign/secret_key" require "../../../src/sodium/sign/secret_key"
describe Cox::Sign::SecretKey do describe Sodium::Sign::SecretKey do
it "signs and verifies" do it "signs and verifies" do
message = "foo" message = "foo"
skey = Cox::Sign::SecretKey.new skey = Sodium::Sign::SecretKey.new
sig = skey.sign_detached message sig = skey.sign_detached message
skey.public_key.verify_detached message, sig skey.public_key.verify_detached message, sig
@ -12,10 +12,10 @@ describe Cox::Sign::SecretKey do
it "signs and fails" do it "signs and fails" do
message = "foo" message = "foo"
skey = Cox::Sign::SecretKey.new skey = Sodium::Sign::SecretKey.new
sig = skey.sign_detached message sig = skey.sign_detached message
expect_raises Cox::Error::VerificationFailed do expect_raises Sodium::Error::VerificationFailed do
skey.public_key.verify_detached "bar", sig skey.public_key.verify_detached "bar", sig
end end
end end

View File

@ -1,2 +1,2 @@
require "spec" require "spec"
require "../src/cox" require "../src/sodium"

View File

@ -1,6 +1,6 @@
require "random/secure" require "random/secure"
module Cox module Sodium
class Error < ::Exception class Error < ::Exception
class VerificationFailed < Error class VerificationFailed < Error
end end
@ -14,8 +14,8 @@ module Cox
end end
end end
require "./cox/**" require "./sodium/**"
if Cox::LibSodium.sodium_init == -1 if Sodium::LibSodium.sodium_init == -1
abort "Failed to init libsodium" abort "Failed to init libsodium"
end end

View File

@ -1,6 +1,6 @@
require "../lib_sodium" require "../lib_sodium"
module Cox::Cipher module Sodium::Cipher
# The great beat you can eat! # The great beat you can eat!
# #
# What? They're both dance? # What? They're both dance?
@ -69,7 +69,7 @@ module Cox::Cipher
# #
# This class mimicks the OpenSSL::Cipher interface with minor differences. # This class mimicks the OpenSSL::Cipher interface with minor differences.
# #
# See `spec/cox/cipher/chalsa_spec.cr` for examples on how to use this class. # See `spec/sodium/cipher/chalsa_spec.cr` for examples on how to use this class.
class {{ key.id }} < Chalsa class {{ key.id }} < Chalsa
# Xor's src with the cipher output and places in dst. # Xor's src with the cipher output and places in dst.
# #
@ -78,12 +78,12 @@ module Cox::Cipher
if (key = @key) && (nonce = @nonce) if (key = @key) && (nonce = @nonce)
raise ArgumentError.new("src and dst bytesize must be identical") if src.bytesize != dst.bytesize raise ArgumentError.new("src and dst bytesize must be identical") if src.bytesize != dst.bytesize
if LibSodium.crypto_stream_{{ val.id }}_xor_ic(dst, src, src.bytesize, nonce, @offset, key) != 0 if LibSodium.crypto_stream_{{ val.id }}_xor_ic(dst, src, src.bytesize, nonce, @offset, key) != 0
raise Cox::Error.new("crypto_stream_{{ val.id }}_xor_ic") raise Sodium::Error.new("crypto_stream_{{ val.id }}_xor_ic")
end end
@offset += src.bytesize @offset += src.bytesize
dst dst
else else
raise Cox::Error.new("key and nonce must be set before calling update #{@key.nil?} #{@nonce.nil?}") raise Sodium::Error.new("key and nonce must be set before calling update #{@key.nil?} #{@nonce.nil?}")
end end
end end

View File

@ -1,6 +1,6 @@
require "../lib_sodium" require "../lib_sodium"
module Cox::CryptoBox module Sodium::CryptoBox
class Pair class Pair
include Wipe include Wipe

View File

@ -1,6 +1,6 @@
require "../lib_sodium" require "../lib_sodium"
module Cox::CryptoBox module Sodium::CryptoBox
class PublicKey < Key class PublicKey < Key
include Wipe include Wipe
KEY_SIZE = LibSodium::PUBLIC_KEY_SIZE KEY_SIZE = LibSodium::PUBLIC_KEY_SIZE

View File

@ -1,6 +1,6 @@
require "../lib_sodium" require "../lib_sodium"
module Cox::CryptoBox module Sodium::CryptoBox
class SecretKey < Key class SecretKey < Key
include Wipe include Wipe
KEY_SIZE = LibSodium::SECRET_KEY_SIZE KEY_SIZE = LibSodium::SECRET_KEY_SIZE

View File

@ -1,6 +1,6 @@
require "openssl/digest/digest_base" require "openssl/digest/digest_base"
module Cox::Digest module Sodium::Digest
class Blake2b class Blake2b
# provides copying digest/hexdigest methods # provides copying digest/hexdigest methods
include OpenSSL::DigestBase include OpenSSL::DigestBase
@ -57,13 +57,13 @@ module Cox::Digest
personal = @have_personal ? @personal.to_unsafe : nil personal = @have_personal ? @personal.to_unsafe : nil
if LibSodium.crypto_generichash_blake2b_init_salt_personal(@state, key, @key_size, @digest_size, salt, personal) != 0 if LibSodium.crypto_generichash_blake2b_init_salt_personal(@state, key, @key_size, @digest_size, salt, personal) != 0
raise Cox::Error.new("blake2b_init_key_salt_personal") raise Sodium::Error.new("blake2b_init_key_salt_personal")
end end
end end
def update(data : Bytes) def update(data : Bytes)
if LibSodium.crypto_generichash_blake2b_update(@state, data, data.bytesize) != 0 if LibSodium.crypto_generichash_blake2b_update(@state, data, data.bytesize) != 0
raise Cox::Error.new("crypto_generichash_blake2b_update") raise Sodium::Error.new("crypto_generichash_blake2b_update")
end end
self self
@ -81,7 +81,7 @@ module Cox::Digest
# Use .digest or .hexdigest instead. # Use .digest or .hexdigest instead.
def finish(dst : Bytes) : Bytes def finish(dst : Bytes) : Bytes
if LibSodium.crypto_generichash_blake2b_final(@state, dst, dst.bytesize) != 0 if LibSodium.crypto_generichash_blake2b_final(@state, dst, dst.bytesize) != 0
raise Cox::Error.new("crypto_generichash_blake2b_final") raise Sodium::Error.new("crypto_generichash_blake2b_final")
end end
dst dst

View File

@ -1,4 +1,4 @@
module Cox module Sodium
class Kdf class Kdf
property bytes : Bytes property bytes : Bytes
@ -25,7 +25,7 @@ module Cox
subkey = Bytes.new subkey_size subkey = Bytes.new subkey_size
if (ret = LibSodium.crypto_kdf_derive_from_key(subkey, subkey.bytesize, subkey_id, context, @bytes)) != 0 if (ret = LibSodium.crypto_kdf_derive_from_key(subkey, subkey.bytesize, subkey_id, context, @bytes)) != 0
raise Cox::Error.new("crypto_kdf_derive_from_key returned #{ret} (subkey size is probably out of range)") raise Sodium::Error.new("crypto_kdf_derive_from_key returned #{ret} (subkey size is probably out of range)")
end end
subkey subkey
end end

View File

@ -1,4 +1,4 @@
module Cox module Sodium
abstract class Key abstract class Key
abstract def bytes abstract def bytes

View File

@ -1,4 +1,4 @@
module Cox module Sodium
@[Link(ldflags: "`#{__DIR__}/../../build/pkg-libs.sh #{__DIR__}/../..`")] @[Link(ldflags: "`#{__DIR__}/../../build/pkg-libs.sh #{__DIR__}/../..`")]
lib LibSodium lib LibSodium
fun sodium_init : LibC::Int fun sodium_init : LibC::Int

View File

@ -1,7 +1,7 @@
require "./lib_sodium" require "./lib_sodium"
require "random/secure" require "random/secure"
module Cox module Sodium
class Nonce class Nonce
NONCE_SIZE = LibSodium::NONCE_SIZE NONCE_SIZE = LibSodium::NONCE_SIZE

View File

@ -1,11 +1,11 @@
module Cox module Sodium
# [Argon2 Password Hashing](https://libsodium.gitbook.io/doc/password_hashing/the_argon2i_function) # [Argon2 Password Hashing](https://libsodium.gitbook.io/doc/password_hashing/the_argon2i_function)
# * #store #verify #needs_rehash? are used together for password verification. # * #store #verify #needs_rehash? are used together for password verification.
# * #key_derive is used on it's own to generate password based keys. # * #key_derive is used on it's own to generate password based keys.
# #
# See `examples/pwhash_selector.cr` for help on selecting parameters. # See `examples/pwhash_selector.cr` for help on selecting parameters.
class Pwhash class Pwhash
class PasswordVerifyError < Cox::Error class PasswordVerifyError < Sodium::Error
end end
OPSLIMIT_MIN = LibSodium.crypto_pwhash_opslimit_min OPSLIMIT_MIN = LibSodium.crypto_pwhash_opslimit_min
@ -39,7 +39,7 @@ module Cox
def store(pass) def store(pass)
outstr = Bytes.new LibSodium::PWHASH_STR_SIZE outstr = Bytes.new LibSodium::PWHASH_STR_SIZE
if LibSodium.crypto_pwhash_str(outstr, pass, pass.bytesize, @opslimit, @memlimit) != 0 if LibSodium.crypto_pwhash_str(outstr, pass, pass.bytesize, @opslimit, @memlimit) != 0
raise Cox::Error.new("crypto_pwhash_str") raise Sodium::Error.new("crypto_pwhash_str")
end end
outstr outstr
end end
@ -65,7 +65,7 @@ module Cox
when 1 when 1
true true
else else
raise Cox::Error.new("crypto_pwhash_str_needs_rehash") raise Sodium::Error.new("crypto_pwhash_str_needs_rehash")
end end
end end
@ -76,7 +76,7 @@ module Cox
if alg = algorithm if alg = algorithm
key = Bytes.new key_bytes key = Bytes.new key_bytes
if LibSodium.crypto_pwhash(key, key.bytesize, pass, pass.bytesize, salt, @opslimit, @memlimit, alg) != 0 if LibSodium.crypto_pwhash(key, key.bytesize, pass, pass.bytesize, salt, @opslimit, @memlimit, alg) != 0
raise Cox::Error.new("crypto_pwhash_str") raise Sodium::Error.new("crypto_pwhash_str")
end end
key key
else else

View File

@ -1,15 +1,15 @@
require "./lib_sodium" require "./lib_sodium"
module Cox module Sodium
# [https://libsodium.gitbook.io/doc/secret-key_cryptography](https://libsodium.gitbook.io/doc/secret-key_cryptography) # [https://libsodium.gitbook.io/doc/secret-key_cryptography](https://libsodium.gitbook.io/doc/secret-key_cryptography)
# #
# ```crystal # ```crystal
# key = Cox::SecretKey.new # key = Sodium::SecretKey.new
# message = "foobar" # message = "foobar"
# encrypted, nonce = key.encrypt_easy message # encrypted, nonce = key.encrypt_easy message
# #
# # On the other side. # # On the other side.
# key = Cox::SecretKey.new key # key = Sodium::SecretKey.new key
# message = key.decrypt_easy encrypted, nonce # message = key.decrypt_easy encrypted, nonce
# ``` # ```
class SecretBox < Key class SecretBox < Key
@ -54,14 +54,14 @@ module Cox
raise ArgumentError.new("dst.bytesize must be src.bytesize + MAC_SIZE, got #{dst.bytesize}") raise ArgumentError.new("dst.bytesize must be src.bytesize + MAC_SIZE, got #{dst.bytesize}")
end end
if LibSodium.crypto_secretbox_easy(dst, src, src.bytesize, nonce.to_slice, @bytes) != 0 if LibSodium.crypto_secretbox_easy(dst, src, src.bytesize, nonce.to_slice, @bytes) != 0
raise Cox::Error.new("crypto_secretbox_easy") raise Sodium::Error.new("crypto_secretbox_easy")
end end
dst dst
end end
def decrypt_easy(data : Bytes, nonce : Nonce) : Bytes def decrypt_easy(data : Bytes, nonce : Nonce) : Bytes
output_size = data.bytesize - MAC_SIZE output_size = data.bytesize - MAC_SIZE
raise Cox::Error::DecryptionFailed.new("encrypted data too small #{data.bytesize}") if output_size <= 0 raise Sodium::Error::DecryptionFailed.new("encrypted data too small #{data.bytesize}") if output_size <= 0
output = Bytes.new output_size output = Bytes.new output_size
decrypt_easy(data, output, nonce) decrypt_easy(data, output, nonce)
end end
@ -71,7 +71,7 @@ module Cox
raise ArgumentError.new("dst.bytesize must be src.bytesize - MAC_SIZE, got #{dst.bytesize}") raise ArgumentError.new("dst.bytesize must be src.bytesize - MAC_SIZE, got #{dst.bytesize}")
end end
if LibSodium.crypto_secretbox_open_easy(dst, src, src.bytesize, nonce.to_slice, @bytes) != 0 if LibSodium.crypto_secretbox_open_easy(dst, src, src.bytesize, nonce.to_slice, @bytes) != 0
raise Cox::Error::DecryptionFailed.new("crypto_secretbox_easy") raise Sodium::Error::DecryptionFailed.new("crypto_secretbox_easy")
end end
dst dst
end end

View File

@ -1,6 +1,6 @@
require "../lib_sodium" require "../lib_sodium"
module Cox module Sodium
class Sign::PublicKey < Key class Sign::PublicKey < Key
include Wipe include Wipe
KEY_SIZE = LibSodium::PUBLIC_SIGN_SIZE KEY_SIZE = LibSodium::PUBLIC_SIGN_SIZE
@ -24,7 +24,7 @@ module Cox
v = LibSodium.crypto_sign_verify_detached sig, message, message.bytesize, @bytes v = LibSodium.crypto_sign_verify_detached sig, message, message.bytesize, @bytes
if v != 0 if v != 0
raise Cox::Error::VerificationFailed.new("crypto_sign_verify_detached") raise Sodium::Error::VerificationFailed.new("crypto_sign_verify_detached")
end end
end end
end end

View File

@ -1,7 +1,7 @@
require "../lib_sodium" require "../lib_sodium"
module Cox module Sodium
class Sign::SecretKey < Cox::Key class Sign::SecretKey < Sodium::Key
include Wipe include Wipe
KEY_SIZE = LibSodium::SECRET_SIGN_SIZE KEY_SIZE = LibSodium::SECRET_SIGN_SIZE

View File

@ -1,3 +1,3 @@
module Cox module Sodium
VERSION = "0.1.0" VERSION = "0.1.0"
end end

View File

@ -1,4 +1,4 @@
module Cox::Wipe module Sodium::Wipe
@closed = false @closed = false
def close def close
@ -9,7 +9,7 @@ module Cox::Wipe
protected def wipe protected def wipe
return if @closed return if @closed
Cox.memzero @bytes Sodium.memzero @bytes
end end
def finalize def finalize