sodium 0.0.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/.travis.yml +27 -0
- data/Gemfile +9 -0
- data/README.md +111 -0
- data/Rakefile +3 -0
- data/VERSION +1 -0
- data/config/nacl_ffi.yml +90 -0
- data/lib/sodium.rb +24 -0
- data/lib/sodium/auth.rb +52 -0
- data/lib/sodium/box.rb +127 -0
- data/lib/sodium/buffer.rb +141 -0
- data/lib/sodium/delegate.rb +58 -0
- data/lib/sodium/ffi.rb +9 -0
- data/lib/sodium/ffi/crypto.rb +106 -0
- data/lib/sodium/ffi/lib_c.rb +9 -0
- data/lib/sodium/ffi/random.rb +11 -0
- data/lib/sodium/hash.rb +23 -0
- data/lib/sodium/one_time_auth.rb +52 -0
- data/lib/sodium/random.rb +16 -0
- data/lib/sodium/secret_box.rb +65 -0
- data/lib/sodium/sign.rb +75 -0
- data/lib/sodium/version.rb +5 -0
- data/sodium.gemspec +9 -3
- data/sodium.pub.gpg +37 -0
- data/tasks/libsodium.rake +70 -0
- data/tasks/test.rake +6 -0
- data/tasks/version.rake +3 -0
- data/test/sodium/auth/hmacsha256_test.rb +54 -0
- data/test/sodium/auth/hmacsha512256_test.rb +53 -0
- data/test/sodium/auth_test.rb +49 -0
- data/test/sodium/box/curve25519xsalsa20poly1305_test.rb +79 -0
- data/test/sodium/box_test.rb +109 -0
- data/test/sodium/buffer_test.rb +120 -0
- data/test/sodium/delegate_test.rb +44 -0
- data/test/sodium/hash/sha256_test.rb +31 -0
- data/test/sodium/hash/sha512_test.rb +35 -0
- data/test/sodium/hash_test.rb +35 -0
- data/test/sodium/one_time_auth/poly1305_test.rb +54 -0
- data/test/sodium/one_time_auth_test.rb +49 -0
- data/test/sodium/random_test.rb +25 -0
- data/test/sodium/secret_box/xsalsa20poly1305_test.rb +50 -0
- data/test/sodium/secret_box_test.rb +56 -0
- data/test/sodium/sign/ed25519_test.rb +52 -0
- data/test/sodium/sign_test.rb +58 -0
- data/test/test_helper.rb +44 -0
- metadata +117 -8
- checksums.yaml +0 -7
data/lib/sodium/sign.rb
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'sodium'
|
2
|
+
|
3
|
+
class Sodium::Sign
|
4
|
+
include Sodium::Delegate
|
5
|
+
|
6
|
+
def self.keypair
|
7
|
+
public_key = Sodium::Buffer.empty self.implementation[:PUBLICKEYBYTES]
|
8
|
+
secret_key = Sodium::Buffer.empty self.implementation[:SECRETKEYBYTES]
|
9
|
+
|
10
|
+
self.implementation.nacl_keypair(
|
11
|
+
public_key.to_str,
|
12
|
+
secret_key.to_str
|
13
|
+
) or raise Sodium::CryptoError, 'failed to generate a keypair'
|
14
|
+
|
15
|
+
return secret_key, public_key
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.verify(key, message, signature)
|
19
|
+
key = self._public_key(key)
|
20
|
+
signature = self._signature(message, signature)
|
21
|
+
message = Sodium::Buffer.empty(signature.bytesize)
|
22
|
+
mlen = FFI::MemoryPointer.new(:ulong_long, 1, true)
|
23
|
+
|
24
|
+
self.implementation.nacl_open(
|
25
|
+
message.to_str,
|
26
|
+
mlen,
|
27
|
+
signature.to_str,
|
28
|
+
signature.to_str.bytesize,
|
29
|
+
key.to_str
|
30
|
+
)
|
31
|
+
end
|
32
|
+
|
33
|
+
def initialize(key)
|
34
|
+
@key = self.class._secret_key(key)
|
35
|
+
end
|
36
|
+
|
37
|
+
def sign(message)
|
38
|
+
message = self.class._message(message)
|
39
|
+
signature = Sodium::Buffer.empty(message.bytesize + self.implementation[:BYTES])
|
40
|
+
slen = FFI::MemoryPointer.new(:ulong_long, 1, true)
|
41
|
+
|
42
|
+
self.implementation.nacl(
|
43
|
+
signature.to_str,
|
44
|
+
slen,
|
45
|
+
message.to_str,
|
46
|
+
message.to_str.bytesize,
|
47
|
+
@key.to_str
|
48
|
+
) or raise Sodium::CryptoError, 'failed to generate signature'
|
49
|
+
|
50
|
+
# signatures actually encode the message itself at the end, so we
|
51
|
+
# slice off only the signature bytes
|
52
|
+
signature.byteslice(
|
53
|
+
0,
|
54
|
+
slen.read_ulong_long - message.to_str.bytesize
|
55
|
+
)
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def self._public_key(k)
|
61
|
+
Sodium::Buffer.new k, self.implementation[:PUBLICKEYBYTES]
|
62
|
+
end
|
63
|
+
|
64
|
+
def self._secret_key(k)
|
65
|
+
Sodium::Buffer.new k, self.implementation[:SECRETKEYBYTES]
|
66
|
+
end
|
67
|
+
|
68
|
+
def self._message(m)
|
69
|
+
Sodium::Buffer.new m
|
70
|
+
end
|
71
|
+
|
72
|
+
def self._signature(m, s)
|
73
|
+
Sodium::Buffer.new(s) + m
|
74
|
+
end
|
75
|
+
end
|
data/sodium.gemspec
CHANGED
@@ -1,17 +1,23 @@
|
|
1
1
|
Gem::Specification.new do |gem|
|
2
2
|
gem.name = 'sodium'
|
3
|
-
gem.version = '0.0.0'
|
3
|
+
gem.version = File.read('VERSION') rescue '0.0.0'
|
4
4
|
|
5
5
|
gem.author = 'Stephen Touset'
|
6
6
|
gem.email = 'stephen@touset.org'
|
7
7
|
|
8
8
|
gem.homepage = 'https://github.com/stouset/sodium'
|
9
|
-
gem.summary =
|
10
|
-
gem.description =
|
9
|
+
gem.summary = 'A Ruby binding to the easy-to-use high-speed crypto library libsodium'
|
10
|
+
gem.description = 'A library for performing cryptography based on modern ciphers and protocols'
|
11
11
|
|
12
12
|
gem.bindir = 'bin'
|
13
13
|
gem.files = `git ls-files` .split("\n")
|
14
14
|
gem.extensions = `git ls-files -- ext/*.rb`.split("\n")
|
15
15
|
gem.executables = `git ls-files -- bin/*` .split("\n").map {|e| File.basename(e) }
|
16
16
|
gem.test_files = `git ls-files -- spec/*` .split("\n")
|
17
|
+
|
18
|
+
gem.add_dependency 'ffi', '~> 1'
|
19
|
+
|
20
|
+
gem.add_development_dependency 'rake', '~> 10'
|
21
|
+
gem.add_development_dependency 'minitest', '~> 5'
|
22
|
+
gem.add_development_dependency 'version', '~> 1'
|
17
23
|
end
|
data/sodium.pub.gpg
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
2
|
+
Version: GnuPG v1.4.13 (Darwin)
|
3
|
+
|
4
|
+
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
|
35
|
+
4AA=
|
36
|
+
=JlbY
|
37
|
+
-----END PGP PUBLIC KEY BLOCK-----
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'rake/clean'
|
2
|
+
|
3
|
+
require 'rbconfig'
|
4
|
+
require 'digest/sha2'
|
5
|
+
|
6
|
+
|
7
|
+
LIBSODIUM_MIRROR = ENV['LIBSODIUM_MIRROR'] || "https://github.com/jedisct1/libsodium/tarball/%s"
|
8
|
+
LIBSODIUM_VERSION = ENV['LIBSODIUM_VERSION'] || 'master'
|
9
|
+
LIBSODIUM_DIGEST = ENV['LIBSODIUM_DIGEST'] || nil
|
10
|
+
|
11
|
+
LIBSODIUM_URL = LIBSODIUM_MIRROR % LIBSODIUM_VERSION
|
12
|
+
LIBSODIUM_PATH = "libsodium-#{LIBSODIUM_VERSION}"
|
13
|
+
LIBSODIUM_TARBALL = "build/#{LIBSODIUM_PATH}.tar.gz"
|
14
|
+
LIBSODIUM_BUILD = "build/#{LIBSODIUM_PATH}"
|
15
|
+
LIBSODIUM_LIBDIR = "#{LIBSODIUM_BUILD}/src/libsodium/.libs"
|
16
|
+
LIBSODIUM_LIB = "libsodium.a"
|
17
|
+
LIBSODIUM = "#{LIBSODIUM_LIBDIR}/#{LIBSODIUM_LIB}"
|
18
|
+
|
19
|
+
namespace :libsodium do
|
20
|
+
directory LIBSODIUM_BUILD
|
21
|
+
|
22
|
+
file LIBSODIUM_TARBALL => LIBSODIUM_BUILD do
|
23
|
+
sh %{curl -L -o #{LIBSODIUM_TARBALL} #{LIBSODIUM_URL}}
|
24
|
+
|
25
|
+
next if LIBSODIUM_DIGEST.nil?
|
26
|
+
next if LIBSODIUM_DIGEST == Digest::SHA256.hexdigest(
|
27
|
+
File.read(LIBSODIUM_TARBALL)
|
28
|
+
)
|
29
|
+
|
30
|
+
rm LIBSODIUM_TARBALL
|
31
|
+
raise "#{LIBSODIUM_TARBALL} failed checksum"
|
32
|
+
end
|
33
|
+
|
34
|
+
file "#{LIBSODIUM_BUILD}/autogen.sh" => [
|
35
|
+
LIBSODIUM_BUILD,
|
36
|
+
LIBSODIUM_TARBALL,
|
37
|
+
] do
|
38
|
+
sh %{tar -C #{LIBSODIUM_BUILD} --strip-components 1 -m -xf #{LIBSODIUM_TARBALL}}
|
39
|
+
end
|
40
|
+
|
41
|
+
file "#{LIBSODIUM_BUILD}/configure" => "#{LIBSODIUM_BUILD}/autogen.sh" do
|
42
|
+
sh %{cd #{LIBSODIUM_BUILD} && ./autogen.sh}
|
43
|
+
end
|
44
|
+
|
45
|
+
file "#{LIBSODIUM_BUILD}/Makefile" => "#{LIBSODIUM_BUILD}/configure" do
|
46
|
+
sh %{cd #{LIBSODIUM_BUILD} && ./configure}
|
47
|
+
end
|
48
|
+
|
49
|
+
file LIBSODIUM => "#{LIBSODIUM_BUILD}/Makefile" do
|
50
|
+
sh %{cd #{LIBSODIUM_BUILD} && make}
|
51
|
+
end
|
52
|
+
|
53
|
+
desc 'Compile a local copy of libsodium'
|
54
|
+
task :compile => LIBSODIUM do
|
55
|
+
# allow use of the library by the dynamic linker
|
56
|
+
ENV['DYLD_LIBRARY_PATH'] = LIBSODIUM_LIBDIR
|
57
|
+
ENV[ 'LD_LIBRARY_PATH'] = LIBSODIUM_LIBDIR
|
58
|
+
end
|
59
|
+
|
60
|
+
task :clean do
|
61
|
+
sh %{cd #{LIBSODIUM_BUILD} && make mostlyclean}
|
62
|
+
end
|
63
|
+
|
64
|
+
task :clobber do
|
65
|
+
CLOBBER.add 'build'
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
task :clean => 'libsodium:clean'
|
70
|
+
task :clobber => 'libsodium:clobber'
|
data/tasks/test.rake
ADDED
data/tasks/version.rake
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
describe Sodium::Auth::HMACSHA256 do
|
4
|
+
include SodiumTestHelpers
|
5
|
+
|
6
|
+
subject { self.klass.new(self.key) }
|
7
|
+
|
8
|
+
let(:klass) { Sodium::Auth::HMACSHA256 }
|
9
|
+
let(:primitive) { :hmacsha256 }
|
10
|
+
|
11
|
+
let :constants do
|
12
|
+
{ :BYTES => 32,
|
13
|
+
:KEYBYTES => 32, }
|
14
|
+
end
|
15
|
+
|
16
|
+
let_64(:key) { 'XMfWD8/yrcNDzJyGhxRIwi5tSGKf8D0ul9FyX/djvjg=' }
|
17
|
+
let_64(:authenticator) { '6WDKvxKevcZts0Yc1HWGnylNYEpcxPO9tVtApEK8XWc=' }
|
18
|
+
let_64(:plaintext) { 'bWVzc2FnZQ==' }
|
19
|
+
|
20
|
+
it '::primitive must be correct' do
|
21
|
+
self.klass.primitive.must_equal self.primitive
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'must have correct values for its constants' do
|
25
|
+
self.constants.each_pair do |name, value|
|
26
|
+
self.klass[name].must_equal value
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'must mint keys' do
|
31
|
+
self.klass.key.bytesize.
|
32
|
+
must_equal self.klass[:KEYBYTES]
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'must generate authenticators' do
|
36
|
+
self.subject.auth(
|
37
|
+
self.plaintext
|
38
|
+
).to_str.must_equal self.authenticator
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'must verify authenticators' do
|
42
|
+
self.subject.verify(
|
43
|
+
self.plaintext,
|
44
|
+
self.authenticator
|
45
|
+
).must_equal true
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'must not verify forged authenticators' do
|
49
|
+
self.subject.verify(
|
50
|
+
self.plaintext,
|
51
|
+
self.authenticator.succ
|
52
|
+
).must_equal false
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
describe Sodium::Auth::HMACSHA512256 do
|
4
|
+
include SodiumTestHelpers
|
5
|
+
|
6
|
+
subject { self.klass.new(self.key) }
|
7
|
+
|
8
|
+
let(:klass) { Sodium::Auth::HMACSHA512256 }
|
9
|
+
let(:primitive) { :hmacsha512256 }
|
10
|
+
|
11
|
+
let :constants do
|
12
|
+
{ :BYTES => 32,
|
13
|
+
:KEYBYTES => 32, }
|
14
|
+
end
|
15
|
+
|
16
|
+
let_64(:key) { 'XMfWD8/yrcNDzJyGhxRIwi5tSGKf8D0ul9FyX/djvjg=' }
|
17
|
+
let_64(:authenticator) { '6BN5+HNq0F8skQKkta+CLiBJ7mrrJaGw3G2J7jMT2qA=' }
|
18
|
+
let_64(:plaintext) { 'bWVzc2FnZQ==' }
|
19
|
+
|
20
|
+
it '::primitive must be correct' do
|
21
|
+
self.klass.primitive.must_equal self.primitive
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'must have correct values for its constants' do
|
25
|
+
self.constants.each_pair do |name, value|
|
26
|
+
self.klass[name].must_equal value
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'must mint keys' do
|
31
|
+
self.klass.key.bytesize.must_equal self.klass[:KEYBYTES]
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'must generate authenticators' do
|
35
|
+
self.subject.auth(
|
36
|
+
self.plaintext
|
37
|
+
).to_str.must_equal self.authenticator
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'must verify authenticators' do
|
41
|
+
self.subject.verify(
|
42
|
+
self.plaintext,
|
43
|
+
self.authenticator
|
44
|
+
).must_equal true
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'must not verify forged authenticators' do
|
48
|
+
self.subject.verify(
|
49
|
+
self.plaintext,
|
50
|
+
self.authenticator.succ
|
51
|
+
).must_equal false
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
describe Sodium::Auth do
|
4
|
+
include SodiumTestHelpers
|
5
|
+
|
6
|
+
subject { self.klass.new(self.key) }
|
7
|
+
let(:klass) { Sodium::Auth }
|
8
|
+
let(:key) { self.klass.key }
|
9
|
+
|
10
|
+
it 'must default to the HMACSHA512256 implementation' do
|
11
|
+
self.klass.implementation.
|
12
|
+
must_equal Sodium::Auth::HMACSHA512256
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'must allow access to alternate implementations' do
|
16
|
+
self.klass.implementation(:hmacsha256).
|
17
|
+
must_equal Sodium::Auth::HMACSHA256
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'must instantiate the default implementation' do
|
21
|
+
self.subject.
|
22
|
+
must_be_kind_of Sodium::Auth::HMACSHA512256
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'must mint keys from the default implementation' do
|
26
|
+
sodium_mock_default(self.klass) do |klass, mock|
|
27
|
+
mock.expect :[], 0, [:KEYBYTES]
|
28
|
+
|
29
|
+
klass.key.to_str.must_equal ''
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'must raise when instantiating with an invalid key' do
|
34
|
+
lambda { self.klass.new(self.key.to_str[0..-2]) }.
|
35
|
+
must_raise Sodium::LengthError
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'must raise when verifying an invalid authenticator' do
|
39
|
+
lambda { self.subject.verify('message', 'blaaah') }.
|
40
|
+
must_raise Sodium::LengthError
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'must raise when failing to generate an authenticator' do
|
44
|
+
sodium_stub_failure(self.klass, :nacl) do
|
45
|
+
lambda { self.subject.auth('message') }.
|
46
|
+
must_raise Sodium::CryptoError
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
describe Sodium::Box::Curve25519XSalsa20Poly1305 do
|
4
|
+
include SodiumTestHelpers
|
5
|
+
|
6
|
+
subject { self.klass.new(self.secret_key, self.public_key) }
|
7
|
+
|
8
|
+
let(:klass) { Sodium::Box::Curve25519XSalsa20Poly1305 }
|
9
|
+
let(:primitive) { :curve25519xsalsa20poly1305 }
|
10
|
+
|
11
|
+
let :constants do
|
12
|
+
{ :PUBLICKEYBYTES => 32,
|
13
|
+
:SECRETKEYBYTES => 32,
|
14
|
+
:BEFORENMBYTES => 32,
|
15
|
+
:NONCEBYTES => 24,
|
16
|
+
:ZEROBYTES => 32,
|
17
|
+
:BOXZEROBYTES => 16,
|
18
|
+
:MACBYTES => 16, }
|
19
|
+
end
|
20
|
+
|
21
|
+
let_64(:secret_key) { 'f52WNdyy0r1YA5NCGlcF+vJ5HPG8yfHwzn/HJSJzfQk=' }
|
22
|
+
let_64(:public_key) { 'es8h5AH9GGD7PF10D1txeHAFAB2UNc9OZF+JqFWE9y8=' }
|
23
|
+
let_64(:shared_key) { 'TTp8bQBhIuiiQ0plVcqS3Cj62i/IdAFnopx4t9di2Kg=' }
|
24
|
+
let_64(:nonce) { 'i72xIDJ4tcHCOHGYAzI6PoiVm31PFVgx' }
|
25
|
+
let_64(:ciphertext) { 'lHhCSFzopX4z02nlIuInHe3hFwpHFdA=' }
|
26
|
+
let_64(:plaintext) { 'bWVzc2FnZQ==' }
|
27
|
+
|
28
|
+
it '::primitive must be correct' do
|
29
|
+
self.klass.primitive.must_equal self.primitive
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'must have correct values for its constants' do
|
33
|
+
self.constants.each_pair do |name, value|
|
34
|
+
self.klass[name].must_equal value
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'must mint secret keys' do
|
39
|
+
self.klass.keypair[0].bytesize.must_equal self.klass[:SECRETKEYBYTES]
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'must mint public keys' do
|
43
|
+
self.klass.keypair[1].bytesize.must_equal self.klass[:PUBLICKEYBYTES]
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'must generate closed boxes' do
|
47
|
+
self.subject.box(
|
48
|
+
self.plaintext,
|
49
|
+
self.nonce
|
50
|
+
).to_str.must_equal self.ciphertext
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'must open boxes' do
|
54
|
+
self.subject.open(
|
55
|
+
self.ciphertext,
|
56
|
+
self.nonce
|
57
|
+
).to_str.must_equal self.plaintext
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'must generate shared keys' do
|
61
|
+
self.subject.beforenm.to_str.must_equal self.shared_key
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'must generate closed boxes with shared keys' do
|
65
|
+
self.klass.afternm(
|
66
|
+
self.shared_key,
|
67
|
+
self.plaintext,
|
68
|
+
self.nonce
|
69
|
+
).to_str.must_equal self.ciphertext
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'must open boxes with shared keys' do
|
73
|
+
self.klass.open_afternm(
|
74
|
+
self.shared_key,
|
75
|
+
self.ciphertext,
|
76
|
+
self.nonce
|
77
|
+
).to_str.must_equal self.plaintext
|
78
|
+
end
|
79
|
+
end
|