sodium 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
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