sodium 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Binary file
data/.gitignore CHANGED
@@ -2,3 +2,9 @@ build/
2
2
  coverage/
3
3
 
4
4
  Gemfile.lock
5
+
6
+ Makefile
7
+ *.o
8
+ *.so
9
+ *.bundle
10
+ .*.time
@@ -1,13 +1,16 @@
1
1
  script: bundle exec rake test
2
2
 
3
+ bundler_args: --without tools
4
+
3
5
  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
6
+ matrix:
7
+ - >
8
+ LIBSODIUM_MIRROR="https://github.com/jedisct1/libsodium/tarball/%s"
9
+ LIBSODIUM_VERSION="master"
10
+ # - >
11
+ # LIBSODIUM_MIRROR="http://download.dnscrypt.org/libsodium/releases/libsodium-%s.tar.gz"
12
+ # LIBSODIUM_VERSION=0.4.1
13
+ # LIBSODIUM_DIGEST=65756c7832950401cc0e6ee0e99b165974244e749f40f33d465f56447bae8ce3
11
14
 
12
15
  rvm:
13
16
  - 1.8.7
@@ -0,0 +1,20 @@
1
+ ### 0.6.0 (2013-06-27)
2
+
3
+ - Additions
4
+ * Sodium::Auth can be used entirely with class methods
5
+ * Sodium::Buffer gains many new API methods
6
+ * signed gem
7
+
8
+ - Removals
9
+ * Sodium::Buffer loses #pad, #unpad
10
+
11
+ - Enhancements
12
+ * Sodium::Buffer performance improvements
13
+
14
+ - Bug Fixes
15
+ * using `pointer` type for FFI methods to avoid bugs related to
16
+ in/out buffers in JRuby
17
+
18
+ ### 0.5.0 (2013-06-05)
19
+
20
+ - Initial release
data/Gemfile CHANGED
@@ -2,7 +2,9 @@ source 'https://rubygems.org/'
2
2
 
3
3
  gemspec
4
4
 
5
- gem 'pry'
5
+ group :tools do
6
+ gem 'pry'
7
+ end
6
8
 
7
9
  group :test do
8
10
  gem 'coveralls', :require => false
data/README.md CHANGED
@@ -108,4 +108,4 @@ Fork, commit, push. Submit pull request. When possible, try and follow existing
108
108
  [example-asymmetric-encryption]: examples/TODO
109
109
  [example-asymmetric-signatures]: examples/TODO
110
110
 
111
- [gpg-key]: sodium.pub.gpg
111
+ [gpg-key]: certs/sodium@touset.org.pub.gpg
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.5.0
1
+ 0.6.0
@@ -0,0 +1,20 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIDMDCCAhigAwIBAgIBADANBgkqhkiG9w0BAQUFADA+MQ8wDQYDVQQDDAZzb2Rp
3
+ dW0xFjAUBgoJkiaJk/IsZAEZFgZ0b3VzZXQxEzARBgoJkiaJk/IsZAEZFgNvcmcw
4
+ HhcNMTMwNjI4MDEzMzQ4WhcNMTQwNjI4MDEzMzQ4WjA+MQ8wDQYDVQQDDAZzb2Rp
5
+ dW0xFjAUBgoJkiaJk/IsZAEZFgZ0b3VzZXQxEzARBgoJkiaJk/IsZAEZFgNvcmcw
6
+ ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCh3C2P1jW4MvcpXioNkqW/
7
+ HiD9ZpTew1tHTolQclBBmOmOApLUPc9PIsfbohph83Z82x+BWbjEdL5NAfEQjRVu
8
+ O8JUBJh0YRDF9P7fDtd9w0b3mmhumujbEsmDYs1ru5VvjgCh+Hfxgddlpha0KmxQ
9
+ 0j3h/Uj27tFbE33dIRqb5dBBBnnIM5CqRMu5/gDeXN5GrjYK3JfZlzZRECjnfuR5
10
+ qDqoQFJK5ZmaEFm9E88HdAIS+sV9zb1OCYlADr3EB/a3Shxedx4SsX7oBPyNfsRb
11
+ kMdTr+VynH/OEPSo0dW1DuKpUCmNBscrTOwhn6hJUDNpr6f0CTfYG9jGJY3p5JMt
12
+ AgMBAAGjOTA3MAkGA1UdEwQCMAAwHQYDVR0OBBYEFIu3aZS82t6UR4Z5eON3t2LI
13
+ AHPeMAsGA1UdDwQEAwIEsDANBgkqhkiG9w0BAQUFAAOCAQEAkjXdsFKC9mQfT3tP
14
+ PNtArZ+Y/MhEfNXgKeTIHuIXMaFe86ekTxYxfIziH5VpGtIzeVxXE4teNNI/tpSX
15
+ DcBNspVsx4N/PBqVdtD2KqTO+yrHiER7T9XEEctMgmFQB+NGMLNIpde1tGS8hX2p
16
+ mcWzr4EAsJwbtLa3HHPwNrr3+Xj1YA8SvLffsJ0nUv/DeqkDCr/CG8mfPO65KtvX
17
+ rp7h6AAaApIXd1JOn/ady0QxBNc9Rcjg0iG3lF4bRozRR2/B3cNC9PlHUhObWLYh
18
+ /fYRy+X91OOKL0AyBJRoXo4iT7YeerdeYuWB9HZjJZSR13qeIn2vgJOS4qpPgqyu
19
+ S0VfcA==
20
+ -----END CERTIFICATE-----
@@ -5,8 +5,8 @@
5
5
  - KEYBYTES
6
6
 
7
7
  :functions:
8
- ~ : [ buffer_out, buffer_in, ulong_long, buffer_in, int ]
9
- :verify: [ buffer_in , buffer_in, ulong_long, buffer_in, int ]
8
+ ~ : [ pointer, pointer, ulong_long, pointer, int ]
9
+ :verify: [ pointer, pointer, ulong_long, pointer, int ]
10
10
 
11
11
  :primitives:
12
12
  - :HMACSHA512256
@@ -24,12 +24,12 @@
24
24
  - MACBYTES
25
25
 
26
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 ]
27
+ ~ : [ pointer, pointer, ulong_long, pointer, pointer, pointer, int ]
28
+ :open : [ pointer, pointer, ulong_long, pointer, pointer, pointer, int ]
29
+ :keypair : [ pointer, pointer, int ]
30
+ :beforenm : [ pointer, pointer, pointer, int ]
31
+ :afternm : [ pointer, pointer, ulong_long, pointer, pointer, int ]
32
+ :open_afternm: [ pointer, pointer, ulong_long, pointer, pointer, int ]
33
33
 
34
34
  :primitives:
35
35
  - :Curve25519XSalsa20Poly1305
@@ -40,7 +40,7 @@
40
40
  - BYTES
41
41
 
42
42
  :functions:
43
- ~: [ buffer_out, buffer_in, ulong_long, int ]
43
+ ~: [ pointer, pointer, ulong_long, int ]
44
44
 
45
45
  :primitives:
46
46
  - :SHA512
@@ -53,8 +53,8 @@
53
53
  - KEYBYTES
54
54
 
55
55
  :functions:
56
- ~ : [ buffer_out, buffer_in, ulong_long, buffer_in, int ]
57
- :verify: [ buffer_in , buffer_in, ulong_long, buffer_in, int ]
56
+ ~ : [ pointer, pointer, ulong_long, pointer, int ]
57
+ :verify: [ pointer, pointer, ulong_long, pointer, int ]
58
58
 
59
59
  :primitives:
60
60
  - :Poly1305
@@ -68,8 +68,8 @@
68
68
  - BOXZEROBYTES
69
69
 
70
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 ]
71
+ ~ : [ pointer, pointer, ulong_long, pointer, pointer, int ]
72
+ :open: [ pointer, pointer, ulong_long, pointer, pointer, int ]
73
73
 
74
74
  :primitives:
75
75
  - :XSalsa20Poly1305
@@ -82,9 +82,9 @@
82
82
  - SECRETKEYBYTES
83
83
 
84
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 ]
85
+ ~ : [ pointer, pointer, pointer, ulong_long, pointer, int ]
86
+ open : [ pointer, pointer, pointer, ulong_long, pointer, int ]
87
+ keypair: [ pointer, pointer, int ]
88
88
 
89
89
  :primitives:
90
90
  - :Ed25519
@@ -0,0 +1,11 @@
1
+ #
2
+ # FIXME: workaround for JRuby 1.7.4, where C extensions are
3
+ # disabled. This can be removed, apparently, when 1.7.5 is released.
4
+ #
5
+ if defined? ENV_JAVA
6
+ ENV_JAVA['jruby.cext.enabled'] = 'true'
7
+ end
8
+
9
+ require 'mkmf'
10
+
11
+ create_makefile('sodium/ffi/memory')
@@ -0,0 +1,16 @@
1
+ #include <stddef.h>
2
+
3
+ void
4
+ sodium_memxor(unsigned char *out, unsigned char *buf1, unsigned char *buf2, size_t size) {
5
+ size_t i;
6
+ for(i = 0; i < size; i++)
7
+ out[i] = buf1[i] ^ buf2[i];
8
+ }
9
+
10
+ void
11
+ sodium_memput(unsigned char *out, unsigned char *in, size_t offset, size_t size) {
12
+ size_t i;
13
+ for (i = 0; i < size; i++) {
14
+ out[offset + i] = in[i];
15
+ }
16
+ }
@@ -7,35 +7,45 @@ class Sodium::Auth
7
7
  Sodium::Buffer.key self.implementation[:KEYBYTES]
8
8
  end
9
9
 
10
- def initialize(key)
11
- @key = self.class._key(key)
12
- end
13
-
14
- def auth(message)
15
- message = self.class._message(message)
10
+ def self.auth(key, message)
11
+ key = self._key(key)
12
+ message = self._message(message)
16
13
 
17
14
  Sodium::Buffer.empty self.implementation[:BYTES] do |authenticator|
18
15
  self.implementation.nacl(
19
16
  authenticator.to_str,
20
17
  message.to_str,
21
18
  message.to_str.bytesize,
22
- @key.to_str
19
+ key.to_str
23
20
  ) or raise Sodium::CryptoError, 'failed to generate an authenticator'
24
21
  end
25
22
  end
26
23
 
27
- def verify(message, authenticator)
28
- message = self.class._message(message)
29
- authenticator = self.class._authenticator(authenticator)
24
+ def self.verify(key, message, authenticator)
25
+ key = self._key(key)
26
+ message = self._message(message)
27
+ authenticator = self._authenticator(authenticator)
30
28
 
31
29
  self.implementation.nacl_verify(
32
30
  authenticator.to_str,
33
31
  message.to_str,
34
32
  message.to_str.bytesize,
35
- @key.to_str
33
+ key.to_str
36
34
  )
37
35
  end
38
36
 
37
+ def initialize(key)
38
+ @key = self.class._key(key)
39
+ end
40
+
41
+ def auth(message)
42
+ self.class.auth(@key, message)
43
+ end
44
+
45
+ def verify(message, authenticator)
46
+ self.class.verify(@key, message, authenticator)
47
+ end
48
+
39
49
  private
40
50
 
41
51
  def self._key(k)
@@ -28,7 +28,7 @@ class Sodium::Box
28
28
  nonce.to_str,
29
29
  shared_key.to_str
30
30
  ) or raise Sodium::CryptoError, 'failed to close the box'
31
- end.unpad self.implementation[:BOXZEROBYTES]
31
+ end.ldrop self.implementation[:BOXZEROBYTES]
32
32
  end
33
33
 
34
34
  def self.open_afternm(shared_key, ciphertext, nonce)
@@ -44,7 +44,7 @@ class Sodium::Box
44
44
  nonce.to_str,
45
45
  shared_key.to_str
46
46
  ) or raise Sodium::CryptoError, 'failed to open the box'
47
- end.unpad self.implementation[:ZEROBYTES]
47
+ end.ldrop self.implementation[:ZEROBYTES]
48
48
  end
49
49
 
50
50
 
@@ -70,7 +70,7 @@ class Sodium::Box
70
70
  @public_key.to_str,
71
71
  @secret_key.to_str
72
72
  ) or raise Sodium::CryptoError, 'failed to close the box'
73
- end.unpad self.implementation[:BOXZEROBYTES]
73
+ end.ldrop self.implementation[:BOXZEROBYTES]
74
74
  end
75
75
 
76
76
  def open(ciphertext, nonce)
@@ -86,7 +86,7 @@ class Sodium::Box
86
86
  @public_key.to_str,
87
87
  @secret_key.to_str
88
88
  ) or raise Sodium::CryptoError, 'failed to open the box'
89
- end.unpad self.implementation[:ZEROBYTES]
89
+ end.ldrop self.implementation[:ZEROBYTES]
90
90
  end
91
91
 
92
92
  def beforenm
@@ -114,11 +114,11 @@ class Sodium::Box
114
114
  end
115
115
 
116
116
  def self._message(m)
117
- Sodium::Buffer.new(m).pad self.implementation[:ZEROBYTES]
117
+ Sodium::Buffer.lpad m, self.implementation[:ZEROBYTES]
118
118
  end
119
119
 
120
120
  def self._ciphertext(c)
121
- Sodium::Buffer.new(c).pad self.implementation[:BOXZEROBYTES]
121
+ Sodium::Buffer.lpad c, self.implementation[:BOXZEROBYTES]
122
122
  end
123
123
 
124
124
  def self._nonce(n)
@@ -14,6 +14,30 @@ class Sodium::Buffer
14
14
  self.new("\0" * size).tap {|buffer| yield buffer if block_given? }
15
15
  end
16
16
 
17
+ def self.ljust(string, size)
18
+ size = (size > string.bytesize) ? size : string.bytesize
19
+
20
+ self.empty(size) do |buffer|
21
+ buffer[0, string.bytesize] = string
22
+ end
23
+ end
24
+
25
+ def self.rjust(string, size)
26
+ size = (size > string.bytesize) ? size : string.bytesize
27
+
28
+ self.empty(size) do |buffer|
29
+ buffer[size - string.bytesize, string.bytesize] = string
30
+ end
31
+ end
32
+
33
+ def self.lpad(string, size, &block)
34
+ self.rjust(string, string.bytesize + size, &block)
35
+ end
36
+
37
+ def self.rpad(string, size, &block)
38
+ self.ljust(string, string.bytesize + size, &block)
39
+ end
40
+
17
41
  def self.new(bytes, size = bytes.bytesize)
18
42
  raise Sodium::LengthError, "buffer must be exactly #{size} bytes long" unless
19
43
  bytes.bytesize == size
@@ -37,26 +61,67 @@ class Sodium::Buffer
37
61
 
38
62
  ObjectSpace.define_finalizer self,
39
63
  self.class._finalizer(@bytes)
64
+
65
+ self.freeze
40
66
  end
41
67
 
42
- def +(other)
43
- Sodium::Buffer.new(
44
- self.to_str +
45
- Sodium::Buffer.new(other).to_str
46
- )
68
+ def ==(bytes)
69
+ bytes = Sodium::Buffer.new(bytes)
70
+
71
+ return false unless
72
+ self.bytesize == bytes.bytesize
73
+
74
+ Sodium::FFI::Crypto.sodium_memcmp(
75
+ self.to_str,
76
+ bytes.to_str,
77
+ bytes.bytesize
78
+ ) == 0
47
79
  end
48
80
 
49
- def pad(size)
50
- self.class.new(
51
- ("\0" * size) + @bytes
52
- )
81
+ def +(bytes)
82
+ Sodium::Buffer.empty(self.bytesize + bytes.bytesize) do |buffer|
83
+ buffer[0, self .bytesize] = self
84
+ buffer[self.bytesize, bytes.bytesize] = bytes
85
+ end
86
+ end
87
+
88
+ def ^(bytes)
89
+ bytes = Sodium::Buffer.new(bytes)
90
+
91
+ raise ArgumentError, %{must only XOR strings of equal length} unless
92
+ self.bytesize == bytes.bytesize
93
+
94
+ Sodium::Buffer.empty(self.bytesize) do |buffer|
95
+ Sodium::FFI::Memory.sodium_memxor(
96
+ buffer.to_str,
97
+ self.to_str,
98
+ bytes.to_str,
99
+ bytes.bytesize
100
+ )
101
+ end
53
102
  end
54
103
 
55
- def unpad(size)
56
- self.byteslice(size .. -1)
104
+ def []=(offset, size, bytes)
105
+ raise ArgumentError, %{must only assign to existing bytes in the buffer} unless
106
+ self.bytesize >= offset + size
107
+
108
+ raise ArgumentError, %{must reassign only a fixed number of bytes} unless
109
+ size == bytes.bytesize
110
+
111
+ # ensure the original bytes get cleared
112
+ bytes = Sodium::Buffer.new(bytes)
113
+
114
+ Sodium::FFI::Memory.sodium_memput(
115
+ self.to_str,
116
+ bytes.to_str,
117
+ offset,
118
+ size
119
+ )
120
+
121
+ true
57
122
  end
58
123
 
59
- def byteslice(*args)
124
+ def [](*args)
60
125
  return self.class.new(
61
126
  @bytes.byteslice(*args).to_s
62
127
  ) if (
@@ -103,6 +168,9 @@ class Sodium::Buffer
103
168
  finish += self.bytesize if finish < 0
104
169
  size = finish - start + 1
105
170
 
171
+ # this approach ensures the bytes are copied into new memory, so
172
+ # instantiating a new buffer doesn't clear the bytes in the
173
+ # existing buffer
106
174
  bytes = (start >= 0 and size >= 0) ?
107
175
  @bytes.unpack("@#{start}a#{size}").first :
108
176
  ''
@@ -110,10 +178,20 @@ class Sodium::Buffer
110
178
  self.class.new(bytes)
111
179
  end
112
180
 
181
+ alias byteslice []
182
+
113
183
  def bytesize
114
184
  @bytes.bytesize
115
185
  end
116
186
 
187
+ def rdrop(size)
188
+ self[0, self.bytesize - size]
189
+ end
190
+
191
+ def ldrop(size)
192
+ self[size, self.bytesize - size]
193
+ end
194
+
117
195
  def inspect
118
196
  # this appears to be equivalent to the default Object#inspect,
119
197
  # albeit without instance variables
@@ -6,4 +6,5 @@ end
6
6
 
7
7
  require 'sodium/ffi/lib_c'
8
8
  require 'sodium/ffi/crypto'
9
+ require 'sodium/ffi/memory'
9
10
  require 'sodium/ffi/random'
@@ -92,8 +92,9 @@ module Sodium::FFI::Crypto
92
92
 
93
93
  ffi_lib 'sodium'
94
94
 
95
- attach_function 'sodium_init', [], :void
96
- attach_function 'sodium_memzero', [:pointer, :size_t], :void
95
+ attach_function 'sodium_init', [], :void
96
+ attach_function 'sodium_memzero', [:pointer, :size_t], :void
97
+ attach_function 'sodium_memcmp', [:pointer, :pointer, :size_t], :int
97
98
 
98
99
  sodium_init
99
100
 
@@ -0,0 +1,12 @@
1
+ require 'pathname'
2
+
3
+ module Sodium::FFI::Memory
4
+ extend FFI::Library
5
+
6
+ ffi_lib Pathname.new(__FILE__).dirname.join(
7
+ %{memory.#{RbConfig::MAKEFILE_CONFIG['DLEXT']}}
8
+ )
9
+
10
+ attach_function 'sodium_memxor', [:pointer, :pointer, :pointer, :size_t ], :void
11
+ attach_function 'sodium_memput', [:pointer, :pointer, :size_t, :size_t ], :void
12
+ end
@@ -27,7 +27,7 @@ class Sodium::SecretBox
27
27
  nonce.to_str,
28
28
  @key.to_str
29
29
  ) or raise Sodium::CryptoError, 'failed to close the secret box'
30
- end.unpad self.implementation[:BOXZEROBYTES]
30
+ end.ldrop self.implementation[:BOXZEROBYTES]
31
31
  end
32
32
 
33
33
  def open(ciphertext, nonce)
@@ -42,7 +42,7 @@ class Sodium::SecretBox
42
42
  nonce.to_str,
43
43
  @key.to_str
44
44
  ) or raise Sodium::CryptoError, 'failed to open the secret box'
45
- end.unpad self.implementation[:ZEROBYTES]
45
+ end.ldrop self.implementation[:ZEROBYTES]
46
46
  end
47
47
 
48
48
  private
@@ -52,11 +52,11 @@ class Sodium::SecretBox
52
52
  end
53
53
 
54
54
  def self._message(m)
55
- Sodium::Buffer.new(m).pad self.implementation[:ZEROBYTES]
55
+ Sodium::Buffer.lpad m, self.implementation[:ZEROBYTES]
56
56
  end
57
57
 
58
58
  def self._ciphertext(c)
59
- Sodium::Buffer.new(c).pad self.implementation[:BOXZEROBYTES]
59
+ Sodium::Buffer.lpad c, self.implementation[:BOXZEROBYTES]
60
60
  end
61
61
 
62
62
  def self._nonce(n)
@@ -10,14 +10,19 @@ Gem::Specification.new do |gem|
10
10
  gem.description = 'A library for performing cryptography based on modern ciphers and protocols'
11
11
 
12
12
  gem.bindir = 'bin'
13
- gem.files = `git ls-files` .split("\n")
14
- gem.extensions = `git ls-files -- ext/*.rb`.split("\n")
15
- gem.executables = `git ls-files -- bin/*` .split("\n").map {|e| File.basename(e) }
16
- gem.test_files = `git ls-files -- spec/*` .split("\n")
13
+ gem.files = `git ls-files` .split("\n")
14
+ gem.executables = `git ls-files -- bin/*` .split("\n").map {|e| File.basename(e) }
15
+ gem.extensions = `git ls-files -- ext/**/*.rb`.split("\n")
16
+ gem.test_files = `git ls-files -- spec/*` .split("\n")
17
+
18
+ gem.requirements << 'libsodium ~> 0.5'
17
19
 
18
20
  gem.add_dependency 'ffi', '~> 1'
19
21
 
20
22
  gem.add_development_dependency 'rake', '~> 10'
21
23
  gem.add_development_dependency 'minitest', '~> 5'
22
24
  gem.add_development_dependency 'version', '~> 1'
25
+
26
+ gem.signing_key = '/Volumes/Sensitive/Keys/Gems/sodium@touset.org.key'
27
+ gem.cert_chain = [ 'certs/sodium@touset.org.cert' ]
23
28
  end
@@ -0,0 +1,24 @@
1
+ namespace :compile do
2
+ LIB_PATH = File.expand_path('../../lib', __FILE__)
3
+ EXT_PATH = File.expand_path('../../ext/sodium', __FILE__)
4
+
5
+ MEMORY_PATH = File.join EXT_PATH, 'memory'
6
+ MEMORY_SRC = File.join MEMORY_PATH, '*.c'
7
+ MEMORY_LIB = 'memory.' + RbConfig::CONFIG['DLEXT']
8
+
9
+ desc 'Compile the memory extension'
10
+ task :memory => %{#{LIB_PATH}/sodium/ffi/#{MEMORY_LIB}}
11
+
12
+ file %{#{LIB_PATH}/sodium/ffi/#{MEMORY_LIB}} => %{#{MEMORY_PATH}/Makefile} do
13
+ sh %{make -C #{MEMORY_PATH} install sitearchdir="#{LIB_PATH}"}
14
+ end
15
+
16
+ file %{#{MEMORY_PATH}/Makefile} => FileList[MEMORY_SRC] do
17
+ Dir.chdir(MEMORY_PATH) { ruby %{extconf.rb} }
18
+ end
19
+ end
20
+
21
+ desc 'Compile all native extensions'
22
+ task :compile => %w{ compile:memory }
23
+
24
+ task :test => %w{ compile }
@@ -33,12 +33,23 @@ describe Sodium::Auth::HMACSHA256 do
33
33
  end
34
34
 
35
35
  it 'must generate authenticators' do
36
+ self.klass.auth(
37
+ self.key,
38
+ self.plaintext
39
+ ).to_str.must_equal self.authenticator
40
+
36
41
  self.subject.auth(
37
42
  self.plaintext
38
43
  ).to_str.must_equal self.authenticator
39
44
  end
40
45
 
41
46
  it 'must verify authenticators' do
47
+ self.klass.verify(
48
+ self.key,
49
+ self.plaintext,
50
+ self.authenticator
51
+ ).must_equal true
52
+
42
53
  self.subject.verify(
43
54
  self.plaintext,
44
55
  self.authenticator
@@ -32,12 +32,23 @@ describe Sodium::Auth::HMACSHA512256 do
32
32
  end
33
33
 
34
34
  it 'must generate authenticators' do
35
+ self.klass.auth(
36
+ self.key,
37
+ self.plaintext
38
+ ).to_str.must_equal self.authenticator
39
+
35
40
  self.subject.auth(
36
41
  self.plaintext
37
42
  ).to_str.must_equal self.authenticator
38
43
  end
39
44
 
40
45
  it 'must verify authenticators' do
46
+ self.klass.verify(
47
+ self.key,
48
+ self.plaintext,
49
+ self.authenticator
50
+ ).must_equal true
51
+
41
52
  self.subject.verify(
42
53
  self.plaintext,
43
54
  self.authenticator
@@ -37,6 +37,32 @@ describe Sodium::Buffer do
37
37
  mock.verify
38
38
  end
39
39
 
40
+ it '::ljust must pad zero bytes on the end' do
41
+ subject.ljust('xyz', 5).to_str.must_equal "xyz\0\0"
42
+ end
43
+
44
+ it '::ljust must not pad bytes when not needed' do
45
+ subject.ljust('xyz', 2).to_str.must_equal 'xyz'
46
+ end
47
+
48
+ it '::rjust must pad zero bytes onto the front' do
49
+ subject.rjust('xyz', 5).to_str.must_equal "\0\0xyz"
50
+ end
51
+
52
+ it '::rjust must not pad bytes when not needed' do
53
+ subject.rjust('xyz', 2).to_str.must_equal 'xyz'
54
+ end
55
+
56
+ it '::lpad must prepend the required number of bytes' do
57
+ subject.lpad('xyz', 0).to_str.must_equal 'xyz'
58
+ subject.lpad('xyz', 2).to_str.must_equal "\0\0xyz"
59
+ end
60
+
61
+ it '::rpad must append the required number of bytes' do
62
+ subject.rpad('xyz', 0).to_str.must_equal 'xyz'
63
+ subject.rpad('xyz', 2).to_str.must_equal "xyz\0\0"
64
+ end
65
+
40
66
  it '::new must create a buffer containing the specified string' do
41
67
  subject.new('xyz' ).to_str.must_equal('xyz')
42
68
  subject.new('xyz' * 50).to_str.must_equal('xyz' * 50)
@@ -60,56 +86,87 @@ describe Sodium::Buffer do
60
86
  it '#initialize must wipe the buffer during finalization'
61
87
  it '#initialize must prevent the string from being paged to disk'
62
88
 
63
- it '#pad bytes onto the front' do
64
- subject.new('s').pad(3).to_str.must_equal "\0\0\0s"
89
+ it '#== must compare equality of two buffers' do
90
+ subject.new('xyz').==('xyz') .must_equal true
91
+ subject.new('xyz').==('xy') .must_equal false
92
+ subject.new('xyz').==('xyzz').must_equal false
93
+ subject.new('xyz').==('abc') .must_equal false
65
94
  end
66
95
 
67
- it '#unpad bytes from the front' do
68
- subject.new("\0\0\0s").unpad(3).to_str.must_equal 's'
96
+ it '#== must compare equality of two buffers in constant time'
97
+
98
+ it '#+ must append two buffers' do
99
+ subject.new('xyz').+('abc').to_str.must_equal 'xyzabc'
100
+ end
101
+
102
+ it '#^ must XOR two buffers' do
103
+ subject.new('xyz').^('xyz').to_str.must_equal "\0\0\0"
104
+ subject.new('xyz').^('xyz').to_str.must_equal "\0\0\0"
69
105
  end
70
106
 
71
- it '#byteslice must accept an indivdual byte offset to return' do
107
+ it '#[]= must allow replacement of byte ranges' do
108
+ subject.new('xyz').tap {|b| b[0, 3] = 'abc' }.to_str.must_equal 'abc'
109
+ subject.new('xyz').tap {|b| b[0, 2] = 'ab' }.to_str.must_equal 'abz'
110
+ subject.new('xyz').tap {|b| b[2, 1] = 'c' }.to_str.must_equal 'xyc'
111
+ end
112
+
113
+ it '#[]= must not allow resizing the buffer' do
114
+ lambda { subject.new('xyz')[0, 1] = 'ab' }.must_raise ArgumentError
115
+ lambda { subject.new('xyz')[0, 2] = 'a' }.must_raise ArgumentError
116
+ lambda { subject.new('xyz')[3, 1] = 'a' }.must_raise ArgumentError
117
+ lambda { subject.new('xyz')[2, 2] = 'ab' }.must_raise ArgumentError
118
+ end
119
+
120
+ it '#[] must accept an indivdual byte offset to return' do
72
121
  subject.new('xyz').tap do |buffer|
73
- buffer.byteslice(-4).to_str.must_equal ''
74
- buffer.byteslice(-3).to_str.must_equal 'x'
75
- buffer.byteslice(-2).to_str.must_equal 'y'
76
- buffer.byteslice(-1).to_str.must_equal 'z'
77
- buffer.byteslice( 0).to_str.must_equal 'x'
78
- buffer.byteslice( 1).to_str.must_equal 'y'
79
- buffer.byteslice( 2).to_str.must_equal 'z'
80
- buffer.byteslice( 3).to_str.must_equal ''
122
+ buffer[-4].to_str.must_equal ''
123
+ buffer[-3].to_str.must_equal 'x'
124
+ buffer[-2].to_str.must_equal 'y'
125
+ buffer[-1].to_str.must_equal 'z'
126
+ buffer[ 0].to_str.must_equal 'x'
127
+ buffer[ 1].to_str.must_equal 'y'
128
+ buffer[ 2].to_str.must_equal 'z'
129
+ buffer[ 3].to_str.must_equal ''
81
130
  end
82
131
  end
83
132
 
84
- it '#byteslice must accept ranges of bytes to return' do
133
+ it '#[] must accept ranges of bytes to return' do
85
134
  subject.new('xyz').tap do |buffer|
86
- buffer.byteslice( 0.. 0).to_str.must_equal 'x'
87
- buffer.byteslice( 0.. 1).to_str.must_equal 'xy'
88
- buffer.byteslice( 0.. 2).to_str.must_equal 'xyz'
89
- buffer.byteslice( 0.. 3).to_str.must_equal 'xyz'
90
- buffer.byteslice( 1..-1).to_str.must_equal 'yz'
91
- buffer.byteslice( 2..-2).to_str.must_equal ''
92
- buffer.byteslice(-3..-1).to_str.must_equal 'xyz'
93
- buffer.byteslice(-4.. 1).to_str.must_equal ''
135
+ buffer[ 0.. 0].to_str.must_equal 'x'
136
+ buffer[ 0.. 1].to_str.must_equal 'xy'
137
+ buffer[ 0.. 2].to_str.must_equal 'xyz'
138
+ buffer[ 0.. 3].to_str.must_equal 'xyz'
139
+ buffer[ 1..-1].to_str.must_equal 'yz'
140
+ buffer[ 2..-2].to_str.must_equal ''
141
+ buffer[-3..-1].to_str.must_equal 'xyz'
142
+ buffer[-4.. 1].to_str.must_equal ''
94
143
  end
95
144
  end
96
145
 
97
- it '#byteslice must accept an offset and number of bytes to return' do
146
+ it '#[] must accept an offset and number of bytes to return' do
98
147
  subject.new('xyz').tap do |buffer|
99
- buffer.byteslice( 0, 0).to_str.must_equal ''
100
- buffer.byteslice( 0, 1).to_str.must_equal 'x'
101
- buffer.byteslice( 0, 3).to_str.must_equal 'xyz'
102
- buffer.byteslice( 2, 4).to_str.must_equal 'z'
103
- buffer.byteslice( 2, 1).to_str.must_equal 'z'
104
- buffer.byteslice(-2, 1).to_str.must_equal 'y'
105
- buffer.byteslice( 0, -1).to_str.must_equal ''
148
+ buffer[ 0, 0].to_str.must_equal ''
149
+ buffer[ 0, 1].to_str.must_equal 'x'
150
+ buffer[ 0, 3].to_str.must_equal 'xyz'
151
+ buffer[ 2, 4].to_str.must_equal 'z'
152
+ buffer[ 2, 1].to_str.must_equal 'z'
153
+ buffer[-2, 1].to_str.must_equal 'y'
154
+ buffer[ 0, -1].to_str.must_equal ''
106
155
  end
107
156
  end
108
157
 
109
- it '#bytesize must return its length' do
158
+ it '#[] must return its length' do
110
159
  subject.new('testing').bytesize.must_equal 7
111
160
  end
112
161
 
162
+ it '#ldrop must drop bytes off the left' do
163
+ subject.new('xyz').ldrop(2).to_str.must_equal('z')
164
+ end
165
+
166
+ it '#rdrop must drop bytes off the right' do
167
+ subject.new('xyz').rdrop(2).to_str.must_equal('x')
168
+ end
169
+
113
170
  it '#inspect must not reveal its instance variables' do
114
171
  subject.new('blah').inspect.wont_include 'blah'
115
172
  end
metadata CHANGED
@@ -1,15 +1,36 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sodium
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.6.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
8
8
  - Stephen Touset
9
9
  autorequire:
10
10
  bindir: bin
11
- cert_chain: []
12
- date: 2013-06-05 00:00:00.000000000 Z
11
+ cert_chain:
12
+ - |
13
+ -----BEGIN CERTIFICATE-----
14
+ MIIDMDCCAhigAwIBAgIBADANBgkqhkiG9w0BAQUFADA+MQ8wDQYDVQQDDAZzb2Rp
15
+ dW0xFjAUBgoJkiaJk/IsZAEZFgZ0b3VzZXQxEzARBgoJkiaJk/IsZAEZFgNvcmcw
16
+ HhcNMTMwNjI4MDEzMzQ4WhcNMTQwNjI4MDEzMzQ4WjA+MQ8wDQYDVQQDDAZzb2Rp
17
+ dW0xFjAUBgoJkiaJk/IsZAEZFgZ0b3VzZXQxEzARBgoJkiaJk/IsZAEZFgNvcmcw
18
+ ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCh3C2P1jW4MvcpXioNkqW/
19
+ HiD9ZpTew1tHTolQclBBmOmOApLUPc9PIsfbohph83Z82x+BWbjEdL5NAfEQjRVu
20
+ O8JUBJh0YRDF9P7fDtd9w0b3mmhumujbEsmDYs1ru5VvjgCh+Hfxgddlpha0KmxQ
21
+ 0j3h/Uj27tFbE33dIRqb5dBBBnnIM5CqRMu5/gDeXN5GrjYK3JfZlzZRECjnfuR5
22
+ qDqoQFJK5ZmaEFm9E88HdAIS+sV9zb1OCYlADr3EB/a3Shxedx4SsX7oBPyNfsRb
23
+ kMdTr+VynH/OEPSo0dW1DuKpUCmNBscrTOwhn6hJUDNpr6f0CTfYG9jGJY3p5JMt
24
+ AgMBAAGjOTA3MAkGA1UdEwQCMAAwHQYDVR0OBBYEFIu3aZS82t6UR4Z5eON3t2LI
25
+ AHPeMAsGA1UdDwQEAwIEsDANBgkqhkiG9w0BAQUFAAOCAQEAkjXdsFKC9mQfT3tP
26
+ PNtArZ+Y/MhEfNXgKeTIHuIXMaFe86ekTxYxfIziH5VpGtIzeVxXE4teNNI/tpSX
27
+ DcBNspVsx4N/PBqVdtD2KqTO+yrHiER7T9XEEctMgmFQB+NGMLNIpde1tGS8hX2p
28
+ mcWzr4EAsJwbtLa3HHPwNrr3+Xj1YA8SvLffsJ0nUv/DeqkDCr/CG8mfPO65KtvX
29
+ rp7h6AAaApIXd1JOn/ady0QxBNc9Rcjg0iG3lF4bRozRR2/B3cNC9PlHUhObWLYh
30
+ /fYRy+X91OOKL0AyBJRoXo4iT7YeerdeYuWB9HZjJZSR13qeIn2vgJOS4qpPgqyu
31
+ S0VfcA==
32
+ -----END CERTIFICATE-----
33
+ date: 2013-06-28 00:00:00.000000000 Z
13
34
  dependencies:
14
35
  - !ruby/object:Gem::Dependency
15
36
  name: ffi
@@ -78,16 +99,22 @@ dependencies:
78
99
  description: A library for performing cryptography based on modern ciphers and protocols
79
100
  email: stephen@touset.org
80
101
  executables: []
81
- extensions: []
102
+ extensions:
103
+ - ext/sodium/memory/extconf.rb
82
104
  extra_rdoc_files: []
83
105
  files:
84
106
  - .gitignore
85
107
  - .travis.yml
108
+ - CHANGELOG.md
86
109
  - Gemfile
87
110
  - README.md
88
111
  - Rakefile
89
112
  - VERSION
113
+ - certs/sodium@touset.org.cert
114
+ - certs/sodium@touset.org.pub.gpg
90
115
  - config/nacl_ffi.yml
116
+ - ext/sodium/memory/extconf.rb
117
+ - ext/sodium/memory/memory.c
91
118
  - lib/sodium.rb
92
119
  - lib/sodium/auth.rb
93
120
  - lib/sodium/box.rb
@@ -96,6 +123,7 @@ files:
96
123
  - lib/sodium/ffi.rb
97
124
  - lib/sodium/ffi/crypto.rb
98
125
  - lib/sodium/ffi/lib_c.rb
126
+ - lib/sodium/ffi/memory.rb
99
127
  - lib/sodium/ffi/random.rb
100
128
  - lib/sodium/hash.rb
101
129
  - lib/sodium/one_time_auth.rb
@@ -104,7 +132,7 @@ files:
104
132
  - lib/sodium/sign.rb
105
133
  - lib/sodium/version.rb
106
134
  - sodium.gemspec
107
- - sodium.pub.gpg
135
+ - tasks/extensions.rake
108
136
  - tasks/libsodium.rake
109
137
  - tasks/test.rake
110
138
  - tasks/version.rake
@@ -144,7 +172,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
144
172
  - - '>='
145
173
  - !ruby/object:Gem::Version
146
174
  version: '0'
147
- requirements: []
175
+ requirements:
176
+ - libsodium ~> 0.5
148
177
  rubyforge_project:
149
178
  rubygems_version: 1.8.25
150
179
  signing_key:
Binary file