Rename project from "cox" to "sodium.cr".
parent
8e939b9518
commit
a4b1b8071c
|
@ -3,7 +3,7 @@ os:
|
|||
- linux
|
||||
- osx
|
||||
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:
|
||||
- export LIBSODIUM_BUILD_DIR=$HOME/libsodium
|
||||
after_failure:
|
||||
|
|
66
README.md
66
README.md
|
@ -1,6 +1,6 @@
|
|||
# cox
|
||||
[![Build Status](https://travis-ci.org/didactic-drunk/cox.svg?branch=master)](https://travis-ci.org/didactic-drunk/cox)
|
||||
[![Docs](https://img.shields.io/badge/docs-available-brightgreen.svg)](https://didactic-drunk.github.io/cox/)
|
||||
# sodium.cr
|
||||
[![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/sodium.cr/)
|
||||
|
||||
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
|
||||
dependencies:
|
||||
cox:
|
||||
github: didactic-drunk/cox
|
||||
sodium.cr:
|
||||
github: didactic-drunk/sodium.cr
|
||||
```
|
||||
|
||||
## What should I use for my application?
|
||||
|
@ -65,16 +65,16 @@ dependencies:
|
|||
| Class | |
|
||||
| --- | --- |
|
||||
| `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. |
|
||||
| [`Cox::Sign::SecretKey`](https://didactic-drunk.github.io/cox/Cox/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::CryptoBox::SecretKey`](https://didactic-drunk.github.io/sodium.cr/Sodium/CryptoBox/SecretKey.html) | I want to encrypt + authenticate data using public key encryption. |
|
||||
| [`Sodium::Sign::SecretKey`](https://didactic-drunk.github.io/sodium.cr/Sodium/Sign/SecretKey.html) | I want to sign or verify messages without encryption. |
|
||||
| [`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) |
|
||||
| [`Cox::Digest::Blake2b`](https://didactic-drunk.github.io/cox/Cox/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) |
|
||||
| `Cox::Pwhash` | I want to hash a password and store it. |
|
||||
| `Cox::Pwhash` | I want to derive a key from a password. |
|
||||
| `Cox::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::Digest::Blake2b`](https://didactic-drunk.github.io/sodium.cr/Sodium/Digest::Blake2b.html) | I want to hash data fast and securely. |
|
||||
| `Sodium::Digest::SipHash` | I want to hash data really fast and less securely. (Not implemented yet) |
|
||||
| `Sodium::Pwhash` | I want to hash a password and store it. |
|
||||
| `Sodium::Pwhash` | I want to derive a key from a password. |
|
||||
| `Sodium::Kdf` | I have a high quality master key and want to make subkeys. |
|
||||
| [`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. |
|
||||
|
||||
|
||||
|
@ -84,15 +84,15 @@ The `specs` provide the best examples of how to use or misuse this shard.
|
|||
|
||||
### CryptoBox easy encryption
|
||||
```crystal
|
||||
require "cox"
|
||||
require "sodium"
|
||||
|
||||
data = "Hello World!"
|
||||
|
||||
# Alice is the sender
|
||||
alice = Cox::CryptoBox::SecretKey.new
|
||||
alice = Sodium::CryptoBox::SecretKey.new
|
||||
|
||||
# Bob is the recipient
|
||||
bob = Cox::CryptoBox::SecretKey.new
|
||||
bob = Sodium::CryptoBox::SecretKey.new
|
||||
|
||||
# Precompute a shared secret between alice and bob.
|
||||
pair = alice.pair bob.public_key
|
||||
|
@ -105,7 +105,7 @@ nonce, encrypted = pair.encrypt data
|
|||
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)
|
||||
decrypted = Sodium.decrypt(encrypted, nonce, alice.public, bob.secret)
|
||||
|
||||
String.new(decrypted) # => "Hello World!"
|
||||
end
|
||||
|
@ -115,41 +115,41 @@ end
|
|||
```crystal
|
||||
message = "Hello World!"
|
||||
|
||||
secret_key = Cox::Sign::SecretKey.new
|
||||
secret_key = Sodium::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
|
||||
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
|
||||
```
|
||||
|
||||
### Secret Key Encryption
|
||||
```crystal
|
||||
key = Cox::SecretKey.new
|
||||
key = Sodium::SecretKey.new
|
||||
|
||||
message = "foobar"
|
||||
encrypted, nonce = key.encrypt_easy message
|
||||
|
||||
# On the other side.
|
||||
key = Cox::SecretKey.new key
|
||||
key = Sodium::SecretKey.new key
|
||||
message = key.decrypt_easy encrypted, nonce
|
||||
```
|
||||
|
||||
### Blake2b
|
||||
```crystal
|
||||
key = Bytes.new Cox::Digest::Blake2B::KEY_SIZE
|
||||
salt = Bytes.new Cox::Digest::Blake2B::SALT_SIZE
|
||||
personal = Bytes.new Cox::Digest::Blake2B::PERSONAL_SIZE
|
||||
out_size = 64 # bytes between Cox::Digest::Blake2B::OUT_SIZE_MIN and Cox::Digest::Blake2B::OUT_SIZE_MAX
|
||||
key = Bytes.new Sodium::Digest::Blake2B::KEY_SIZE
|
||||
salt = Bytes.new Sodium::Digest::Blake2B::SALT_SIZE
|
||||
personal = Bytes.new Sodium::Digest::Blake2B::PERSONAL_SIZE
|
||||
out_size = 64 # bytes between Sodium::Digest::Blake2B::OUT_SIZE_MIN and Sodium::Digest::Blake2B::OUT_SIZE_MAX
|
||||
data = "data".to_slice
|
||||
|
||||
# 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
|
||||
output = d.hexdigest
|
||||
|
||||
|
@ -160,7 +160,7 @@ output = d.hexdigest
|
|||
|
||||
### Key derivation
|
||||
```crystal
|
||||
kdf = Cox::Kdf.new
|
||||
kdf = Sodium::Kdf.new
|
||||
|
||||
# kdf.derive(8_byte_context, subkey_id, subkey_size)
|
||||
subkey1 = kdf.derive "context1", 0, 16
|
||||
|
@ -171,10 +171,10 @@ subkey4 = kdf.derive "context2", 1, 64
|
|||
|
||||
### Password Hashing
|
||||
```crystal
|
||||
pwhash = Cox::Pwhash.new
|
||||
pwhash = Sodium::Pwhash.new
|
||||
|
||||
pwhash.memlimit = Cox::Pwhash::MEMLIMIT_MIN
|
||||
pwhash.opslimit = Cox::Pwhash::OPSLIMIT_MIN
|
||||
pwhash.memlimit = Sodium::Pwhash::MEMLIMIT_MIN
|
||||
pwhash.opslimit = Sodium::Pwhash::OPSLIMIT_MIN
|
||||
|
||||
pass = "1234"
|
||||
hash = pwhash.hash_str pass
|
||||
|
@ -203,7 +203,7 @@ Ops limit →
|
|||
|
||||
## 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)**
|
||||
3. Create your feature branch (git checkout -b my-new-feature)
|
||||
4. Commit your changes (git commit -am 'Add some feature')
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
require "benchmark"
|
||||
require "../src/cox"
|
||||
require "../src/sodium"
|
||||
require "openssl"
|
||||
require "openssl/digest"
|
||||
|
||||
|
@ -13,19 +13,19 @@ puts "'crystal run --release benchmarks/blake2b.cr sha1 sha256'"
|
|||
Benchmark.ips(warmup: 0.5) do |bm|
|
||||
sizes.each_with_index do |size, i|
|
||||
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.digest
|
||||
end
|
||||
|
||||
d = Cox::Digest::Blake2b.new output_size
|
||||
d = Sodium::Digest::Blake2b.new output_size
|
||||
bm.report "blake2b reset per iter #{size}" do
|
||||
d.reset
|
||||
d.update bufs[i]
|
||||
d.digest
|
||||
end
|
||||
|
||||
d = Cox::Digest::Blake2b.new output_size
|
||||
d = Sodium::Digest::Blake2b.new output_size
|
||||
dst = Bytes.new d.digest_size
|
||||
bm.report "blake2b reset reusing buffer per iter #{size}" do
|
||||
d.reset
|
||||
|
|
|
@ -52,7 +52,7 @@ openssl speed -evp blake2b512 md5
|
|||
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.
|
||||
# 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.
|
||||
|
|
|
@ -9,7 +9,7 @@ export MIN_LIBSODIUM_VERSION=1.0.18
|
|||
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); }'; }
|
||||
|
||||
|
@ -17,13 +17,13 @@ if `pkg-config libsodium --exists`; then
|
|||
PKG_VER=`pkg-config libsodium --modversion`
|
||||
|
||||
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
|
||||
[ ! -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
|
||||
fi
|
||||
else
|
||||
[ ! -z "$COX_BUILD_VERBOSE" ] && echo "Missing libsodium system package."
|
||||
[ ! -z "$SODIUM_BUILD_VERBOSE" ] && echo "Missing libsodium system package."
|
||||
export LIBSODIUM_INSTALL=1
|
||||
fi
|
||||
|
||||
|
|
|
@ -12,8 +12,8 @@ set -e
|
|||
|
||||
#export LIBSODIUM_INSTALL=1
|
||||
if [ "$LIBSODIUM_INSTALL" != "1" ]; then
|
||||
[ ! -z "$COX_BUILD_VERBOSE" ] echo "Skipping libsodium build."
|
||||
exit
|
||||
[ ! -z "$SODIUM_BUILD_VERBOSE" ] && echo "Skipping libsodium build."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
|
||||
|
@ -22,7 +22,7 @@ cd "$LIBSODIUM_BUILD_DIR"
|
|||
|
||||
|
||||
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"
|
||||
TGZ_FILENAME="$DIRNAME".tar.gz
|
||||
|
@ -58,11 +58,11 @@ if [ ! -f "$LIBSODIUM_INSTALL_PATH/include/sodium.h" ]; then
|
|||
touch .make.install.done
|
||||
fi
|
||||
|
||||
[ ! -z "$COX_BUILD_VERBOSE" ] && echo "Finished building libsodium."
|
||||
[ ! -z "$SODIUM_BUILD_VERBOSE" ] && echo "Finished building libsodium."
|
||||
else
|
||||
# find "$LIBSODIUM_INSTALL_PATH"
|
||||
|
||||
[ ! -z "$COX_BUILD_VERBOSE" ] && echo "Using already built libsodium."
|
||||
[ ! -z "$SODIUM_BUILD_VERBOSE" ] && echo "Using already built libsodium."
|
||||
fi
|
||||
|
||||
exit 0
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
require "../src/cox"
|
||||
require "tallboy"
|
||||
require "../src/sodium"
|
||||
|
||||
if ARGV.empty?
|
||||
puts "Help select Pwhash ops/mem limits for your application."
|
||||
|
@ -15,8 +14,8 @@ time_limit = if t = ARGV.shift?
|
|||
else
|
||||
time_min * 4
|
||||
end
|
||||
mem_limit = (ARGV.shift?.try &.to_i || (Cox::Pwhash::MEMLIMIT_MAX)).to_u64
|
||||
pwhash = Cox::Pwhash.new
|
||||
mem_limit = (ARGV.shift?.try &.to_i || (Sodium::Pwhash::MEMLIMIT_MAX)).to_u64
|
||||
pwhash = Sodium::Pwhash.new
|
||||
pass = "1234"
|
||||
|
||||
# data = Array(Array({UInt64, UInt64, Float64})).new
|
||||
|
@ -36,9 +35,9 @@ def bytes_str(b)
|
|||
"%5d#{suffix}" % b
|
||||
end
|
||||
|
||||
pwhash.memlimit = Cox::Pwhash::MEMLIMIT_MIN
|
||||
pwhash.memlimit = Sodium::Pwhash::MEMLIMIT_MIN
|
||||
loop do
|
||||
pwhash.opslimit = Cox::Pwhash::OPSLIMIT_MIN
|
||||
pwhash.opslimit = Sodium::Pwhash::OPSLIMIT_MIN
|
||||
row = ["%5dK" % (pwhash.memlimit / 1024)]
|
||||
data << row
|
||||
|
||||
|
@ -72,7 +71,7 @@ loop do
|
|||
puts ""
|
||||
|
||||
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
|
||||
end
|
||||
# header << "Ops limit"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
name: cox
|
||||
name: sodium.cr
|
||||
version: 0.1.0
|
||||
|
||||
authors:
|
||||
|
@ -8,6 +8,6 @@ development_dependencies:
|
|||
ghshard:
|
||||
github: bcardiff/ghshard
|
||||
|
||||
crystal: 0.24.1
|
||||
crystal: 0.28.0
|
||||
|
||||
license: MIT
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
require "./spec_helper"
|
||||
|
||||
describe Cox do
|
||||
describe Sodium do
|
||||
# Finished in 71 microseconds
|
||||
# 1 examples, 2 failures, 5 errors, 0 pending
|
||||
# What a man.
|
||||
|
|
|
@ -23,10 +23,10 @@ test_vectors = [
|
|||
},
|
||||
]
|
||||
|
||||
describe Cox::Digest::Blake2b do
|
||||
describe Sodium::Digest::Blake2b do
|
||||
it "libsodium comparisons" do
|
||||
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.hexdigest.should eq vec[:output]
|
||||
end
|
||||
|
@ -34,31 +34,31 @@ describe Cox::Digest::Blake2b do
|
|||
|
||||
it "test vectors" do
|
||||
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.hexdigest.should eq vec[:output]
|
||||
end
|
||||
end
|
||||
|
||||
it "produces different output with different salt or personal params" do
|
||||
key = Bytes.new Cox::Digest::Blake2b::KEY_SIZE
|
||||
salt = Bytes.new Cox::Digest::Blake2b::SALT_SIZE
|
||||
salt2 = Bytes.new Cox::Digest::Blake2b::SALT_SIZE
|
||||
key = Bytes.new Sodium::Digest::Blake2b::KEY_SIZE
|
||||
salt = Bytes.new Sodium::Digest::Blake2b::SALT_SIZE
|
||||
salt2 = Bytes.new Sodium::Digest::Blake2b::SALT_SIZE
|
||||
salt2 = salt.dup
|
||||
salt2[0] = 1
|
||||
personal = Bytes.new Cox::Digest::Blake2b::PERSONAL_SIZE
|
||||
personal = Bytes.new Sodium::Digest::Blake2b::PERSONAL_SIZE
|
||||
personal2 = personal.dup
|
||||
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
|
||||
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
|
||||
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
|
||||
personalout = d.hexdigest
|
||||
|
||||
|
@ -69,19 +69,19 @@ describe Cox::Digest::Blake2b do
|
|||
|
||||
it "raises on invalid " do
|
||||
expect_raises ArgumentError do
|
||||
Cox::Digest::Blake2b.new key: Bytes.new(128)
|
||||
Sodium::Digest::Blake2b.new key: Bytes.new(128)
|
||||
end
|
||||
|
||||
expect_raises ArgumentError do
|
||||
Cox::Digest::Blake2b.new salt: Bytes.new(1)
|
||||
Sodium::Digest::Blake2b.new salt: Bytes.new(1)
|
||||
end
|
||||
|
||||
expect_raises ArgumentError do
|
||||
Cox::Digest::Blake2b.new salt: Bytes.new(128)
|
||||
Sodium::Digest::Blake2b.new salt: Bytes.new(128)
|
||||
end
|
||||
|
||||
expect_raises ArgumentError do
|
||||
Cox::Digest::Blake2b.new personal: Bytes.new(128)
|
||||
Sodium::Digest::Blake2b.new personal: Bytes.new(128)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,13 +1,13 @@
|
|||
require "../../spec_helper"
|
||||
require "../../../src/cox/cipher/chalsa"
|
||||
require "../../../src/sodium/cipher/chalsa"
|
||||
|
||||
{% for name in %w(XSalsa20 Salsa20 XChaCha20 ChaCha20Ietf ChaCha20) %}
|
||||
# TODO: verify against test vectors.
|
||||
describe Cox::Cipher::{{ name.id }} do
|
||||
describe Sodium::Cipher::{{ name.id }} do
|
||||
it "xors" do
|
||||
data = Bytes.new(100)
|
||||
cipher1 = Cox::Cipher::{{ name.id }}.new
|
||||
cipher2 = Cox::Cipher::{{ name.id }}.new
|
||||
cipher1 = Sodium::Cipher::{{ name.id }}.new
|
||||
cipher2 = Sodium::Cipher::{{ name.id }}.new
|
||||
key = cipher1.random_key
|
||||
nonce = cipher1.random_nonce
|
||||
output = cipher1.update data
|
|
@ -1,14 +1,14 @@
|
|||
require "../../spec_helper"
|
||||
|
||||
describe Cox::CryptoBox::SecretKey do
|
||||
describe Sodium::CryptoBox::SecretKey do
|
||||
it "easy encrypt/decrypt" do
|
||||
data = "Hello World!"
|
||||
|
||||
# Alice is the sender
|
||||
alice = Cox::CryptoBox::SecretKey.new
|
||||
alice = Sodium::CryptoBox::SecretKey.new
|
||||
|
||||
# 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
|
||||
# secret key
|
|
@ -2,12 +2,12 @@ require "../spec_helper"
|
|||
|
||||
CONTEXT = "8_bytess"
|
||||
|
||||
describe Cox::Kdf do
|
||||
describe Sodium::Kdf do
|
||||
it "generates master key" do
|
||||
kdf1 = Cox::Kdf.new
|
||||
kdf1 = Sodium::Kdf.new
|
||||
|
||||
# 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
|
||||
key1_s1 = kdf1.derive CONTEXT, 0, 16
|
||||
|
@ -16,7 +16,7 @@ describe Cox::Kdf do
|
|||
end
|
||||
|
||||
it "generates different keys" do
|
||||
kdf1 = Cox::Kdf.new
|
||||
kdf1 = Sodium::Kdf.new
|
||||
subkey1 = kdf1.derive CONTEXT, 0, 16
|
||||
subkey2 = kdf1.derive CONTEXT, 1, 16
|
||||
subkey1.should_not eq subkey2
|
|
@ -1,27 +1,27 @@
|
|||
require "../spec_helper"
|
||||
|
||||
private def pw_min
|
||||
pwhash = Cox::Pwhash.new
|
||||
pwhash = Sodium::Pwhash.new
|
||||
|
||||
# set to minimum to speed up tests
|
||||
pwhash.memlimit = Cox::Pwhash::MEMLIMIT_MIN
|
||||
pwhash.opslimit = Cox::Pwhash::OPSLIMIT_MIN
|
||||
pwhash.memlimit = Sodium::Pwhash::MEMLIMIT_MIN
|
||||
pwhash.opslimit = Sodium::Pwhash::OPSLIMIT_MIN
|
||||
pwhash
|
||||
end
|
||||
|
||||
describe Cox::Pwhash do
|
||||
describe Sodium::Pwhash do
|
||||
it "hashes and verifies a password" do
|
||||
pwhash = pw_min
|
||||
|
||||
pass = "1234"
|
||||
hash = pwhash.store pass
|
||||
pwhash.verify hash, pass
|
||||
expect_raises(Cox::Pwhash::PasswordVerifyError) do
|
||||
expect_raises(Sodium::Pwhash::PasswordVerifyError) do
|
||||
pwhash.verify hash, "5678"
|
||||
end
|
||||
|
||||
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
|
||||
end
|
||||
|
||||
|
@ -34,7 +34,7 @@ describe Cox::Pwhash do
|
|||
|
||||
it "derives a key from a password" do
|
||||
pwhash = pw_min
|
||||
pwhash.algorithm = Cox::Pwhash::Algorithm::Argon2id13
|
||||
pwhash.algorithm = Sodium::Pwhash::Algorithm::Argon2id13
|
||||
salt = pwhash.salt
|
||||
key1 = pwhash.key_derive salt, "foo", 16
|
||||
key2 = pwhash.key_derive salt, "foo", 16
|
|
@ -1,15 +1,15 @@
|
|||
require "../spec_helper"
|
||||
|
||||
describe Cox::SecretBox do
|
||||
describe Sodium::SecretBox do
|
||||
it "encrypts/decrypts" do
|
||||
key = Cox::SecretBox.new
|
||||
key = Sodium::SecretBox.new
|
||||
|
||||
message = "foobar"
|
||||
encrypted, nonce = key.encrypt_easy message
|
||||
decrypted = key.decrypt_easy encrypted, nonce
|
||||
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
|
||||
end
|
||||
end
|
|
@ -1,10 +1,10 @@
|
|||
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
|
||||
message = "foo"
|
||||
skey = Cox::Sign::SecretKey.new
|
||||
skey = Sodium::Sign::SecretKey.new
|
||||
sig = skey.sign_detached message
|
||||
|
||||
skey.public_key.verify_detached message, sig
|
||||
|
@ -12,10 +12,10 @@ describe Cox::Sign::SecretKey do
|
|||
|
||||
it "signs and fails" do
|
||||
message = "foo"
|
||||
skey = Cox::Sign::SecretKey.new
|
||||
skey = Sodium::Sign::SecretKey.new
|
||||
sig = skey.sign_detached message
|
||||
|
||||
expect_raises Cox::Error::VerificationFailed do
|
||||
expect_raises Sodium::Error::VerificationFailed do
|
||||
skey.public_key.verify_detached "bar", sig
|
||||
end
|
||||
end
|
|
@ -1,2 +1,2 @@
|
|||
require "spec"
|
||||
require "../src/cox"
|
||||
require "../src/sodium"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
require "random/secure"
|
||||
|
||||
module Cox
|
||||
module Sodium
|
||||
class Error < ::Exception
|
||||
class VerificationFailed < Error
|
||||
end
|
||||
|
@ -14,8 +14,8 @@ module Cox
|
|||
end
|
||||
end
|
||||
|
||||
require "./cox/**"
|
||||
require "./sodium/**"
|
||||
|
||||
if Cox::LibSodium.sodium_init == -1
|
||||
if Sodium::LibSodium.sodium_init == -1
|
||||
abort "Failed to init libsodium"
|
||||
end
|
|
@ -1,6 +1,6 @@
|
|||
require "../lib_sodium"
|
||||
|
||||
module Cox::Cipher
|
||||
module Sodium::Cipher
|
||||
# The great beat you can eat!
|
||||
#
|
||||
# What? They're both dance?
|
||||
|
@ -69,7 +69,7 @@ module Cox::Cipher
|
|||
#
|
||||
# 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
|
||||
# Xor's src with the cipher output and places in dst.
|
||||
#
|
||||
|
@ -78,12 +78,12 @@ module Cox::Cipher
|
|||
if (key = @key) && (nonce = @nonce)
|
||||
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
|
||||
raise Cox::Error.new("crypto_stream_{{ val.id }}_xor_ic")
|
||||
raise Sodium::Error.new("crypto_stream_{{ val.id }}_xor_ic")
|
||||
end
|
||||
@offset += src.bytesize
|
||||
dst
|
||||
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
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
require "../lib_sodium"
|
||||
|
||||
module Cox::CryptoBox
|
||||
module Sodium::CryptoBox
|
||||
class Pair
|
||||
include Wipe
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
require "../lib_sodium"
|
||||
|
||||
module Cox::CryptoBox
|
||||
module Sodium::CryptoBox
|
||||
class PublicKey < Key
|
||||
include Wipe
|
||||
KEY_SIZE = LibSodium::PUBLIC_KEY_SIZE
|
|
@ -1,6 +1,6 @@
|
|||
require "../lib_sodium"
|
||||
|
||||
module Cox::CryptoBox
|
||||
module Sodium::CryptoBox
|
||||
class SecretKey < Key
|
||||
include Wipe
|
||||
KEY_SIZE = LibSodium::SECRET_KEY_SIZE
|
|
@ -1,6 +1,6 @@
|
|||
require "openssl/digest/digest_base"
|
||||
|
||||
module Cox::Digest
|
||||
module Sodium::Digest
|
||||
class Blake2b
|
||||
# provides copying digest/hexdigest methods
|
||||
include OpenSSL::DigestBase
|
||||
|
@ -57,13 +57,13 @@ module Cox::Digest
|
|||
personal = @have_personal ? @personal.to_unsafe : nil
|
||||
|
||||
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
|
||||
|
||||
def update(data : Bytes)
|
||||
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
|
||||
|
||||
self
|
||||
|
@ -81,7 +81,7 @@ module Cox::Digest
|
|||
# Use .digest or .hexdigest instead.
|
||||
def finish(dst : Bytes) : Bytes
|
||||
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
|
||||
|
||||
dst
|
|
@ -1,4 +1,4 @@
|
|||
module Cox
|
||||
module Sodium
|
||||
class Kdf
|
||||
property bytes : Bytes
|
||||
|
||||
|
@ -25,7 +25,7 @@ module Cox
|
|||
|
||||
subkey = Bytes.new subkey_size
|
||||
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
|
||||
subkey
|
||||
end
|
|
@ -1,4 +1,4 @@
|
|||
module Cox
|
||||
module Sodium
|
||||
abstract class Key
|
||||
abstract def bytes
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
module Cox
|
||||
module Sodium
|
||||
@[Link(ldflags: "`#{__DIR__}/../../build/pkg-libs.sh #{__DIR__}/../..`")]
|
||||
lib LibSodium
|
||||
fun sodium_init : LibC::Int
|
|
@ -1,7 +1,7 @@
|
|||
require "./lib_sodium"
|
||||
require "random/secure"
|
||||
|
||||
module Cox
|
||||
module Sodium
|
||||
class Nonce
|
||||
NONCE_SIZE = LibSodium::NONCE_SIZE
|
||||
|
|
@ -1,11 +1,11 @@
|
|||
module Cox
|
||||
module Sodium
|
||||
# [Argon2 Password Hashing](https://libsodium.gitbook.io/doc/password_hashing/the_argon2i_function)
|
||||
# * #store #verify #needs_rehash? are used together for password verification.
|
||||
# * #key_derive is used on it's own to generate password based keys.
|
||||
#
|
||||
# See `examples/pwhash_selector.cr` for help on selecting parameters.
|
||||
class Pwhash
|
||||
class PasswordVerifyError < Cox::Error
|
||||
class PasswordVerifyError < Sodium::Error
|
||||
end
|
||||
|
||||
OPSLIMIT_MIN = LibSodium.crypto_pwhash_opslimit_min
|
||||
|
@ -39,7 +39,7 @@ module Cox
|
|||
def store(pass)
|
||||
outstr = Bytes.new LibSodium::PWHASH_STR_SIZE
|
||||
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
|
||||
outstr
|
||||
end
|
||||
|
@ -65,7 +65,7 @@ module Cox
|
|||
when 1
|
||||
true
|
||||
else
|
||||
raise Cox::Error.new("crypto_pwhash_str_needs_rehash")
|
||||
raise Sodium::Error.new("crypto_pwhash_str_needs_rehash")
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -76,7 +76,7 @@ module Cox
|
|||
if alg = algorithm
|
||||
key = Bytes.new key_bytes
|
||||
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
|
||||
key
|
||||
else
|
|
@ -1,15 +1,15 @@
|
|||
require "./lib_sodium"
|
||||
|
||||
module Cox
|
||||
module Sodium
|
||||
# [https://libsodium.gitbook.io/doc/secret-key_cryptography](https://libsodium.gitbook.io/doc/secret-key_cryptography)
|
||||
#
|
||||
# ```crystal
|
||||
# key = Cox::SecretKey.new
|
||||
# key = Sodium::SecretKey.new
|
||||
# message = "foobar"
|
||||
# encrypted, nonce = key.encrypt_easy message
|
||||
#
|
||||
# # On the other side.
|
||||
# key = Cox::SecretKey.new key
|
||||
# key = Sodium::SecretKey.new key
|
||||
# message = key.decrypt_easy encrypted, nonce
|
||||
# ```
|
||||
class SecretBox < Key
|
||||
|
@ -54,14 +54,14 @@ module Cox
|
|||
raise ArgumentError.new("dst.bytesize must be src.bytesize + MAC_SIZE, got #{dst.bytesize}")
|
||||
end
|
||||
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
|
||||
dst
|
||||
end
|
||||
|
||||
def decrypt_easy(data : Bytes, nonce : Nonce) : Bytes
|
||||
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
|
||||
decrypt_easy(data, output, nonce)
|
||||
end
|
||||
|
@ -71,7 +71,7 @@ module Cox
|
|||
raise ArgumentError.new("dst.bytesize must be src.bytesize - MAC_SIZE, got #{dst.bytesize}")
|
||||
end
|
||||
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
|
||||
dst
|
||||
end
|
|
@ -1,6 +1,6 @@
|
|||
require "../lib_sodium"
|
||||
|
||||
module Cox
|
||||
module Sodium
|
||||
class Sign::PublicKey < Key
|
||||
include Wipe
|
||||
KEY_SIZE = LibSodium::PUBLIC_SIGN_SIZE
|
||||
|
@ -24,7 +24,7 @@ module Cox
|
|||
|
||||
v = LibSodium.crypto_sign_verify_detached sig, message, message.bytesize, @bytes
|
||||
if v != 0
|
||||
raise Cox::Error::VerificationFailed.new("crypto_sign_verify_detached")
|
||||
raise Sodium::Error::VerificationFailed.new("crypto_sign_verify_detached")
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,7 +1,7 @@
|
|||
require "../lib_sodium"
|
||||
|
||||
module Cox
|
||||
class Sign::SecretKey < Cox::Key
|
||||
module Sodium
|
||||
class Sign::SecretKey < Sodium::Key
|
||||
include Wipe
|
||||
KEY_SIZE = LibSodium::SECRET_SIGN_SIZE
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
module Cox
|
||||
module Sodium
|
||||
VERSION = "0.1.0"
|
||||
end
|
|
@ -1,4 +1,4 @@
|
|||
module Cox::Wipe
|
||||
module Sodium::Wipe
|
||||
@closed = false
|
||||
|
||||
def close
|
||||
|
@ -9,7 +9,7 @@ module Cox::Wipe
|
|||
|
||||
protected def wipe
|
||||
return if @closed
|
||||
Cox.memzero @bytes
|
||||
Sodium.memzero @bytes
|
||||
end
|
||||
|
||||
def finalize
|
Loading…
Reference in New Issue