ffi-libsodium 0.1.10 → 0.2.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.
- 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
|