sodium 0.0.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. data/.gitignore +4 -0
  2. data/.travis.yml +27 -0
  3. data/Gemfile +9 -0
  4. data/README.md +111 -0
  5. data/Rakefile +3 -0
  6. data/VERSION +1 -0
  7. data/config/nacl_ffi.yml +90 -0
  8. data/lib/sodium.rb +24 -0
  9. data/lib/sodium/auth.rb +52 -0
  10. data/lib/sodium/box.rb +127 -0
  11. data/lib/sodium/buffer.rb +141 -0
  12. data/lib/sodium/delegate.rb +58 -0
  13. data/lib/sodium/ffi.rb +9 -0
  14. data/lib/sodium/ffi/crypto.rb +106 -0
  15. data/lib/sodium/ffi/lib_c.rb +9 -0
  16. data/lib/sodium/ffi/random.rb +11 -0
  17. data/lib/sodium/hash.rb +23 -0
  18. data/lib/sodium/one_time_auth.rb +52 -0
  19. data/lib/sodium/random.rb +16 -0
  20. data/lib/sodium/secret_box.rb +65 -0
  21. data/lib/sodium/sign.rb +75 -0
  22. data/lib/sodium/version.rb +5 -0
  23. data/sodium.gemspec +9 -3
  24. data/sodium.pub.gpg +37 -0
  25. data/tasks/libsodium.rake +70 -0
  26. data/tasks/test.rake +6 -0
  27. data/tasks/version.rake +3 -0
  28. data/test/sodium/auth/hmacsha256_test.rb +54 -0
  29. data/test/sodium/auth/hmacsha512256_test.rb +53 -0
  30. data/test/sodium/auth_test.rb +49 -0
  31. data/test/sodium/box/curve25519xsalsa20poly1305_test.rb +79 -0
  32. data/test/sodium/box_test.rb +109 -0
  33. data/test/sodium/buffer_test.rb +120 -0
  34. data/test/sodium/delegate_test.rb +44 -0
  35. data/test/sodium/hash/sha256_test.rb +31 -0
  36. data/test/sodium/hash/sha512_test.rb +35 -0
  37. data/test/sodium/hash_test.rb +35 -0
  38. data/test/sodium/one_time_auth/poly1305_test.rb +54 -0
  39. data/test/sodium/one_time_auth_test.rb +49 -0
  40. data/test/sodium/random_test.rb +25 -0
  41. data/test/sodium/secret_box/xsalsa20poly1305_test.rb +50 -0
  42. data/test/sodium/secret_box_test.rb +56 -0
  43. data/test/sodium/sign/ed25519_test.rb +52 -0
  44. data/test/sodium/sign_test.rb +58 -0
  45. data/test/test_helper.rb +44 -0
  46. metadata +117 -8
  47. checksums.yaml +0 -7
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ build/
2
+ coverage/
3
+
4
+ Gemfile.lock
data/.travis.yml ADDED
@@ -0,0 +1,27 @@
1
+ script: bundle exec rake test
2
+
3
+ env:
4
+ - >
5
+ LIBSODIUM_MIRROR="https://github.com/jedisct1/libsodium/tarball/%s"
6
+ LIBSODIUM_VERSION="master"
7
+ # - >
8
+ # LIBSODIUM_MIRROR="http://download.dnscrypt.org/libsodium/releases/libsodium-%s.tar.gz"
9
+ # LIBSODIUM_VERSION=0.4.1
10
+ # LIBSODIUM_DIGEST=65756c7832950401cc0e6ee0e99b165974244e749f40f33d465f56447bae8ce3
11
+
12
+ rvm:
13
+ - 1.8.7
14
+ - 1.9.3
15
+ - 2.0.0
16
+ - ruby-head
17
+ - ree
18
+ - jruby-18mode
19
+ - jruby-19mode
20
+ - jruby-head
21
+ - rbx-18mode
22
+ - rbx-19mode
23
+
24
+ matrix:
25
+ allow_failures:
26
+ - rvm: ruby-head
27
+ - rvm: jruby-head
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source 'https://rubygems.org/'
2
+
3
+ gemspec
4
+
5
+ gem 'pry'
6
+
7
+ group :test do
8
+ gem 'coveralls', :require => false
9
+ end
data/README.md ADDED
@@ -0,0 +1,111 @@
1
+ [![Gem Version][gem-badge]][gem-url]
2
+ [![Build Status][travis-badge]][travis-url]
3
+ [![Dependency Status][gemnasium-badge]][gemnasium-url]
4
+ [![Code Climate][codeclimate-badge]][codeclimate-url]
5
+ [![Coverage Status][coveralls-badge]][coveralls-url]
6
+
7
+ sodium
8
+ ======
9
+
10
+ `sodium` is a Ruby binding to the easy-to-use high-speed crypto library [`libsodium`][libsodium] (which itself is based on [Daniel J. Bernstein][djb]'s [`NaCl`][nacl]). `NaCl`'s goal, and thus this project's, is to provide all the core operations necessary to build high-level cryptographic tools.
11
+
12
+ `NaCl` improves upon existing libraries with improved security through tight coding standads, improved usability, and significantly boosted performance.
13
+
14
+ Why Sodium?
15
+ -----------
16
+
17
+ `sodium` exports the functions provided by `libsodium` in an object-oriented, Rubylike manner using a very thin [FFI][ffi] wrapper. It thus provides all the benefits of using the `libsodium` C library directly: simplicity, performance, and security.
18
+
19
+ This library is tightly focused on providing only modern primitives and operations, giving users as few ways as possible to shoot themselves in the foot. While *no* crypto library can prevent all classes of user error, this library at least attempts to minimize the possibility of known, easily-preventable types of user error such as the use of broken primitives, reliance on non-authenticated encryption modes, and composition of low-level primitives to perform tasks for which well-studied high-level operations already exist.
20
+
21
+ Libraries like [OpenSSL][openssl] pack in support for every cryptographic primitive, protocol, and operation under the sun. Many of these supported features are cryptographically broken and preserved only so developers can maintain compatibility with older software. This is explicitly *not* a goal of `sodium`. While we will provide migration paths away from any primitives discovered to be weak or broken, we will never introduce known-bad primitives (e.g., MD5 or SHA-1) or easy-to-fuck-up operations (e.g., CBC mode) for the sake of interoperability.
22
+
23
+ Security
24
+ --------
25
+
26
+ The underlying cryptographic functions and APIs have been designed, chosen, and implemented by professional cryptographers. `sodium` itself, however, has not. No guarantees are made about its security nor suitability for any particular purpose.
27
+
28
+ If believe you have discovered a security vulnerability in the `sodium` wrapper, contact me at `sodium (at) touset (dot) org`. Please encrypt your message using the project's [GPG key][gpg-key] (fingerprint: `1E71 12A4 9424 2358 F6C8 727D C947 F58B FFCE E0D7`).
29
+
30
+ Supported Platforms
31
+ -------------------
32
+
33
+ * MRI 2.0
34
+ * MRI 1.9.3
35
+ * MRI 1.8.7 / REE
36
+ * Rubinius 1.8 / 1.9
37
+ * JRuby 1.8 / 1.9
38
+
39
+ Support for these platforms is automatically tested using [Travis CI][travis-ci].
40
+
41
+ Windows is also theoretically supported, but is as of yet completely untested. If `sodium` doesn't work for you on Windows (or any of the other supported platforms, for that matter), please submit a bug.
42
+
43
+ Installation
44
+ ------------
45
+
46
+ ### Dependencies
47
+
48
+ `sodium` depends on the [`libsodium`][libsodium] C library. It can be installed through [homebrew][homebrew] on OSX.
49
+
50
+ ```sh
51
+ brew install libsodium
52
+ ```
53
+
54
+ ### Ruby Gem
55
+
56
+ `sodium` is distributed as a gem of the same name. You can simply install it through the `gem` command
57
+
58
+ ```sh
59
+ gem install sodium
60
+ ```
61
+
62
+ or install it through [`bundler`][bundler] by adding it to your `Gemfile` and bundling.
63
+
64
+ ```ruby
65
+ echo gem 'sodium' >> Gemfile
66
+ bundle
67
+ ```
68
+
69
+ Documentation
70
+ -------------
71
+
72
+ Full documentation can be found online at [RubyDoc][rubydoc-url]. Examples are provided for the following high-level operations:
73
+
74
+ * [Secret-Key Encryption][example-symmetric-encryption]
75
+ * [Secret-Key Message Authenticators][example-symmetric-authenticators]
76
+ * [Public-Key Encryption][example-asymmetric-encryption]
77
+ * [Public-Key Message Signatures][example-asymmetric-signatures]
78
+
79
+ Contributing
80
+ ------------
81
+
82
+ Fork, commit, push. Submit pull request. When possible, try and follow existing coding conventions for the file you're editing.
83
+
84
+ [libsodium]: https://github.com/jedisct1/libsodium/
85
+ [djb]: http://cr.yp.to/djb.html
86
+ [nacl]: http://nacl.cr.yp.to/
87
+ [ffi]: http://github.com/ffi/ffi
88
+ [openssl]: http://ruby-doc.org/stdlib-2.0/libdoc/openssl/rdoc/OpenSSL.html
89
+ [travis-ci]: https://travis-ci.org/stouset/sodium
90
+ [homebrew]: http://mxcl.github.io/homebrew/
91
+ [bundler]: http://gembundler.com/
92
+
93
+ [gem-badge]: https://badge.fury.io/rb/sodium.png
94
+ [gem-url]: https://badge.fury.io/rb/sodium
95
+ [travis-badge]: https://travis-ci.org/stouset/sodium.png
96
+ [travis-url]: https://travis-ci.org/stouset/sodium
97
+ [gemnasium-badge]: https://gemnasium.com/stouset/sodium.png
98
+ [gemnasium-url]: https://gemnasium.com/stouset/sodium
99
+ [codeclimate-badge]: https://codeclimate.com/github/stouset/sodium.png
100
+ [codeclimate-url]: https://codeclimate.com/github/stouset/sodium
101
+ [coveralls-badge]: https://coveralls.io/repos/stouset/sodium/badge.png?branch=master
102
+ [coveralls-url]: https://coveralls.io/r/stouset/sodium
103
+ [rubydoc-badge]: :(
104
+ [rubydoc-url]: http://rubydoc.org/gems/sodium/frames
105
+
106
+ [example-symmetric-encryption]: examples/TODO
107
+ [example-symmetric-authenticators]: examples/TODO
108
+ [example-asymmetric-encryption]: examples/TODO
109
+ [example-asymmetric-signatures]: examples/TODO
110
+
111
+ [gpg-key]: sodium.pub.gpg
data/Rakefile ADDED
@@ -0,0 +1,3 @@
1
+ Dir['tasks/**/*.rake'].each {|task| load task }
2
+
3
+ task :default => :test
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.5.0
@@ -0,0 +1,90 @@
1
+ - :class : Sodium::Auth
2
+ :family : crypto_auth
3
+ :constants:
4
+ - BYTES
5
+ - KEYBYTES
6
+
7
+ :functions:
8
+ ~ : [ buffer_out, buffer_in, ulong_long, buffer_in, int ]
9
+ :verify: [ buffer_in , buffer_in, ulong_long, buffer_in, int ]
10
+
11
+ :primitives:
12
+ - :HMACSHA512256
13
+ - :HMACSHA256
14
+
15
+ - :class : Sodium::Box
16
+ :family : crypto_box
17
+ :constants:
18
+ - PUBLICKEYBYTES
19
+ - SECRETKEYBYTES
20
+ - BEFORENMBYTES
21
+ - NONCEBYTES
22
+ - ZEROBYTES
23
+ - BOXZEROBYTES
24
+ - MACBYTES
25
+
26
+ :functions:
27
+ ~ : [ buffer_out, buffer_in, ulong_long, buffer_in, buffer_in, buffer_in, int ]
28
+ :open : [ buffer_out, buffer_in, ulong_long, buffer_in, buffer_in, buffer_in, int ]
29
+ :keypair : [ buffer_out, buffer_out, int ]
30
+ :beforenm : [ buffer_out, buffer_in, buffer_in, int ]
31
+ :afternm : [ buffer_out, buffer_in, ulong_long, buffer_in, buffer_in, int ]
32
+ :open_afternm: [ buffer_out, buffer_in, ulong_long, buffer_in, buffer_in, int ]
33
+
34
+ :primitives:
35
+ - :Curve25519XSalsa20Poly1305
36
+
37
+ - :class : Sodium::Hash
38
+ :family : crypto_hash
39
+ :constants:
40
+ - BYTES
41
+
42
+ :functions:
43
+ ~: [ buffer_out, buffer_in, ulong_long, int ]
44
+
45
+ :primitives:
46
+ - :SHA512
47
+ - :SHA256
48
+
49
+ - :class : Sodium::OneTimeAuth
50
+ :family : crypto_onetimeauth
51
+ :constants:
52
+ - BYTES
53
+ - KEYBYTES
54
+
55
+ :functions:
56
+ ~ : [ buffer_out, buffer_in, ulong_long, buffer_in, int ]
57
+ :verify: [ buffer_in , buffer_in, ulong_long, buffer_in, int ]
58
+
59
+ :primitives:
60
+ - :Poly1305
61
+
62
+ - :class : Sodium::SecretBox
63
+ :family : crypto_secretbox
64
+ :constants:
65
+ - KEYBYTES
66
+ - NONCEBYTES
67
+ - ZEROBYTES
68
+ - BOXZEROBYTES
69
+
70
+ :functions:
71
+ ~ : [ buffer_out, buffer_in, ulong_long, buffer_in, buffer_in, int ]
72
+ :open: [ buffer_out, buffer_in, ulong_long, buffer_in, buffer_in, int ]
73
+
74
+ :primitives:
75
+ - :XSalsa20Poly1305
76
+
77
+ - :class : Sodium::Sign
78
+ :family : crypto_sign
79
+ :constants:
80
+ - BYTES
81
+ - PUBLICKEYBYTES
82
+ - SECRETKEYBYTES
83
+
84
+ :functions:
85
+ ~ : [ buffer_out, buffer_out, buffer_in, ulong_long, buffer_in, int ]
86
+ open : [ buffer_out, buffer_out, buffer_in, ulong_long, buffer_in, int ]
87
+ keypair: [ buffer_out, buffer_out, int ]
88
+
89
+ :primitives:
90
+ - :Ed25519
data/lib/sodium.rb CHANGED
@@ -0,0 +1,24 @@
1
+ module Sodium
2
+ class Error < ::StandardError; end
3
+ class LengthError < Error; end
4
+ class CryptoError < Error; end
5
+ class MemoryError < Error; end
6
+ end
7
+
8
+ # require 'sodium/version'
9
+
10
+ # core classes used by other modules
11
+ require 'sodium/delegate'
12
+ require 'sodium/buffer'
13
+ require 'sodium/random'
14
+
15
+ # object-oriented bindings to FFI
16
+ require 'sodium/auth'
17
+ require 'sodium/box'
18
+ require 'sodium/hash'
19
+ require 'sodium/one_time_auth'
20
+ require 'sodium/secret_box'
21
+ require 'sodium/sign'
22
+
23
+ # automagic FFI bindings to libsodium
24
+ require 'sodium/ffi'
@@ -0,0 +1,52 @@
1
+ require 'sodium'
2
+
3
+ class Sodium::Auth
4
+ include Sodium::Delegate
5
+
6
+ def self.key
7
+ Sodium::Buffer.key self.implementation[:KEYBYTES]
8
+ end
9
+
10
+ def initialize(key)
11
+ @key = self.class._key(key)
12
+ end
13
+
14
+ def auth(message)
15
+ message = self.class._message(message)
16
+
17
+ Sodium::Buffer.empty self.implementation[:BYTES] do |authenticator|
18
+ self.implementation.nacl(
19
+ authenticator.to_str,
20
+ message.to_str,
21
+ message.to_str.bytesize,
22
+ @key.to_str
23
+ ) or raise Sodium::CryptoError, 'failed to generate an authenticator'
24
+ end
25
+ end
26
+
27
+ def verify(message, authenticator)
28
+ message = self.class._message(message)
29
+ authenticator = self.class._authenticator(authenticator)
30
+
31
+ self.implementation.nacl_verify(
32
+ authenticator.to_str,
33
+ message.to_str,
34
+ message.to_str.bytesize,
35
+ @key.to_str
36
+ )
37
+ end
38
+
39
+ private
40
+
41
+ def self._key(k)
42
+ Sodium::Buffer.new k, self.implementation[:KEYBYTES]
43
+ end
44
+
45
+ def self._authenticator(a)
46
+ Sodium::Buffer.new a, self.implementation[:BYTES]
47
+ end
48
+
49
+ def self._message(m)
50
+ Sodium::Buffer.new(m)
51
+ end
52
+ end
data/lib/sodium/box.rb ADDED
@@ -0,0 +1,127 @@
1
+ require 'sodium'
2
+
3
+ class Sodium::Box
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.afternm(shared_key, message, nonce)
19
+ shared_key = _shared_key(shared_key)
20
+ message = _message(message)
21
+ nonce = _nonce(nonce)
22
+
23
+ Sodium::Buffer.empty(message.bytesize) do |ciphertext|
24
+ self.implementation.nacl_afternm(
25
+ ciphertext.to_str,
26
+ message.to_str,
27
+ message.to_str.bytesize,
28
+ nonce.to_str,
29
+ shared_key.to_str
30
+ ) or raise Sodium::CryptoError, 'failed to close the box'
31
+ end.unpad self.implementation[:BOXZEROBYTES]
32
+ end
33
+
34
+ def self.open_afternm(shared_key, ciphertext, nonce)
35
+ shared_key = _shared_key(shared_key)
36
+ ciphertext = _ciphertext(ciphertext)
37
+ nonce = _nonce(nonce)
38
+
39
+ Sodium::Buffer.empty(ciphertext.bytesize) do |message|
40
+ self.implementation.nacl_open_afternm(
41
+ message.to_str,
42
+ ciphertext.to_str,
43
+ ciphertext.to_str.bytesize,
44
+ nonce.to_str,
45
+ shared_key.to_str
46
+ ) or raise Sodium::CryptoError, 'failed to open the box'
47
+ end.unpad self.implementation[:ZEROBYTES]
48
+ end
49
+
50
+
51
+ def initialize(secret_key, public_key)
52
+ @secret_key = self.class._secret_key(secret_key)
53
+ @public_key = self.class._public_key(public_key)
54
+ end
55
+
56
+ def nonce
57
+ Sodium::Buffer.nonce self.implementation[:NONCEBYTES]
58
+ end
59
+
60
+ def box(message, nonce)
61
+ message = self.class._message(message)
62
+ nonce = self.class._nonce(nonce)
63
+
64
+ Sodium::Buffer.empty(message.bytesize) do |ciphertext|
65
+ self.implementation.nacl(
66
+ ciphertext.to_str,
67
+ message.to_str,
68
+ message.to_str.bytesize,
69
+ nonce.to_str,
70
+ @public_key.to_str,
71
+ @secret_key.to_str
72
+ ) or raise Sodium::CryptoError, 'failed to close the box'
73
+ end.unpad self.implementation[:BOXZEROBYTES]
74
+ end
75
+
76
+ def open(ciphertext, nonce)
77
+ ciphertext = self.class._ciphertext(ciphertext)
78
+ nonce = self.class._nonce(nonce)
79
+
80
+ Sodium::Buffer.empty(ciphertext.bytesize) do |message|
81
+ self.implementation.nacl_open(
82
+ message.to_str,
83
+ ciphertext.to_str,
84
+ ciphertext.to_str.bytesize,
85
+ nonce.to_str,
86
+ @public_key.to_str,
87
+ @secret_key.to_str
88
+ ) or raise Sodium::CryptoError, 'failed to open the box'
89
+ end.unpad self.implementation[:ZEROBYTES]
90
+ end
91
+
92
+ def beforenm
93
+ Sodium::Buffer.empty self.implementation[:BEFORENMBYTES] do |shared_key|
94
+ self.implementation.nacl_beforenm(
95
+ shared_key.to_str,
96
+ @public_key.to_str,
97
+ @secret_key.to_str
98
+ ) or raise Sodium::CryptoError, 'failed to create a shared key'
99
+ end
100
+ end
101
+
102
+ private
103
+
104
+ def self._public_key(k)
105
+ Sodium::Buffer.new k, self.implementation[:PUBLICKEYBYTES]
106
+ end
107
+
108
+ def self._secret_key(k)
109
+ Sodium::Buffer.new k, self.implementation[:SECRETKEYBYTES]
110
+ end
111
+
112
+ def self._shared_key(k)
113
+ Sodium::Buffer.new k, self.implementation[:BEFORENMBYTES]
114
+ end
115
+
116
+ def self._message(m)
117
+ Sodium::Buffer.new(m).pad self.implementation[:ZEROBYTES]
118
+ end
119
+
120
+ def self._ciphertext(c)
121
+ Sodium::Buffer.new(c).pad self.implementation[:BOXZEROBYTES]
122
+ end
123
+
124
+ def self._nonce(n)
125
+ Sodium::Buffer.new n, self.implementation[:NONCEBYTES]
126
+ end
127
+ end