ffi-libsodium 0.1.10 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/lib/crypto/aead/chacha20_poly1305.rb +17 -12
- data/lib/crypto/auth.rb +3 -2
- data/lib/crypto/box.rb +30 -34
- data/lib/crypto/generic_hash.rb +13 -33
- data/lib/crypto/one_time_auth.rb +3 -4
- data/lib/crypto/pw_hash/scrypt_salsa208_sha256.rb +13 -24
- data/lib/crypto/scalar_mult.rb +3 -2
- data/lib/crypto/secret_box.rb +27 -26
- data/lib/crypto/short_hash.rb +2 -1
- data/lib/crypto/sign.rb +8 -13
- data/lib/crypto/sign/ed25519.rb +2 -0
- data/lib/libsodium.rb +4 -1
- data/lib/random_bytes.rb +2 -0
- data/lib/sodium.rb +4 -35
- data/lib/sodium/buffer.rb +3 -5
- data/lib/sodium/errors.rb +3 -3
- data/lib/sodium/mprotect.rb +30 -0
- data/lib/sodium/secret_buffer.rb +19 -16
- data/lib/sodium/utils.rb +29 -54
- data/lib/sodium/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 95a7d9bb37cc560f3dfbb7a72a6bcf31ffdf63d6
|
4
|
+
data.tar.gz: 636823f16c86f508ff3180c56edb357a6b8afa2c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e101ac68e41004c5b1dab8594baf37a6bd3c68fa6bb4981fdc556ef7d6d9cfac3e5aadaaec9c4ff11c524570fcf49500459aca5eed2486c8af7835235a0a5b61
|
7
|
+
data.tar.gz: 9c3e394cdf2941d370ad3c690c0bf17a335ba4cc9aba9aea5fa61b88bdff986369493be2348aa3d6663fff6e6e98c3aa6901d5fbefd5b59a5d3893f5bc696fa1
|
data/README.md
CHANGED
@@ -11,7 +11,7 @@ bundle update
|
|
11
11
|
require 'bundler/setup'
|
12
12
|
require 'libsodium'
|
13
13
|
|
14
|
-
password = 'test123'
|
14
|
+
password = Crypto.generichash('test123')
|
15
15
|
|
16
16
|
salt = Crypto::PwHash::ScryptSalsa208SHA256.salt
|
17
17
|
key = Crypto::PwHash.scryptsalsa208sha256(Crypto::Auth::KEYBYTES, password, salt)
|
@@ -46,7 +46,6 @@ module Crypto
|
|
46
46
|
check_length(key, KEYBYTES, :SecretKey)
|
47
47
|
|
48
48
|
ciphertext = Sodium::Buffer.new(:uchar, message_len + ABYTES)
|
49
|
-
ciphertext.primitive = PRIMITIVE
|
50
49
|
key.readonly if key.is_a?(Sodium::SecretBuffer)
|
51
50
|
crypto_aead_chacha20poly1305_encrypt(ciphertext, nil, message, message_len, additional_data, get_size(additional_data), nil, nonce, key)
|
52
51
|
|
@@ -56,22 +55,28 @@ module Crypto
|
|
56
55
|
end
|
57
56
|
|
58
57
|
def decrypt(ciphertext, additional_data, nonce, key)
|
59
|
-
|
58
|
+
ciphertext_len = get_size(ciphertext)
|
59
|
+
if (decrypted_len = ciphertext_len - ABYTES) > 0
|
60
|
+
check_length(nonce, NPUBBYTES, :Nonce)
|
61
|
+
check_length(key, KEYBYTES, :SecretKey)
|
62
|
+
|
63
|
+
decrypted = Sodium::Buffer.new(:uchar, decrypted_len)
|
64
|
+
key.readonly if key.is_a?(Sodium::SecretBuffer)
|
65
|
+
if crypto_aead_chacha20poly1305_decrypt(decrypted, nil, nil, ciphertext, ciphertext_len, additional_data, get_size(additional_data), nonce, key) == 0
|
66
|
+
decrypted
|
67
|
+
else
|
68
|
+
raise Sodium::CryptoError, "Message forged", caller
|
69
|
+
end
|
70
|
+
else
|
60
71
|
fail Sodium::LengthError, "Ciphertext is too short", caller
|
61
72
|
end
|
62
|
-
check_length(nonce, NPUBBYTES, :Nonce)
|
63
|
-
check_length(key, KEYBYTES, :SecretKey)
|
64
|
-
|
65
|
-
decrypted = Sodium::Buffer.new(:uchar, ciphertext_len - ABYTES)
|
66
|
-
key.readonly if key.is_a?(Sodium::SecretBuffer)
|
67
|
-
unless crypto_aead_chacha20poly1305_decrypt(decrypted, nil, nil, ciphertext, ciphertext_len, additional_data, get_size(additional_data), nonce, key).zero?
|
68
|
-
raise Sodium::CryptoError, "Message forged", caller
|
69
|
-
end
|
70
|
-
|
71
|
-
decrypted
|
72
73
|
ensure
|
73
74
|
key.noaccess if key.is_a?(Sodium::SecretBuffer)
|
74
75
|
end
|
75
76
|
end
|
77
|
+
|
78
|
+
Chacha20Poly1305.freeze
|
76
79
|
end
|
80
|
+
|
81
|
+
AEAD.freeze
|
77
82
|
end
|
data/lib/crypto/auth.rb
CHANGED
@@ -27,7 +27,6 @@ module Crypto
|
|
27
27
|
check_length(key, KEYBYTES, :SecretKey)
|
28
28
|
|
29
29
|
mac = Sodium::Buffer.new(:uchar, BYTES)
|
30
|
-
mac.primitive = PRIMITIVE
|
31
30
|
key.readonly if key.is_a?(Sodium::SecretBuffer)
|
32
31
|
crypto_auth(mac, message, get_size(message), key)
|
33
32
|
|
@@ -41,12 +40,14 @@ module Crypto
|
|
41
40
|
check_length(key, KEYBYTES, :SecretKey)
|
42
41
|
|
43
42
|
key.readonly if key.is_a?(Sodium::SecretBuffer)
|
44
|
-
crypto_auth_verify(mac, message, get_size(message), key)
|
43
|
+
crypto_auth_verify(mac, message, get_size(message), key) == 0
|
45
44
|
ensure
|
46
45
|
key.noaccess if key.is_a?(Sodium::SecretBuffer)
|
47
46
|
end
|
48
47
|
end
|
49
48
|
|
49
|
+
Auth.freeze
|
50
|
+
|
50
51
|
module_function
|
51
52
|
|
52
53
|
def auth(*args)
|
data/lib/crypto/box.rb
CHANGED
@@ -40,9 +40,7 @@ module Crypto
|
|
40
40
|
|
41
41
|
def keypair
|
42
42
|
public_key = Sodium::Buffer.new(:uchar, PUBLICKEYBYTES)
|
43
|
-
public_key.primitive = PRIMITIVE
|
44
43
|
secret_key = Sodium::Buffer.new(:uchar, SECRETKEYBYTES)
|
45
|
-
secret_key.primitive = PRIMITIVE
|
46
44
|
crypto_box_keypair(public_key, secret_key)
|
47
45
|
|
48
46
|
[public_key, secret_key]
|
@@ -52,9 +50,7 @@ module Crypto
|
|
52
50
|
check_length(seed, SEEDBYTES, :Seed)
|
53
51
|
|
54
52
|
public_key = Sodium::Buffer.new(:uchar, PUBLICKEYBYTES)
|
55
|
-
public_key.primitive = PRIMITIVE
|
56
53
|
secret_key = Sodium::Buffer.new(:uchar, SECRETKEYBYTES)
|
57
|
-
secret_key.primitive = PRIMITIVE
|
58
54
|
seed.readonly if seed.is_a?(Sodium::SecretBuffer)
|
59
55
|
crypto_box_seed_keypair(public_key, secret_key, seed)
|
60
56
|
|
@@ -65,8 +61,7 @@ module Crypto
|
|
65
61
|
|
66
62
|
def memory_locked_keypair
|
67
63
|
public_key = Sodium::Buffer.new(:uchar, PUBLICKEYBYTES)
|
68
|
-
|
69
|
-
secret_key = Sodium::SecretBuffer.new(SECRETKEYBYTES, PRIMITIVE)
|
64
|
+
secret_key = Sodium::SecretBuffer.new(SECRETKEYBYTES)
|
70
65
|
crypto_box_keypair(public_key, secret_key)
|
71
66
|
secret_key.noaccess
|
72
67
|
|
@@ -77,8 +72,7 @@ module Crypto
|
|
77
72
|
check_length(seed, SEEDBYTES, :Seed)
|
78
73
|
|
79
74
|
public_key = Sodium::Buffer.new(:uchar, PUBLICKEYBYTES)
|
80
|
-
|
81
|
-
secret_key = Sodium::SecretBuffer.new(SECRETKEYBYTES, PRIMITIVE)
|
75
|
+
secret_key = Sodium::SecretBuffer.new(SECRETKEYBYTES)
|
82
76
|
seed.readonly if seed.is_a?(Sodium::SecretBuffer)
|
83
77
|
crypto_box_seed_keypair(public_key, secret_key, seed)
|
84
78
|
secret_key.noaccess
|
@@ -95,7 +89,6 @@ module Crypto
|
|
95
89
|
check_length(secret_key, SECRETKEYBYTES, :SecretKey)
|
96
90
|
|
97
91
|
ciphertext = Sodium::Buffer.new(:uchar, message_len + MACBYTES)
|
98
|
-
ciphertext.primitive = PRIMITIVE
|
99
92
|
secret_key.readonly if secret_key.is_a?(Sodium::SecretBuffer)
|
100
93
|
crypto_box_easy(ciphertext, message, message_len, nonce, public_key, secret_key)
|
101
94
|
|
@@ -112,22 +105,22 @@ module Crypto
|
|
112
105
|
|
113
106
|
decrypted = Sodium::Buffer.new(:uchar, ciphertext_len - MACBYTES)
|
114
107
|
secret_key.readonly if secret_key.is_a?(Sodium::SecretBuffer)
|
115
|
-
|
108
|
+
if crypto_box_open_easy(decrypted, ciphertext, ciphertext_len, nonce, public_key, secret_key) == 0
|
109
|
+
decrypted
|
110
|
+
else
|
116
111
|
raise Sodium::CryptoError, "Message forged", caller
|
117
112
|
end
|
118
|
-
|
119
|
-
decrypted
|
120
113
|
ensure
|
121
114
|
secret_key.noaccess if secret_key.is_a?(Sodium::SecretBuffer)
|
122
115
|
end
|
123
116
|
|
124
117
|
def easy_in_place(data, nonce, public_key, secret_key)
|
125
|
-
message =
|
118
|
+
message = String(data)
|
126
119
|
check_length(nonce, NONCEBYTES, :Nonce)
|
127
120
|
check_length(public_key, PUBLICKEYBYTES, :PublicKey)
|
128
121
|
check_length(secret_key, SECRETKEYBYTES, :SecretKey)
|
129
122
|
|
130
|
-
message_len =
|
123
|
+
message_len = message.bytesize
|
131
124
|
message << zeros(MACBYTES)
|
132
125
|
secret_key.readonly if secret_key.is_a?(Sodium::SecretBuffer)
|
133
126
|
crypto_box_easy(message, message, message_len, nonce, public_key, secret_key)
|
@@ -137,33 +130,36 @@ module Crypto
|
|
137
130
|
secret_key.noaccess if secret_key.is_a?(Sodium::SecretBuffer)
|
138
131
|
end
|
139
132
|
|
140
|
-
def open_easy_in_place(data, nonce, public_key, secret_key,
|
141
|
-
ciphertext =
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
133
|
+
def open_easy_in_place(data, nonce, public_key, secret_key, encoding = false)
|
134
|
+
ciphertext = String(data)
|
135
|
+
ciphertext_len = ciphertext.bytesize
|
136
|
+
if (message_len = ciphertext_len - MACBYTES) > 0
|
137
|
+
check_length(nonce, NONCEBYTES, :Nonce)
|
138
|
+
check_length(public_key, PUBLICKEYBYTES, :PublicKey)
|
139
|
+
check_length(secret_key, SECRETKEYBYTES, :SecretKey)
|
140
|
+
|
141
|
+
secret_key.readonly if secret_key.is_a?(Sodium::SecretBuffer)
|
142
|
+
if crypto_box_open_easy(ciphertext, ciphertext, ciphertext_len, nonce, public_key, secret_key) == 0
|
143
|
+
if encoding
|
144
|
+
ciphertext.slice!(message_len..-1).force_encoding(encoding)
|
145
|
+
else
|
146
|
+
ciphertext.slice!(message_len..-1)
|
147
|
+
end
|
148
|
+
|
149
|
+
ciphertext
|
150
|
+
else
|
151
|
+
raise Sodium::CryptoError, "Message forged", caller
|
152
|
+
end
|
157
153
|
else
|
158
|
-
|
154
|
+
fail Sodium::LengthError, "Ciphertext is too short", caller
|
159
155
|
end
|
160
|
-
|
161
|
-
ciphertext
|
162
156
|
ensure
|
163
157
|
secret_key.noaccess if secret_key.is_a?(Sodium::SecretBuffer)
|
164
158
|
end
|
165
159
|
end
|
166
160
|
|
161
|
+
Box.freeze
|
162
|
+
|
167
163
|
module_function
|
168
164
|
|
169
165
|
def box(*args)
|
data/lib/crypto/generic_hash.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
require 'ffi'
|
2
2
|
require_relative '../sodium/utils'
|
3
|
-
require_relative '../sodium/errors'
|
4
3
|
require_relative '../sodium/buffer'
|
5
4
|
require_relative '../sodium/secret_buffer'
|
5
|
+
require_relative '../sodium/errors'
|
6
6
|
|
7
7
|
module Crypto
|
8
8
|
module GenericHash
|
@@ -46,28 +46,19 @@ module Crypto
|
|
46
46
|
module_function
|
47
47
|
|
48
48
|
def generichash(message, hash_size = BYTES, key = nil)
|
49
|
-
if hash_size > BYTES_MAX ||hash_size < BYTES_MIN
|
50
|
-
fail Sodium::LengthError, "Hash size must be between #{BYTES_MIN} and #{BYTES_MAX} bytes, got size=#{hash_size} bytes", caller
|
51
|
-
end
|
52
|
-
|
53
49
|
if key
|
54
50
|
key_len = get_size(key)
|
55
|
-
|
56
|
-
if key_len > KEYBYTES_MAX ||key_len < KEYBYTES_MIN
|
57
|
-
fail Sodium::LengthError, "Key length must be between #{KEYBYTES_MIN} and #{KEYBYTES_MAX} bytes, got length=#{key_len} bytes", caller
|
58
|
-
end
|
59
51
|
else
|
60
52
|
key_len = 0
|
61
53
|
end
|
62
54
|
|
63
55
|
blake2b = Sodium::Buffer.new(:uchar, hash_size)
|
64
|
-
blake2b.primitive = PRIMITIVE
|
65
56
|
key.readonly if key.is_a?(Sodium::SecretBuffer)
|
66
|
-
|
57
|
+
if crypto_generichash(blake2b, hash_size, message, get_size(message), key, key_len) == 0
|
58
|
+
blake2b
|
59
|
+
else
|
67
60
|
raise Sodium::CryptoError
|
68
61
|
end
|
69
|
-
|
70
|
-
blake2b
|
71
62
|
ensure
|
72
63
|
key.noaccess if key.is_a?(Sodium::SecretBuffer)
|
73
64
|
end
|
@@ -75,47 +66,36 @@ module Crypto
|
|
75
66
|
def init(key = nil, hash_size = BYTES)
|
76
67
|
if key
|
77
68
|
key_len = get_size(key)
|
78
|
-
|
79
|
-
if key_len > KEYBYTES_MAX ||key_len < KEYBYTES_MIN
|
80
|
-
fail Sodium::LengthError, "Key length must be between #{KEYBYTES_MIN} and #{KEYBYTES_MAX} bytes, got length=#{key_len} bytes", caller
|
81
|
-
end
|
82
69
|
else
|
83
70
|
key_len = 0
|
84
71
|
end
|
85
72
|
|
86
|
-
if hash_size > BYTES_MAX ||hash_size < BYTES_MIN
|
87
|
-
fail Sodium::LengthError, "Hash size must be between #{BYTES_MIN} and #{BYTES_MAX} bytes, got size=#{hash_size} bytes", caller
|
88
|
-
end
|
89
|
-
|
90
73
|
state = State.new
|
91
|
-
blake2b = Sodium::Buffer.new(:uchar, hash_size)
|
92
|
-
blake2b.primitive = PRIMITIVE
|
93
74
|
key.readonly if key.is_a?(Sodium::SecretBuffer)
|
94
|
-
|
95
|
-
|
75
|
+
if crypto_generichash_init(state, key, key_len, hash_size) == 0
|
76
|
+
[state, Sodium::Buffer.new(:uchar, hash_size)]
|
77
|
+
else
|
96
78
|
raise Sodium::CryptoError
|
97
79
|
end
|
98
|
-
|
99
|
-
[state, blake2b]
|
100
80
|
ensure
|
101
81
|
key.noaccess if key.is_a?(Sodium::SecretBuffer)
|
102
82
|
end
|
103
83
|
|
104
84
|
def update(state, message)
|
105
|
-
|
106
|
-
raise Sodium::CryptoError
|
107
|
-
end
|
85
|
+
crypto_generichash_update(state, message, get_size(message))
|
108
86
|
end
|
109
87
|
|
110
88
|
def final(state, blake2b)
|
111
|
-
|
89
|
+
if crypto_generichash_final(state, blake2b, blake2b.size) == 0
|
90
|
+
blake2b
|
91
|
+
else
|
112
92
|
raise Sodium::CryptoError
|
113
93
|
end
|
114
|
-
|
115
|
-
blake2b
|
116
94
|
end
|
117
95
|
end
|
118
96
|
|
97
|
+
GenericHash.freeze
|
98
|
+
|
119
99
|
module_function
|
120
100
|
|
121
101
|
def generichash(*args)
|
data/lib/crypto/one_time_auth.rb
CHANGED
@@ -36,7 +36,6 @@ module Crypto
|
|
36
36
|
check_length(key, KEYBYTES, :SecretKey)
|
37
37
|
|
38
38
|
out = Sodium::Buffer.new(:uchar, BYTES)
|
39
|
-
out.primitive = PRIMITIVE
|
40
39
|
key.readonly if key.is_a?(Sodium::SecretBuffer)
|
41
40
|
crypto_onetimeauth(out, message, get_size(message), key)
|
42
41
|
|
@@ -50,7 +49,7 @@ module Crypto
|
|
50
49
|
check_length(key, KEYBYTES, :SecretKey)
|
51
50
|
|
52
51
|
key.readonly if key.is_a?(Sodium::SecretBuffer)
|
53
|
-
crypto_onetimeauth_verify(out, message, get_size(message), key)
|
52
|
+
crypto_onetimeauth_verify(out, message, get_size(message), key) == 0
|
54
53
|
ensure
|
55
54
|
key.noaccess if key.is_a?(Sodium::SecretBuffer)
|
56
55
|
end
|
@@ -73,13 +72,13 @@ module Crypto
|
|
73
72
|
|
74
73
|
def final(state)
|
75
74
|
out = Sodium::Buffer.new(:uchar, BYTES)
|
76
|
-
out.primitive = PRIMITIVE
|
77
75
|
crypto_onetimeauth_final(state, out)
|
78
|
-
|
79
76
|
out
|
80
77
|
end
|
81
78
|
end
|
82
79
|
|
80
|
+
OneTimeAuth.freeze
|
81
|
+
|
83
82
|
module_function
|
84
83
|
|
85
84
|
def onetimeauth(*args)
|
@@ -49,51 +49,40 @@ module Crypto
|
|
49
49
|
end
|
50
50
|
|
51
51
|
def scryptsalsa208sha256(outlen, passwd, salt, opslimit = OPSLIMIT_INTERACTIVE, memlimit = MEMLIMIT_INTERACTIVE)
|
52
|
-
out = nil
|
53
52
|
check_length(salt, SALTBYTES, :Salt)
|
54
|
-
if opslimit < OPSLIMIT_INTERACTIVE
|
55
|
-
fail Sodium::LengthError, "Opslimit must be at least #{OPSLIMIT_INTERACTIVE}, got #{opslimit}", caller
|
56
|
-
end
|
57
|
-
if memlimit < MEMLIMIT_INTERACTIVE
|
58
|
-
fail Sodium::LengthError, "Memlimit must be at least #{MEMLIMIT_INTERACTIVE}, got #{memlimit}", caller
|
59
|
-
end
|
60
53
|
|
61
|
-
out = Sodium::SecretBuffer.new(outlen
|
62
|
-
|
54
|
+
out = Sodium::SecretBuffer.new(outlen)
|
55
|
+
if crypto_pwhash_scryptsalsa208sha256(out, outlen, passwd, get_size(passwd), salt, opslimit, memlimit) == 0
|
56
|
+
out.noaccess
|
57
|
+
out
|
58
|
+
else
|
63
59
|
raise NoMemoryError, "Failed to allocate memory max size=#{memlimit} bytes", caller
|
64
60
|
end
|
65
|
-
|
66
|
-
out
|
67
|
-
ensure
|
68
|
-
out.noaccess if out
|
69
61
|
end
|
70
62
|
|
71
63
|
def str(passwd, opslimit = OPSLIMIT_INTERACTIVE, memlimit = MEMLIMIT_INTERACTIVE)
|
72
|
-
if opslimit < OPSLIMIT_INTERACTIVE
|
73
|
-
fail Sodium::LengthError, "Opslimit must be at least #{OPSLIMIT_INTERACTIVE}, got #{opslimit}", caller
|
74
|
-
end
|
75
|
-
if memlimit < MEMLIMIT_INTERACTIVE
|
76
|
-
fail Sodium::LengthError, "Memlimit must be at least #{MEMLIMIT_INTERACTIVE}, got #{memlimit}", caller
|
77
|
-
end
|
78
|
-
|
79
64
|
hashed_password = FFI::MemoryPointer.new(:char, STRBYTES)
|
80
|
-
|
65
|
+
if crypto_pwhash_scryptsalsa208sha256_str(hashed_password, passwd, get_size(passwd), opslimit, memlimit) == 0
|
66
|
+
hashed_password.get_string(0)
|
67
|
+
else
|
81
68
|
raise NoMemoryError, "Failed to allocate memory max size=#{memlimit} bytes", caller
|
82
69
|
end
|
83
|
-
|
84
|
-
hashed_password.get_string(0)
|
85
70
|
end
|
86
71
|
|
87
72
|
def str_verify(str, passwd)
|
88
73
|
check_length(str, STRBYTES - 1, :Str)
|
89
|
-
crypto_pwhash_scryptsalsa208sha256_str_verify(str, passwd, get_size(passwd))
|
74
|
+
crypto_pwhash_scryptsalsa208sha256_str_verify(str, passwd, get_size(passwd)) == 0
|
90
75
|
end
|
91
76
|
end
|
92
77
|
|
78
|
+
ScryptSalsa208SHA256.freeze
|
79
|
+
|
93
80
|
module_function
|
94
81
|
|
95
82
|
def scryptsalsa208sha256(*args)
|
96
83
|
ScryptSalsa208SHA256.scryptsalsa208sha256(*args)
|
97
84
|
end
|
98
85
|
end
|
86
|
+
|
87
|
+
PwHash.freeze
|
99
88
|
end
|
data/lib/crypto/scalar_mult.rb
CHANGED
@@ -27,7 +27,6 @@ module Crypto
|
|
27
27
|
check_length(secret_key, SCALARBYTES, :SecretKey)
|
28
28
|
|
29
29
|
public_key = Sodium::Buffer.new(:uchar, BYTES)
|
30
|
-
public_key.primitive = PRIMITIVE
|
31
30
|
secret_key.readonly if secret_key.is_a?(Sodium::SecretBuffer)
|
32
31
|
crypto_scalarmult_base(public_key, secret_key)
|
33
32
|
|
@@ -40,7 +39,7 @@ module Crypto
|
|
40
39
|
check_length(secret_key, SCALARBYTES, :SecretKey)
|
41
40
|
check_length(public_key, BYTES, :PublicKey)
|
42
41
|
|
43
|
-
shared_secret = Sodium::SecretBuffer.new(BYTES
|
42
|
+
shared_secret = Sodium::SecretBuffer.new(BYTES)
|
44
43
|
secret_key.readonly if secret_key.is_a?(Sodium::SecretBuffer)
|
45
44
|
crypto_scalarmult(shared_secret, secret_key, public_key)
|
46
45
|
shared_secret.noaccess
|
@@ -51,6 +50,8 @@ module Crypto
|
|
51
50
|
end
|
52
51
|
end
|
53
52
|
|
53
|
+
ScalarMult.freeze
|
54
|
+
|
54
55
|
module_function
|
55
56
|
|
56
57
|
def scalarmut(*args)
|
data/lib/crypto/secret_box.rb
CHANGED
@@ -37,7 +37,6 @@ module Crypto
|
|
37
37
|
check_length(key, KEYBYTES, :SecretKey)
|
38
38
|
|
39
39
|
ciphertext = Sodium::Buffer.new(:uchar, message_len + MACBYTES)
|
40
|
-
ciphertext.primitive = PRIMITIVE
|
41
40
|
key.readonly if key.is_a?(Sodium::SecretBuffer)
|
42
41
|
crypto_secretbox_easy(ciphertext, message, message_len, nonce, key)
|
43
42
|
|
@@ -53,22 +52,21 @@ module Crypto
|
|
53
52
|
|
54
53
|
decrypted = Sodium::Buffer.new(:uchar, ciphertext_len - MACBYTES)
|
55
54
|
key.readonly if key.is_a?(Sodium::SecretBuffer)
|
56
|
-
|
57
|
-
|
55
|
+
if crypto_secretbox_open_easy(decrypted, ciphertext, ciphertext_len, nonce, key) == 0
|
56
|
+
decrypted
|
57
|
+
else
|
58
58
|
raise Sodium::CryptoError, "Message forged", caller
|
59
59
|
end
|
60
|
-
|
61
|
-
decrypted
|
62
60
|
ensure
|
63
61
|
key.noaccess if key.is_a?(Sodium::SecretBuffer)
|
64
62
|
end
|
65
63
|
|
66
64
|
def easy_in_place(data, nonce, key)
|
67
|
-
message =
|
65
|
+
message = String(data)
|
68
66
|
check_length(nonce, NONCEBYTES, :Nonce)
|
69
67
|
check_length(key, KEYBYTES, :SecretKey)
|
70
68
|
|
71
|
-
message_len =
|
69
|
+
message_len = message.bytesize
|
72
70
|
message << zeros(MACBYTES)
|
73
71
|
key.readonly if key.is_a?(Sodium::SecretBuffer)
|
74
72
|
crypto_secretbox_easy(message, message, message_len, nonce, key)
|
@@ -78,32 +76,35 @@ module Crypto
|
|
78
76
|
key.noaccess if key.is_a?(Sodium::SecretBuffer)
|
79
77
|
end
|
80
78
|
|
81
|
-
def open_easy_in_place(data, nonce, key,
|
82
|
-
ciphertext =
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
79
|
+
def open_easy_in_place(data, nonce, key, encoding = false)
|
80
|
+
ciphertext = String(data)
|
81
|
+
ciphertext_len = ciphertext.bytesize
|
82
|
+
if (message_len = ciphertext_len - MACBYTES) > 0
|
83
|
+
check_length(nonce, NONCEBYTES, :Nonce)
|
84
|
+
check_length(key, KEYBYTES, :SecretKey)
|
85
|
+
|
86
|
+
key.readonly if key.is_a?(Sodium::SecretBuffer)
|
87
|
+
if crypto_secretbox_open_easy(ciphertext, ciphertext, ciphertext_len, nonce, key) == 0
|
88
|
+
if encoding
|
89
|
+
ciphertext.slice!(message_len..-1).force_encoding(encoding)
|
90
|
+
else
|
91
|
+
ciphertext.slice!(message_len..-1)
|
92
|
+
end
|
93
|
+
|
94
|
+
ciphertext
|
95
|
+
else
|
96
|
+
raise Sodium::CryptoError, "Message forged", caller
|
97
|
+
end
|
97
98
|
else
|
98
|
-
|
99
|
+
fail Sodium::LengthError, "Ciphertext is too short", caller
|
99
100
|
end
|
100
|
-
|
101
|
-
ciphertext
|
102
101
|
ensure
|
103
102
|
key.noaccess if key.is_a?(Sodium::SecretBuffer)
|
104
103
|
end
|
105
104
|
end
|
106
105
|
|
106
|
+
SecretBox.freeze
|
107
|
+
|
107
108
|
module_function
|
108
109
|
|
109
110
|
def secretbox(*args)
|
data/lib/crypto/short_hash.rb
CHANGED
@@ -26,7 +26,6 @@ module Crypto
|
|
26
26
|
check_length(key, KEYBYTES, :SecretKey)
|
27
27
|
|
28
28
|
siphash = Sodium::Buffer.new(:uchar, BYTES)
|
29
|
-
siphash.primitive = PRIMITIVE
|
30
29
|
key.readonly if key.is_a?(Sodium::SecretBuffer)
|
31
30
|
crypto_shorthash(siphash, short_data, get_size(short_data), key)
|
32
31
|
|
@@ -36,6 +35,8 @@ module Crypto
|
|
36
35
|
end
|
37
36
|
end
|
38
37
|
|
38
|
+
ShortHash.freeze
|
39
|
+
|
39
40
|
module_function
|
40
41
|
|
41
42
|
def shorthash(*args)
|
data/lib/crypto/sign.rb
CHANGED
@@ -33,9 +33,7 @@ module Crypto
|
|
33
33
|
|
34
34
|
def keypair
|
35
35
|
public_key = Sodium::Buffer.new(:uchar, PUBLICKEYBYTES)
|
36
|
-
public_key.primitive = PRIMITIVE
|
37
36
|
secret_key = Sodium::Buffer.new(:uchar, SECRETKEYBYTES)
|
38
|
-
secret_key.primitive = PRIMITIVE
|
39
37
|
crypto_sign_keypair(public_key, secret_key)
|
40
38
|
|
41
39
|
[public_key, secret_key]
|
@@ -45,9 +43,7 @@ module Crypto
|
|
45
43
|
check_length(seed, SEEDBYTES, :Seed)
|
46
44
|
|
47
45
|
public_key = Sodium::Buffer.new(:uchar, PUBLICKEYBYTES)
|
48
|
-
public_key.primitive = PRIMITIVE
|
49
46
|
secret_key = Sodium::Buffer.new(:uchar, SECRETKEYBYTES)
|
50
|
-
secret_key.primitive = PRIMITIVE
|
51
47
|
seed.readonly if seed.is_a?(Sodium::SecretBuffer)
|
52
48
|
crypto_sign_seed_keypair(public_key, secret_key, seed)
|
53
49
|
|
@@ -58,8 +54,7 @@ module Crypto
|
|
58
54
|
|
59
55
|
def memory_locked_keypair
|
60
56
|
public_key = Sodium::Buffer.new(:uchar, PUBLICKEYBYTES)
|
61
|
-
|
62
|
-
secret_key = Sodium::SecretBuffer.new(SECRETKEYBYTES, PRIMITIVE)
|
57
|
+
secret_key = Sodium::SecretBuffer.new(SECRETKEYBYTES)
|
63
58
|
crypto_sign_keypair(public_key, secret_key)
|
64
59
|
secret_key.noaccess
|
65
60
|
|
@@ -70,8 +65,7 @@ module Crypto
|
|
70
65
|
check_length(seed, SEEDBYTES, :Seed)
|
71
66
|
|
72
67
|
public_key = Sodium::Buffer.new(:uchar, PUBLICKEYBYTES)
|
73
|
-
|
74
|
-
secret_key = Sodium::SecretBuffer.new(SECRETKEYBYTES, PRIMITIVE)
|
68
|
+
secret_key = Sodium::SecretBuffer.new(SECRETKEYBYTES)
|
75
69
|
seed.readonly if seed.is_a?(Sodium::SecretBuffer)
|
76
70
|
crypto_sign_seed_keypair(public_key, secret_key, seed)
|
77
71
|
secret_key.noaccess
|
@@ -86,7 +80,6 @@ module Crypto
|
|
86
80
|
check_length(secret_key, SECRETKEYBYTES, :SecretKey)
|
87
81
|
|
88
82
|
sealed_message = Sodium::Buffer.new(:uchar, message_len + BYTES)
|
89
|
-
sealed_message.primitive = PRIMITIVE
|
90
83
|
secret_key.readonly if secret_key.is_a?(Sodium::SecretBuffer)
|
91
84
|
crypto_sign(sealed_message, nil, message, message_len, secret_key)
|
92
85
|
|
@@ -100,15 +93,17 @@ module Crypto
|
|
100
93
|
check_length(public_key, PUBLICKEYBYTES, :PublicKey)
|
101
94
|
|
102
95
|
unsealed_message = Sodium::Buffer.new(:uchar, sealed_message_len - BYTES)
|
103
|
-
unsealed_message_len = FFI::MemoryPointer.new(:
|
104
|
-
|
96
|
+
unsealed_message_len = FFI::MemoryPointer.new(:ulong_long)
|
97
|
+
if crypto_sign_open(unsealed_message, unsealed_message_len, sealed_message, sealed_message_len, public_key) == 0
|
98
|
+
unsealed_message
|
99
|
+
else
|
105
100
|
raise Sodium::CryptoError, "Incorrect signature", caller
|
106
101
|
end
|
107
|
-
|
108
|
-
unsealed_message
|
109
102
|
end
|
110
103
|
end
|
111
104
|
|
105
|
+
Sign.freeze
|
106
|
+
|
112
107
|
module_function
|
113
108
|
|
114
109
|
def sign(*args)
|
data/lib/crypto/sign/ed25519.rb
CHANGED
data/lib/libsodium.rb
CHANGED
@@ -2,19 +2,22 @@
|
|
2
2
|
require_relative 'sodium'
|
3
3
|
require_relative 'sodium/utils'
|
4
4
|
require_relative 'sodium/buffer'
|
5
|
+
require_relative 'sodium/mprotect'
|
5
6
|
require_relative 'sodium/secret_buffer'
|
7
|
+
Sodium.freeze
|
6
8
|
require_relative 'random_bytes'
|
7
9
|
require_relative 'crypto/secret_box'
|
8
10
|
require_relative 'crypto/auth'
|
9
11
|
require_relative 'crypto/aead/chacha20_poly1305'
|
10
12
|
require_relative 'crypto/box'
|
13
|
+
require_relative 'crypto/sign/ed25519'
|
11
14
|
require_relative 'crypto/sign'
|
12
15
|
require_relative 'crypto/generic_hash'
|
13
16
|
require_relative 'crypto/short_hash'
|
14
17
|
require_relative 'crypto/pw_hash/scrypt_salsa208_sha256'
|
15
18
|
require_relative 'crypto/one_time_auth'
|
16
19
|
require_relative 'crypto/scalar_mult'
|
17
|
-
|
20
|
+
Crypto.freeze
|
18
21
|
|
19
22
|
Thread.exclusive do
|
20
23
|
if Sodium.init == -1
|
data/lib/random_bytes.rb
CHANGED
data/lib/sodium.rb
CHANGED
@@ -16,53 +16,22 @@ module Sodium
|
|
16
16
|
attach_function :sodium_munlock, [:pointer, :size_t], :int
|
17
17
|
attach_function :sodium_malloc, [:size_t], :pointer
|
18
18
|
attach_function :sodium_allocarray, [:size_t, :size_t], :pointer
|
19
|
-
attach_function :sodium_mprotect_noaccess, [:pointer], :int
|
20
|
-
attach_function :sodium_mprotect_readonly, [:pointer], :int
|
21
|
-
attach_function :sodium_mprotect_readwrite, [:pointer], :int
|
22
19
|
|
23
20
|
module_function
|
24
21
|
|
25
22
|
def mlock(addr, len)
|
26
|
-
|
27
|
-
raise MemoryError, "Could not lock length=#{len} bytes memory at address=#{addr.address}", caller
|
28
|
-
end
|
23
|
+
sodium_mlock(addr, len) == 0 || raise(MemoryError, "Could not lock length=#{len} bytes memory at address=#{addr.address}", caller)
|
29
24
|
end
|
30
25
|
|
31
26
|
def munlock(addr, len)
|
32
|
-
|
33
|
-
raise MemoryError, "Could not unlock length=#{len} bytes memory at address=#{addr.address}", caller
|
34
|
-
end
|
27
|
+
sodium_munlock(addr, len) == 0 || raise(MemoryError, "Could not unlock length=#{len} bytes memory at address=#{addr.address}", caller)
|
35
28
|
end
|
36
29
|
|
37
30
|
def malloc(size)
|
38
|
-
|
39
|
-
raise NoMemoryError, "Failed to allocate memory size=#{size} bytes", caller
|
40
|
-
end
|
41
|
-
mem
|
31
|
+
sodium_malloc(size) || raise(NoMemoryError, "Failed to allocate memory size=#{size} bytes", caller)
|
42
32
|
end
|
43
33
|
|
44
34
|
def allocarray(count, size)
|
45
|
-
|
46
|
-
raise NoMemoryError, "Failed to allocate memory size=#{count * size} bytes", caller
|
47
|
-
end
|
48
|
-
mem
|
49
|
-
end
|
50
|
-
|
51
|
-
def noaccess(ptr)
|
52
|
-
unless sodium_mprotect_noaccess(ptr).zero?
|
53
|
-
raise MemoryError, "Memory at address=#{ptr.address} is not secured with #{self}.malloc", caller
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
def readonly(ptr)
|
58
|
-
unless sodium_mprotect_readonly(ptr).zero?
|
59
|
-
raise MemoryError, "Memory at address=#{ptr.address} is not secured with #{self}.malloc", caller
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
def readwrite(ptr)
|
64
|
-
unless sodium_mprotect_readwrite(ptr).zero?
|
65
|
-
raise MemoryError, "Memory at address=#{ptr.address} is not secured with #{self}.malloc", caller
|
66
|
-
end
|
35
|
+
sodium_allocarray(count, size) || raise(NoMemoryError, "Failed to allocate memory size=#{count * size} bytes", caller)
|
67
36
|
end
|
68
37
|
end
|
data/lib/sodium/buffer.rb
CHANGED
data/lib/sodium/errors.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
module Sodium
|
2
|
-
|
3
|
-
|
4
|
-
|
2
|
+
CryptoError = Class.new(StandardError).freeze
|
3
|
+
LengthError = Class.new(ArgumentError).freeze
|
4
|
+
MemoryError = Class.new(StandardError).freeze
|
5
5
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'ffi'
|
2
|
+
require_relative 'errors'
|
3
|
+
require_relative 'utils'
|
4
|
+
|
5
|
+
module Sodium
|
6
|
+
module Mprotect
|
7
|
+
extend FFI::Library
|
8
|
+
ffi_lib :libsodium
|
9
|
+
|
10
|
+
attach_function :sodium_mprotect_noaccess, [:pointer], :int
|
11
|
+
attach_function :sodium_mprotect_readonly, [:pointer], :int
|
12
|
+
attach_function :sodium_mprotect_readwrite, [:pointer], :int
|
13
|
+
|
14
|
+
module_function
|
15
|
+
|
16
|
+
def noaccess(ptr)
|
17
|
+
sodium_mprotect_noaccess(ptr) == 0 || raise(MemoryError, "Memory at address=#{ptr.address} is not secured with Sodium.malloc", caller)
|
18
|
+
end
|
19
|
+
|
20
|
+
def readonly(ptr)
|
21
|
+
sodium_mprotect_readonly(ptr) == 0 || raise(MemoryError, "Memory at address=#{ptr.address} is not secured with Sodium.malloc", caller)
|
22
|
+
end
|
23
|
+
|
24
|
+
def readwrite(ptr)
|
25
|
+
sodium_mprotect_readwrite(ptr) == 0 || raise(MemoryError, "Memory at address=#{ptr.address} is not secured with Sodium.malloc", caller)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
Mprotect.freeze
|
30
|
+
end
|
data/lib/sodium/secret_buffer.rb
CHANGED
@@ -1,58 +1,61 @@
|
|
1
1
|
require 'forwardable'
|
2
|
-
require_relative 'utils'
|
3
2
|
require_relative '../sodium'
|
3
|
+
require_relative 'mprotect'
|
4
4
|
require 'ffi'
|
5
5
|
|
6
6
|
module Sodium
|
7
7
|
class SecretBuffer
|
8
8
|
extend Forwardable
|
9
9
|
|
10
|
-
attr_reader :size, :
|
11
|
-
def_delegators
|
10
|
+
attr_reader :size, :to_ptr
|
11
|
+
def_delegators :@to_ptr, :address, :to_i
|
12
12
|
|
13
|
-
def initialize(size
|
14
|
-
@size =
|
15
|
-
@
|
16
|
-
@to_ptr = Sodium.malloc(self.size)
|
13
|
+
def initialize(size)
|
14
|
+
@size = Integer(size)
|
15
|
+
@to_ptr = Sodium.malloc(@size)
|
17
16
|
setup_finalizer
|
18
17
|
end
|
19
18
|
|
20
19
|
def free
|
21
20
|
remove_finalizer
|
22
|
-
|
23
|
-
Sodium.free(to_ptr)
|
24
|
-
|
21
|
+
Sodium::Mprotect.readonly(@to_ptr)
|
22
|
+
Sodium.free(@to_ptr)
|
23
|
+
remove_instance_variable(:@size)
|
24
|
+
remove_instance_variable(:@to_ptr)
|
25
|
+
true
|
25
26
|
end
|
26
27
|
|
27
28
|
def noaccess
|
28
|
-
Sodium.noaccess(to_ptr)
|
29
|
+
Sodium::Mprotect.noaccess(@to_ptr)
|
29
30
|
end
|
30
31
|
|
31
32
|
def readonly
|
32
|
-
Sodium.readonly(to_ptr)
|
33
|
+
Sodium::Mprotect.readonly(@to_ptr)
|
33
34
|
end
|
34
35
|
|
35
36
|
def readwrite
|
36
|
-
Sodium.readwrite(to_ptr)
|
37
|
+
Sodium::Mprotect.readwrite(@to_ptr)
|
37
38
|
end
|
38
39
|
|
39
40
|
private
|
40
41
|
|
41
42
|
def setup_finalizer
|
42
|
-
ObjectSpace.define_finalizer(to_ptr, self.class.free(to_ptr.address))
|
43
|
+
ObjectSpace.define_finalizer(@to_ptr, self.class.free(@to_ptr.address))
|
43
44
|
end
|
44
45
|
|
45
46
|
def remove_finalizer
|
46
|
-
ObjectSpace.undefine_finalizer to_ptr
|
47
|
+
ObjectSpace.undefine_finalizer @to_ptr
|
47
48
|
end
|
48
49
|
|
49
50
|
def self.free(address)
|
50
51
|
->(obj_id) do
|
51
52
|
ptr = FFI::Pointer.new(address)
|
52
|
-
Sodium.
|
53
|
+
Sodium::Mprotect.readonly(ptr)
|
53
54
|
Sodium.free(ptr)
|
54
55
|
true
|
55
56
|
end
|
56
57
|
end
|
57
58
|
end
|
59
|
+
|
60
|
+
SecretBuffer.freeze
|
58
61
|
end
|
data/lib/sodium/utils.rb
CHANGED
@@ -1,68 +1,41 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
require 'ffi'
|
2
|
+
require_relative 'secret_buffer'
|
3
|
+
require_relative 'errors'
|
3
4
|
|
4
5
|
module Sodium
|
5
6
|
module Utils
|
6
7
|
|
7
8
|
module_function
|
8
9
|
|
9
|
-
def
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
end
|
18
|
-
else
|
19
|
-
fail ArgumentError, "#{description} must be of type String or FFI::Pointer and be length=#{length} bytes long", caller
|
20
|
-
end
|
21
|
-
|
22
|
-
true
|
23
|
-
end
|
24
|
-
|
25
|
-
def get_pointer(ptr)
|
26
|
-
if ptr.is_a?(FFI::Pointer)
|
27
|
-
ptr
|
28
|
-
elsif ptr.respond_to?(:to_ptr)
|
29
|
-
ptr.to_ptr
|
30
|
-
else
|
31
|
-
fail ArgumentError, "#{ptr.class} is not a FFI::Pointer", caller
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
def get_string(string)
|
36
|
-
if string.is_a?(String)
|
37
|
-
string
|
38
|
-
elsif string.respond_to?(:to_str)
|
39
|
-
string.to_str
|
40
|
-
elsif string.respond_to?(:get_string)
|
41
|
-
string.get_string(0)
|
42
|
-
else
|
43
|
-
fail ArgumentError, "#{string.class} is not a String", caller
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
def get_int(int)
|
48
|
-
if int.is_a?(Fixnum)
|
49
|
-
int
|
50
|
-
elsif int.respond_to?(:to_int)
|
51
|
-
int.to_int
|
10
|
+
def get_size(data)
|
11
|
+
case data
|
12
|
+
when FFI::Pointer, SecretBuffer
|
13
|
+
data.size
|
14
|
+
when String
|
15
|
+
data.bytesize
|
16
|
+
when NilClass
|
17
|
+
0
|
52
18
|
else
|
53
|
-
fail
|
19
|
+
fail TypeError, "#{data.class} must be of type FFI::Pointer, Sodium::SecretBufffer, String or NilClass", caller
|
54
20
|
end
|
55
21
|
end
|
56
22
|
|
57
|
-
def
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
23
|
+
def check_length(data, length, description)
|
24
|
+
case data
|
25
|
+
when FFI::Pointer, SecretBuffer
|
26
|
+
if data.size == length
|
27
|
+
true
|
28
|
+
else
|
29
|
+
fail LengthError, "Expected a length=#{length} bytes #{description}, got size=#{data.size} bytes", caller
|
30
|
+
end
|
31
|
+
when String
|
32
|
+
if data.bytesize == length
|
33
|
+
true
|
34
|
+
else
|
35
|
+
fail LengthError, "Expected a length=#{length} bytes #{description}, got size=#{data.bytesize} bytes", caller
|
36
|
+
end
|
64
37
|
else
|
65
|
-
fail
|
38
|
+
fail TypeError, "#{data.class} must be of type FFI::Pointer, Sodium::SecretBufffer or String", caller
|
66
39
|
end
|
67
40
|
end
|
68
41
|
|
@@ -82,4 +55,6 @@ module Sodium
|
|
82
55
|
[hex].pack(HEXY)
|
83
56
|
end
|
84
57
|
end
|
58
|
+
|
59
|
+
Utils.freeze
|
85
60
|
end
|
data/lib/sodium/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ffi-libsodium
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Hendrik Beskow
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-12-
|
11
|
+
date: 2014-12-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ffi
|
@@ -62,6 +62,7 @@ files:
|
|
62
62
|
- lib/sodium.rb
|
63
63
|
- lib/sodium/buffer.rb
|
64
64
|
- lib/sodium/errors.rb
|
65
|
+
- lib/sodium/mprotect.rb
|
65
66
|
- lib/sodium/secret_buffer.rb
|
66
67
|
- lib/sodium/utils.rb
|
67
68
|
- lib/sodium/version.rb
|