sodium 0.6.2 → 0.7.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.
@@ -5,5 +5,8 @@ module Sodium::FFI::LibC
5
5
 
6
6
  ffi_lib FFI::Library::LIBC
7
7
 
8
+ attach_function 'calloc', [:size_t, :size_t], :pointer
9
+ attach_function 'free', [:pointer], :void
10
+
8
11
  attach_function 'mlock', [:pointer, :size_t], :int
9
12
  end
@@ -8,9 +8,9 @@ class Sodium::Hash
8
8
 
9
9
  Sodium::Buffer.empty self.implementation[:BYTES] do |digest|
10
10
  self.implementation.nacl(
11
- digest.to_str,
12
- message.to_str,
13
- message.to_str.bytesize
11
+ digest .to_ptr,
12
+ message.to_ptr,
13
+ message.bytesize
14
14
  ) or raise Sodium::CryptoError, 'failed to generate a hash for the message'
15
15
  end
16
16
  end
@@ -16,10 +16,10 @@ class Sodium::OneTimeAuth
16
16
 
17
17
  Sodium::Buffer.empty self.implementation[:BYTES] do |authenticator|
18
18
  self.implementation.nacl(
19
- authenticator.to_str,
20
- message.to_str,
21
- message.to_str.bytesize,
22
- @key.to_str
19
+ authenticator.to_ptr,
20
+ message .to_ptr,
21
+ message .bytesize,
22
+ @key .to_ptr
23
23
  ) or raise Sodium::CryptoError, 'failed to generate an authenticator'
24
24
  end
25
25
  end
@@ -29,10 +29,10 @@ class Sodium::OneTimeAuth
29
29
  authenticator = self.class._authenticator(authenticator)
30
30
 
31
31
  self.implementation.nacl_verify(
32
- authenticator.to_str,
33
- message.to_str,
34
- message.to_str.bytesize,
35
- @key.to_str
32
+ authenticator.to_ptr,
33
+ message .to_ptr,
34
+ message .bytesize,
35
+ @key .to_ptr
36
36
  )
37
37
  end
38
38
 
@@ -4,7 +4,7 @@ module Sodium::Random
4
4
  def self.bytes(size)
5
5
  Sodium::Buffer.empty(size) do |buffer|
6
6
  Sodium::FFI::Random.randombytes_buf(
7
- buffer.to_str,
7
+ buffer.to_ptr,
8
8
  buffer.bytesize
9
9
  )
10
10
  end
@@ -21,11 +21,11 @@ class Sodium::SecretBox
21
21
 
22
22
  Sodium::Buffer.empty(message.bytesize) do |ciphertext|
23
23
  self.implementation.nacl(
24
- ciphertext.to_str,
25
- message.to_str,
26
- message.to_str.bytesize,
27
- nonce.to_str,
28
- @key.to_str
24
+ ciphertext .to_ptr,
25
+ message .to_ptr,
26
+ message .bytesize,
27
+ nonce .to_ptr,
28
+ @key .to_ptr
29
29
  ) or raise Sodium::CryptoError, 'failed to close the secret box'
30
30
  end.ldrop self.implementation[:BOXZEROBYTES]
31
31
  end
@@ -36,11 +36,11 @@ class Sodium::SecretBox
36
36
 
37
37
  Sodium::Buffer.empty(ciphertext.bytesize) do |message|
38
38
  self.implementation.nacl_open(
39
- message.to_str,
40
- ciphertext.to_str,
41
- ciphertext.to_str.bytesize,
42
- nonce.to_str,
43
- @key.to_str
39
+ message .to_ptr,
40
+ ciphertext .to_ptr,
41
+ ciphertext .bytesize,
42
+ nonce .to_ptr,
43
+ @key .to_ptr
44
44
  ) or raise Sodium::CryptoError, 'failed to open the secret box'
45
45
  end.ldrop self.implementation[:ZEROBYTES]
46
46
  end
@@ -8,8 +8,8 @@ class Sodium::Sign
8
8
  secret_key = Sodium::Buffer.empty self.implementation[:SECRETKEYBYTES]
9
9
 
10
10
  self.implementation.nacl_keypair(
11
- public_key.to_str,
12
- secret_key.to_str
11
+ public_key.to_ptr,
12
+ secret_key.to_ptr
13
13
  ) or raise Sodium::CryptoError, 'failed to generate a keypair'
14
14
 
15
15
  return secret_key, public_key
@@ -22,11 +22,11 @@ class Sodium::Sign
22
22
  mlen = FFI::MemoryPointer.new(:ulong_long, 1, true)
23
23
 
24
24
  self.implementation.nacl_open(
25
- message.to_str,
25
+ message .to_ptr,
26
26
  mlen,
27
- signature.to_str,
28
- signature.to_str.bytesize,
29
- key.to_str
27
+ signature .to_ptr,
28
+ signature .bytesize,
29
+ key .to_ptr
30
30
  )
31
31
  end
32
32
 
@@ -40,18 +40,18 @@ class Sodium::Sign
40
40
  slen = FFI::MemoryPointer.new(:ulong_long, 1, true)
41
41
 
42
42
  self.implementation.nacl(
43
- signature.to_str,
43
+ signature .to_ptr,
44
44
  slen,
45
- message.to_str,
46
- message.to_str.bytesize,
47
- @key.to_str
45
+ message .to_ptr,
46
+ message .bytesize,
47
+ @key .to_ptr
48
48
  ) or raise Sodium::CryptoError, 'failed to generate signature'
49
49
 
50
50
  # signatures actually encode the message itself at the end, so we
51
51
  # slice off only the signature bytes
52
52
  signature.byteslice(
53
53
  0,
54
- slen.read_ulong_long - message.to_str.bytesize
54
+ slen.read_ulong_long - message.bytesize
55
55
  )
56
56
  end
57
57
 
@@ -9,12 +9,18 @@ namespace :compile do
9
9
  desc 'Compile the memory extension'
10
10
  task :memory => %{#{LIB_PATH}/sodium/ffi/#{MEMORY_LIB}}
11
11
 
12
- file %{#{LIB_PATH}/sodium/ffi/#{MEMORY_LIB}} => %{#{MEMORY_PATH}/Makefile} do
12
+ file %{#{LIB_PATH}/sodium/ffi/#{MEMORY_LIB}} => FileList[MEMORY_SRC] do
13
+ Dir.chdir(MEMORY_PATH) { ruby %{extconf.rb} }
13
14
  sh %{make -C #{MEMORY_PATH} install sitearchdir="#{LIB_PATH}"}
14
15
  end
15
16
 
16
- file %{#{MEMORY_PATH}/Makefile} => FileList[MEMORY_SRC] do
17
- Dir.chdir(MEMORY_PATH) { ruby %{extconf.rb} }
17
+ task :clean do
18
+ sh %{make -C #{MEMORY_PATH} realclean} if
19
+ File.exist? %{#{MEMORY_PATH}/Makefile}
20
+ end
21
+
22
+ task :clobber do
23
+ CLOBBER.add %{#{LIB_PATH}/sodium/ffi/#{MEMORY_LIB}}
18
24
  end
19
25
  end
20
26
 
@@ -22,3 +28,6 @@ desc 'Compile all native extensions'
22
28
  task :compile => %w{ compile:memory }
23
29
 
24
30
  task :test => %w{ compile }
31
+
32
+ task :clean => :'compile:clean'
33
+ task :clobber => :'compile:clobber'
@@ -36,11 +36,11 @@ describe Sodium::Auth::HMACSHA256 do
36
36
  self.klass.auth(
37
37
  self.key,
38
38
  self.plaintext
39
- ).to_str.must_equal self.authenticator
39
+ ).to_s.must_equal self.authenticator
40
40
 
41
41
  self.subject.auth(
42
42
  self.plaintext
43
- ).to_str.must_equal self.authenticator
43
+ ).to_s.must_equal self.authenticator
44
44
  end
45
45
 
46
46
  it 'must verify authenticators' do
@@ -35,11 +35,11 @@ describe Sodium::Auth::HMACSHA512256 do
35
35
  self.klass.auth(
36
36
  self.key,
37
37
  self.plaintext
38
- ).to_str.must_equal self.authenticator
38
+ ).to_s.must_equal self.authenticator
39
39
 
40
40
  self.subject.auth(
41
41
  self.plaintext
42
- ).to_str.must_equal self.authenticator
42
+ ).to_s.must_equal self.authenticator
43
43
  end
44
44
 
45
45
  it 'must verify authenticators' do
@@ -26,12 +26,12 @@ describe Sodium::Auth do
26
26
  sodium_mock_default(self.klass) do |klass, mock|
27
27
  mock.expect :[], 0, [:KEYBYTES]
28
28
 
29
- klass.key.to_str.must_equal ''
29
+ klass.key.to_s.must_equal ''
30
30
  end
31
31
  end
32
32
 
33
33
  it 'must raise when instantiating with an invalid key' do
34
- lambda { self.klass.new(self.key.to_str[0..-2]) }.
34
+ lambda { self.klass.new(self.key.to_s[0..-2]) }.
35
35
  must_raise Sodium::LengthError
36
36
  end
37
37
 
@@ -47,18 +47,18 @@ describe Sodium::Box::Curve25519XSalsa20Poly1305 do
47
47
  self.subject.box(
48
48
  self.plaintext,
49
49
  self.nonce
50
- ).to_str.must_equal self.ciphertext
50
+ ).to_s.must_equal self.ciphertext
51
51
  end
52
52
 
53
53
  it 'must open boxes' do
54
54
  self.subject.open(
55
55
  self.ciphertext,
56
56
  self.nonce
57
- ).to_str.must_equal self.plaintext
57
+ ).to_s.must_equal self.plaintext
58
58
  end
59
59
 
60
60
  it 'must generate shared keys' do
61
- self.subject.beforenm.to_str.must_equal self.shared_key
61
+ self.subject.beforenm.to_s.must_equal self.shared_key
62
62
  end
63
63
 
64
64
  it 'must generate closed boxes with shared keys' do
@@ -66,7 +66,7 @@ describe Sodium::Box::Curve25519XSalsa20Poly1305 do
66
66
  self.shared_key,
67
67
  self.plaintext,
68
68
  self.nonce
69
- ).to_str.must_equal self.ciphertext
69
+ ).to_s.must_equal self.ciphertext
70
70
  end
71
71
 
72
72
  it 'must open boxes with shared keys' do
@@ -74,6 +74,6 @@ describe Sodium::Box::Curve25519XSalsa20Poly1305 do
74
74
  self.shared_key,
75
75
  self.ciphertext,
76
76
  self.nonce
77
- ).to_str.must_equal self.plaintext
77
+ ).to_s.must_equal self.plaintext
78
78
  end
79
79
  end
@@ -24,29 +24,29 @@ describe Sodium::Box do
24
24
 
25
25
  it 'must mint keypairs from the default implementation' do
26
26
  sodium_mock_default(self.klass) do |klass, mock|
27
- mock.expect :nacl_keypair, true, [ '', '' ]
27
+ mock.expect :nacl_keypair, true, [ FFI::Pointer, FFI::Pointer ]
28
28
  mock.expect :[], 0, [:PUBLICKEYBYTES]
29
29
  mock.expect :[], 0, [:SECRETKEYBYTES]
30
30
 
31
31
  sk, pk = klass.keypair
32
32
 
33
- sk.to_str.must_equal ''
34
- pk.to_str.must_equal ''
33
+ sk.to_s.must_equal ''
34
+ pk.to_s.must_equal ''
35
35
  end
36
36
  end
37
37
 
38
38
  it 'must raise when instantiating with an invalid keypair' do
39
39
  secret_key, public_key = self.keypair
40
40
 
41
- lambda { self.klass.new(secret_key.to_str[0..-2], public_key) }.
41
+ lambda { self.klass.new(secret_key.to_s[0..-2], public_key) }.
42
42
  must_raise Sodium::LengthError
43
43
 
44
- lambda { self.klass.new(secret_key, public_key.to_str[0..-2]) }.
44
+ lambda { self.klass.new(secret_key, public_key.to_s[0..-2]) }.
45
45
  must_raise Sodium::LengthError
46
46
  end
47
47
 
48
48
  it 'must raise when receiving an invalid nonce' do
49
- lambda { self.subject.box('message', self.subject.nonce.to_str[0..-2]) }.
49
+ lambda { self.subject.box('message', self.subject.nonce.to_s[0..-2]) }.
50
50
  must_raise Sodium::LengthError
51
51
  end
52
52
 
@@ -3,29 +3,35 @@ require 'test_helper'
3
3
  describe Sodium::Buffer do
4
4
  subject { Sodium::Buffer }
5
5
 
6
+ def trigger_gc!
7
+ GC.start
8
+ 1_000_000.times { Object.new }
9
+ GC.start
10
+ end
11
+
6
12
  it '::key must securely generate random keys of specified length' do
7
13
  Sodium::Random.stub(:bytes, lambda {|l| ' ' * l }) do
8
- subject.key( 7).to_str.must_equal(' ' * 7)
9
- subject.key( 8).to_str.must_equal(' ' * 8)
10
- subject.key(16).to_str.must_equal(' ' * 16)
11
- subject.key(32).to_str.must_equal(' ' * 32)
12
- subject.key(64).to_str.must_equal(' ' * 64)
14
+ subject.key( 7).to_s.must_equal(' ' * 7)
15
+ subject.key( 8).to_s.must_equal(' ' * 8)
16
+ subject.key(16).to_s.must_equal(' ' * 16)
17
+ subject.key(32).to_s.must_equal(' ' * 32)
18
+ subject.key(64).to_s.must_equal(' ' * 64)
13
19
  end
14
20
  end
15
21
 
16
22
  it '::nonce must securely generate random nonces of specified length' do
17
23
  Sodium::Random.stub(:bytes, lambda {|l| ' ' * l }) do
18
- subject.nonce( 7).to_str.must_equal(' ' * 7)
19
- subject.nonce( 8).to_str.must_equal(' ' * 8)
20
- subject.nonce(16).to_str.must_equal(' ' * 16)
21
- subject.nonce(32).to_str.must_equal(' ' * 32)
22
- subject.nonce(64).to_str.must_equal(' ' * 64)
24
+ subject.nonce( 7).to_s.must_equal(' ' * 7)
25
+ subject.nonce( 8).to_s.must_equal(' ' * 8)
26
+ subject.nonce(16).to_s.must_equal(' ' * 16)
27
+ subject.nonce(32).to_s.must_equal(' ' * 32)
28
+ subject.nonce(64).to_s.must_equal(' ' * 64)
23
29
  end
24
30
  end
25
31
 
26
32
  it '::empty must generate an empty buffer of specified length' do
27
- subject.empty(32).to_str.must_equal("\0" * 32)
28
- subject.empty(40).to_str.must_equal("\0" * 40)
33
+ subject.empty(32).to_s.must_equal("\0" * 32)
34
+ subject.empty(40).to_s.must_equal("\0" * 40)
29
35
  end
30
36
 
31
37
  it '::empty must yield to a block when given' do
@@ -38,43 +44,44 @@ describe Sodium::Buffer do
38
44
  end
39
45
 
40
46
  it '::ljust must pad zero bytes on the end' do
41
- subject.ljust('xyz', 5).to_str.must_equal "xyz\0\0"
47
+ subject.ljust('xyz', 5).to_s.must_equal "xyz\0\0"
42
48
  end
43
49
 
44
50
  it '::ljust must not pad bytes when not needed' do
45
- subject.ljust('xyz', 2).to_str.must_equal 'xyz'
51
+ subject.ljust('xyz', 2).to_s.must_equal 'xyz'
46
52
  end
47
53
 
48
54
  it '::rjust must pad zero bytes onto the front' do
49
- subject.rjust('xyz', 5).to_str.must_equal "\0\0xyz"
55
+ subject.rjust('xyz', 5).to_s.must_equal "\0\0xyz"
50
56
  end
51
57
 
52
58
  it '::rjust must not pad bytes when not needed' do
53
- subject.rjust('xyz', 2).to_str.must_equal 'xyz'
59
+ subject.rjust('xyz', 2).to_s.must_equal 'xyz'
54
60
  end
55
61
 
56
62
  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"
63
+ subject.lpad('xyz', 0).to_s.must_equal 'xyz'
64
+ subject.lpad('xyz', 2).to_s.must_equal "\0\0xyz"
59
65
  end
60
66
 
61
67
  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"
68
+ subject.rpad('xyz', 0).to_s.must_equal 'xyz'
69
+ subject.rpad('xyz', 2).to_s.must_equal "xyz\0\0"
64
70
  end
65
71
 
66
72
  it '::new must create a buffer containing the specified string' do
67
- subject.new('xyz' ).to_str.must_equal('xyz')
68
- subject.new('xyz' * 50).to_str.must_equal('xyz' * 50)
73
+ subject.new('xyz' ).to_s.must_equal('xyz')
74
+ subject.new('xyz' * 50).to_s.must_equal('xyz' * 50)
69
75
  end
70
76
 
71
77
  it '::new must do optional length checking' do
72
- lambda { subject.new('xyz', 4).to_str }.
78
+ lambda { subject.new('xyz', 4).to_s }.
73
79
  must_raise Sodium::LengthError
74
80
  end
75
81
 
76
82
  it '#initialize must freeze its bytes' do
77
- subject.new('s').to_str.must_be :frozen?
83
+ subject.new('s').to_ptr.must_be :frozen?
84
+ subject.new('s').to_s .must_be :frozen?
78
85
  end
79
86
 
80
87
  it '#initialize must wipe the memory from the original string' do
@@ -87,27 +94,27 @@ describe Sodium::Buffer do
87
94
  it '#initialize must prevent the string from being paged to disk'
88
95
 
89
96
  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
97
+ subject.new('xyz').must_be :==, 'xyz'
98
+ subject.new('xyz').wont_be :==, 'xy'
99
+ subject.new('xyz').wont_be :==, 'xyzz'
100
+ subject.new('xyz').wont_be :==, 'abc'
94
101
  end
95
102
 
96
103
  it '#== must compare equality of two buffers in constant time'
97
104
 
98
105
  it '#+ must append two buffers' do
99
- subject.new('xyz').+('abc').to_str.must_equal 'xyzabc'
106
+ subject.new('xyz').+('abc').to_s.must_equal 'xyzabc'
100
107
  end
101
108
 
102
109
  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"
110
+ subject.new('xyz').^('xyz').to_s.must_equal "\0\0\0"
111
+ subject.new('xyz').^('xyz').to_s.must_equal "\0\0\0"
105
112
  end
106
113
 
107
114
  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'
115
+ subject.new('xyz').tap {|b| b[0, 3] = 'abc' }.to_s.must_equal 'abc'
116
+ subject.new('xyz').tap {|b| b[0, 2] = 'ab' }.to_s.must_equal 'abz'
117
+ subject.new('xyz').tap {|b| b[2, 1] = 'c' }.to_s.must_equal 'xyc'
111
118
  end
112
119
 
113
120
  it '#[]= must not allow resizing the buffer' do
@@ -117,61 +124,61 @@ describe Sodium::Buffer do
117
124
  lambda { subject.new('xyz')[2, 2] = 'ab' }.must_raise ArgumentError
118
125
  end
119
126
 
120
- it '#[] must accept an indivdual byte offset to return' do
121
- subject.new('xyz').tap do |buffer|
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 ''
130
- end
131
- end
132
-
133
- it '#[] must accept ranges of bytes to return' do
134
- subject.new('xyz').tap do |buffer|
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 ''
143
- end
144
- end
145
-
146
127
  it '#[] must accept an offset and number of bytes to return' do
147
128
  subject.new('xyz').tap do |buffer|
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 ''
129
+ buffer[ 0, 0].to_s.must_equal ''
130
+ buffer[ 0, 1].to_s.must_equal 'x'
131
+ buffer[ 0, 3].to_s.must_equal 'xyz'
132
+ buffer[ 2, 1].to_s.must_equal 'z'
155
133
  end
156
134
  end
157
135
 
158
- it '#[] must return its length' do
136
+ it '#bytesize must return its length' do
159
137
  subject.new('testing').bytesize.must_equal 7
160
138
  end
161
139
 
162
140
  it '#ldrop must drop bytes off the left' do
163
- subject.new('xyz').ldrop(2).to_str.must_equal('z')
141
+ subject.new('xyz').ldrop(2).to_s.must_equal('z')
164
142
  end
165
143
 
166
144
  it '#rdrop must drop bytes off the right' do
167
- subject.new('xyz').rdrop(2).to_str.must_equal('x')
145
+ subject.new('xyz').rdrop(2).to_s.must_equal('x')
168
146
  end
169
147
 
170
148
  it '#inspect must not reveal its instance variables' do
171
149
  subject.new('blah').inspect.wont_include 'blah'
172
150
  end
173
151
 
174
- it '#to_str must return its internal bytes' do
175
- subject.new('xyz').to_str.must_equal('xyz')
152
+ it '#to_s must return its internal bytes' do
153
+ subject.new('xyz').to_s.must_equal('xyz')
154
+ end
155
+
156
+ it '#to_ptr must return the live pointer to its data' do
157
+ subject.new('xyz').to_ptr.read_bytes(3).must_equal('xyz')
158
+ end
159
+
160
+
161
+ it 'must wipe its contents when garbage collected' do
162
+ address = lambda { Sodium::Buffer.new('xyz').to_ptr.address }
163
+ pointer = FFI::Pointer.new(address.call)
164
+
165
+ trigger_gc!
166
+
167
+ pointer.read_bytes(3).wont_equal('xyz')
168
+ end
169
+
170
+ it 'must free its contents when garbage collected' do
171
+ flag = MiniTest::Mock.new
172
+ free = lambda {|pointer| flag.called(pointer) }
173
+ flag.expect :called, nil, [ FFI::Pointer ]
174
+
175
+ Sodium::FFI::LibC.stub(:free, free) do
176
+ Sodium::Buffer.new('xyz')
177
+
178
+ trigger_gc!
179
+ end
180
+
181
+
182
+ flag.verify
176
183
  end
177
184
  end