hide-protocol 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/hide_protocol/binding.rb +17 -1
- data/lib/hide_protocol.rb +120 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 488170733ac5d9ecacaaa15a84b6c069836d921851fb7efbcf9e13bb7e0483ee
|
|
4
|
+
data.tar.gz: c4c4398f9cb79ddd41c9abbc211de485ac9a1135c782c116818de60579dbb707
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ff80e1e2bdfddf7eac4de7c34746bf73b40f39d37fbd06c0ab85d41325df870622df44b631f9c563eb9f6a926defc441fb56ae8af929af12fe11edfe2d97b957
|
|
7
|
+
data.tar.gz: 0fb2bd25697dcfe863aec6b608e49c12349ea83f803c39359b8d4b72b29a1b244386909247f2df7c64f27b490e4c7b421eb8bd0a7e24b7e9e419036b8da328ac
|
|
@@ -107,7 +107,18 @@ module Hide
|
|
|
107
107
|
hide_challenge_answer: [[VOIDP, VOIDP, SIZE_T, VOIDP], INT32],
|
|
108
108
|
hide_spent_nonces_new: [[], VOIDP],
|
|
109
109
|
hide_spent_nonces_free: [[VOIDP], VOID],
|
|
110
|
-
hide_challenge_accept: [[VOIDP, VOIDP, SIZE_T, VOIDP, SIZE_T, VOIDP, SIZE_T, UINT64], INT32]
|
|
110
|
+
hide_challenge_accept: [[VOIDP, VOIDP, SIZE_T, VOIDP, SIZE_T, VOIDP, SIZE_T, UINT64], INT32],
|
|
111
|
+
hide_identity_verify: [[VOIDP, SIZE_T, VOIDP, SIZE_T, VOIDP], INT32],
|
|
112
|
+
hide_identity_trusts_device: [[VOIDP, SIZE_T, VOIDP, SIZE_T, VOIDP, SIZE_T, VOIDP], INT32],
|
|
113
|
+
hide_identity_head: [[VOIDP, SIZE_T, VOIDP, SIZE_T, VOIDP], INT32],
|
|
114
|
+
hide_epoch_verify: [[VOIDP, SIZE_T, VOIDP], INT32],
|
|
115
|
+
hide_epoch_public_key: [[VOIDP, SIZE_T, UINT64, VOIDP], INT32],
|
|
116
|
+
hide_transparency_verify_inclusion: [
|
|
117
|
+
[VOIDP, SIZE_T, UINT64, UINT64, VOIDP, SIZE_T, VOIDP, SIZE_T], INT32
|
|
118
|
+
],
|
|
119
|
+
hide_transparency_verify_consistency: [
|
|
120
|
+
[UINT64, UINT64, VOIDP, SIZE_T, VOIDP, SIZE_T, VOIDP, SIZE_T], INT32
|
|
121
|
+
]
|
|
111
122
|
}.freeze
|
|
112
123
|
|
|
113
124
|
FUNCTIONS = SIGNATURES.each_with_object({}) do |(name, (args, ret)), acc|
|
|
@@ -163,6 +174,11 @@ module Hide
|
|
|
163
174
|
raw.dup.force_encoding(Encoding::UTF_8).scrub
|
|
164
175
|
end
|
|
165
176
|
|
|
177
|
+
# Reads a size_t out-parameter written into a pointer-sized slot.
|
|
178
|
+
def self.read_count(slot)
|
|
179
|
+
read_word(slot, 0)
|
|
180
|
+
end
|
|
181
|
+
|
|
166
182
|
# A slot holding one pointer-sized out-parameter.
|
|
167
183
|
def self.pointer_slot
|
|
168
184
|
slot = Fiddle::Pointer.malloc(WORD, Fiddle::RUBY_FREE)
|
data/lib/hide_protocol.rb
CHANGED
|
@@ -29,6 +29,13 @@ module Hide
|
|
|
29
29
|
# The data was altered, or is not a HIDE container.
|
|
30
30
|
class AuthenticationError < Error; end
|
|
31
31
|
|
|
32
|
+
# The bytes did not decode at all.
|
|
33
|
+
#
|
|
34
|
+
# A subclass of AuthenticationError so that code which only cares that
|
|
35
|
+
# something failed is unaffected, while a caller that must tell corruption
|
|
36
|
+
# from forgery can rescue this specifically.
|
|
37
|
+
class MalformedError < AuthenticationError; end
|
|
38
|
+
|
|
32
39
|
# The passphrase is wrong, or the key file was modified.
|
|
33
40
|
class WrongPassphraseError < Error; end
|
|
34
41
|
|
|
@@ -56,7 +63,7 @@ module Hide
|
|
|
56
63
|
Binding::ERR_NOT_A_KEY => NotAKeyError,
|
|
57
64
|
Binding::ERR_AUTHENTICATION => AuthenticationError,
|
|
58
65
|
Binding::ERR_NO_MATCHING_RECIPIENT => NoMatchingRecipientError,
|
|
59
|
-
Binding::ERR_MALFORMED =>
|
|
66
|
+
Binding::ERR_MALFORMED => MalformedError,
|
|
60
67
|
Binding::ERR_TOO_LARGE => TooLargeError,
|
|
61
68
|
Binding::ERR_CHALLENGE_EXPIRED => ChallengeExpiredError,
|
|
62
69
|
Binding::ERR_CHALLENGE_REPLAYED => ChallengeReplayedError
|
|
@@ -173,6 +180,118 @@ module Hide
|
|
|
173
180
|
Binding.take(out)
|
|
174
181
|
end
|
|
175
182
|
|
|
183
|
+
# Replays an identity log and returns how many devices it trusts now.
|
|
184
|
+
#
|
|
185
|
+
# Raises MalformedError for a log that does not decode and
|
|
186
|
+
# AuthenticationError for one that decodes but does not verify — the
|
|
187
|
+
# distinction that tells corruption from forgery. A count is returned
|
|
188
|
+
# rather than a boolean: a caller who forgot to test one would read every
|
|
189
|
+
# failure as a pass.
|
|
190
|
+
def verify_identity(log, recovery_key)
|
|
191
|
+
bytes = binary(log, "log")
|
|
192
|
+
recovery = binary(recovery_key, "recovery key")
|
|
193
|
+
slot = Binding.pointer_slot
|
|
194
|
+
check(Binding.call(
|
|
195
|
+
:hide_identity_verify,
|
|
196
|
+
buffer_arg(bytes), bytes.bytesize,
|
|
197
|
+
buffer_arg(recovery), recovery.bytesize,
|
|
198
|
+
slot
|
|
199
|
+
))
|
|
200
|
+
Binding.read_count(slot)
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
# Whether the log trusts this device right now.
|
|
204
|
+
#
|
|
205
|
+
# A boolean is right here — this is a membership query, not a
|
|
206
|
+
# cryptographic check. The log is still verified first, so false means
|
|
207
|
+
# "not a member", never "did not verify": that raises.
|
|
208
|
+
def identity_trusts_device(log, recovery_key, device_public_key)
|
|
209
|
+
bytes = binary(log, "log")
|
|
210
|
+
recovery = binary(recovery_key, "recovery key")
|
|
211
|
+
device = binary(device_public_key, "device public key")
|
|
212
|
+
slot = Binding.pointer_slot
|
|
213
|
+
check(Binding.call(
|
|
214
|
+
:hide_identity_trusts_device,
|
|
215
|
+
buffer_arg(bytes), bytes.bytesize,
|
|
216
|
+
buffer_arg(recovery), recovery.bytesize,
|
|
217
|
+
buffer_arg(device), device.bytesize,
|
|
218
|
+
slot
|
|
219
|
+
))
|
|
220
|
+
(Binding.read_count(slot) & 0xFFFFFFFF) != 0
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
# The head link: 32 bytes naming this exact history.
|
|
224
|
+
def identity_head(log, recovery_key)
|
|
225
|
+
bytes = binary(log, "log")
|
|
226
|
+
recovery = binary(recovery_key, "recovery key")
|
|
227
|
+
out = Binding.empty_buffer
|
|
228
|
+
check(Binding.call(
|
|
229
|
+
:hide_identity_head,
|
|
230
|
+
buffer_arg(bytes), bytes.bytesize,
|
|
231
|
+
buffer_arg(recovery), recovery.bytesize,
|
|
232
|
+
out
|
|
233
|
+
))
|
|
234
|
+
Binding.take(out)
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
# Verifies a published epoch history and returns how many epochs it holds.
|
|
238
|
+
def verify_epoch_chain(chain)
|
|
239
|
+
bytes = binary(chain, "chain")
|
|
240
|
+
slot = Binding.pointer_slot
|
|
241
|
+
check(Binding.call(:hide_epoch_verify, buffer_arg(bytes), bytes.bytesize, slot))
|
|
242
|
+
Binding.read_count(slot)
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
# The public key a sender should encrypt to for this epoch.
|
|
246
|
+
#
|
|
247
|
+
# The chain is verified first, so a key is never returned from a history
|
|
248
|
+
# that does not hold together. An epoch beyond the chain raises
|
|
249
|
+
# InvalidArgumentError.
|
|
250
|
+
def epoch_public_key(chain, epoch)
|
|
251
|
+
bytes = binary(chain, "chain")
|
|
252
|
+
out = Binding.empty_buffer
|
|
253
|
+
check(Binding.call(
|
|
254
|
+
:hide_epoch_public_key,
|
|
255
|
+
buffer_arg(bytes), bytes.bytesize, Integer(epoch), out
|
|
256
|
+
))
|
|
257
|
+
Binding.take(out)
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
# Checks that leaf is entry index of a log of size entries under root.
|
|
261
|
+
#
|
|
262
|
+
# path is the concatenated 32-byte hashes; any other length raises
|
|
263
|
+
# InvalidArgumentError. Nothing is returned, for the same reason verify
|
|
264
|
+
# returns nothing.
|
|
265
|
+
def verify_inclusion(leaf, index, size, path, root)
|
|
266
|
+
leaf_bytes = binary(leaf, "leaf")
|
|
267
|
+
path_bytes = binary(path, "path")
|
|
268
|
+
root_bytes = binary(root, "root")
|
|
269
|
+
check(Binding.call(
|
|
270
|
+
:hide_transparency_verify_inclusion,
|
|
271
|
+
buffer_arg(leaf_bytes), leaf_bytes.bytesize,
|
|
272
|
+
Integer(index), Integer(size),
|
|
273
|
+
buffer_arg(path_bytes), path_bytes.bytesize,
|
|
274
|
+
buffer_arg(root_bytes), root_bytes.bytesize
|
|
275
|
+
))
|
|
276
|
+
nil
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
# Checks that old_root really is the root the log had before it grew to
|
|
280
|
+
# new_root. This is the check that catches a rewritten history.
|
|
281
|
+
def verify_consistency(old_size, new_size, path, old_root, new_root)
|
|
282
|
+
path_bytes = binary(path, "path")
|
|
283
|
+
old_bytes = binary(old_root, "old root")
|
|
284
|
+
new_bytes = binary(new_root, "new root")
|
|
285
|
+
check(Binding.call(
|
|
286
|
+
:hide_transparency_verify_consistency,
|
|
287
|
+
Integer(old_size), Integer(new_size),
|
|
288
|
+
buffer_arg(path_bytes), path_bytes.bytesize,
|
|
289
|
+
buffer_arg(old_bytes), old_bytes.bytesize,
|
|
290
|
+
buffer_arg(new_bytes), new_bytes.bytesize
|
|
291
|
+
))
|
|
292
|
+
nil
|
|
293
|
+
end
|
|
294
|
+
|
|
176
295
|
def check(code)
|
|
177
296
|
return if code == Binding::OK
|
|
178
297
|
|