Rename project from "cox" to "sodium.cr".
parent
8e939b9518
commit
a4b1b8071c
|
@ -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:
|
||||||
|
|
66
README.md
66
README.md
|
@ -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')
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -1,2 +1,2 @@
|
||||||
require "spec"
|
require "spec"
|
||||||
require "../src/cox"
|
require "../src/sodium"
|
||||||
|
|
|
@ -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
|
|
@ -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
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
require "../lib_sodium"
|
require "../lib_sodium"
|
||||||
|
|
||||||
module Cox::CryptoBox
|
module Sodium::CryptoBox
|
||||||
class Pair
|
class Pair
|
||||||
include Wipe
|
include Wipe
|
||||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -1,4 +1,4 @@
|
||||||
module Cox
|
module Sodium
|
||||||
abstract class Key
|
abstract class Key
|
||||||
abstract def bytes
|
abstract def bytes
|
||||||
|
|
|
@ -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
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
module Cox
|
module Sodium
|
||||||
VERSION = "0.1.0"
|
VERSION = "0.1.0"
|
||||||
end
|
end
|
|
@ -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
|
Loading…
Reference in New Issue