hide-protocol 0.9.0-x86_64-linux → 0.9.1-x86_64-linux
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 +8 -0
- data/lib/hide_protocol/binding.rb +21 -0
- data/lib/hide_protocol/libhide_ffi.so +0 -0
- data/lib/hide_protocol.rb +71 -0
- 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: cfb23dd3235edb7cc1f1de32d7095952956a59e2e6f448c1b70d26ffeb17190a
|
|
4
|
+
data.tar.gz: eef7d550450fc5e1b36dc9d6492887160b526970dd3b6338c88eca8d0feeb295
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c334b6c3b5c77e38a807d89df95bfda880b0c2cf5809adfdc345669b46156944ad4baeb9e9e02e51fe511c5476136b812d433785a7ee625bc771b9bae3973918
|
|
7
|
+
data.tar.gz: 3f309306ac02584dc35aeae585eb7b690cdc3a2b0d5a34ef5d6fa55a0ddbd966d77b8df7bd800629851fed9bee6203538c63394451e8f10b9cc6f3d4a67ce135
|
data/README.md
CHANGED
|
@@ -103,12 +103,20 @@ written before signatures existed carries no signing seed and raises
|
|
|
103
103
|
| `Hide.epoch_public_key(chain, epoch)` | the public key to encrypt to for `epoch` |
|
|
104
104
|
| `Hide.verify_inclusion(leaf, index, size, path, root)` | `nil` |
|
|
105
105
|
| `Hide.verify_consistency(old_size, new_size, path, old_root, new_root)` | `nil` |
|
|
106
|
+
| `Hide.verify_identity_pinned(log, recovery_binding, pinned_root)` | `Integer` — devices trusted, after checking the log against the 32-byte root you pinned |
|
|
107
|
+
| `Hide.verify_epoch_chain_bound(log, recovery_binding, pinned_root, chain, epoch_binding)` | `Integer` — epochs held, after proving the chain belongs to that identity |
|
|
108
|
+
| `Hide.verify_checkpoint(note, origin, log_public)` | `[size, root]` — tree size and 32-byte root of a signed checkpoint note |
|
|
106
109
|
|
|
107
110
|
A cryptographic verify **raises** on failure (`MalformedError` if the bytes did
|
|
108
111
|
not decode, `AuthenticationError` if they decoded but did not verify) and never
|
|
109
112
|
returns `false`. The one boolean is `identity_trusts_device`: the log is
|
|
110
113
|
verified first, so `false` means "not a member", never "did not verify".
|
|
111
114
|
|
|
115
|
+
`verify_identity_pinned` is the relying-party check (spec §16): a recovery key
|
|
116
|
+
taken from the same untrusted source as the log cannot catch a Recover appended
|
|
117
|
+
under a stranger's key, but a `recovery_binding` checked against a root you
|
|
118
|
+
trust out of band does.
|
|
119
|
+
|
|
112
120
|
## Native library
|
|
113
121
|
|
|
114
122
|
The core is located in this order:
|
|
@@ -122,6 +122,15 @@ module Hide
|
|
|
122
122
|
],
|
|
123
123
|
hide_transparency_verify_consistency: [
|
|
124
124
|
[UINT64, UINT64, VOIDP, SIZE_T, VOIDP, SIZE_T, VOIDP, SIZE_T], INT32
|
|
125
|
+
],
|
|
126
|
+
hide_identity_verify_pinned: [
|
|
127
|
+
[VOIDP, SIZE_T, VOIDP, SIZE_T, VOIDP, SIZE_T, VOIDP], INT32
|
|
128
|
+
],
|
|
129
|
+
hide_epoch_verify_bound: [
|
|
130
|
+
[VOIDP, SIZE_T, VOIDP, SIZE_T, VOIDP, SIZE_T, VOIDP, SIZE_T, VOIDP, SIZE_T, VOIDP], INT32
|
|
131
|
+
],
|
|
132
|
+
hide_checkpoint_verify: [
|
|
133
|
+
[VOIDP, SIZE_T, VOIDP, VOIDP, SIZE_T, VOIDP, VOIDP], INT32
|
|
125
134
|
]
|
|
126
135
|
}.freeze
|
|
127
136
|
|
|
@@ -189,5 +198,17 @@ module Hide
|
|
|
189
198
|
slot[0, WORD] = "\x00" * WORD
|
|
190
199
|
slot
|
|
191
200
|
end
|
|
201
|
+
|
|
202
|
+
# A slot for a uint64_t out-parameter. Always 8 bytes, unlike a size_t
|
|
203
|
+
# slot, so it is read with "Q" rather than WORD_PACK.
|
|
204
|
+
def self.uint64_slot
|
|
205
|
+
slot = Fiddle::Pointer.malloc(8, Fiddle::RUBY_FREE)
|
|
206
|
+
slot[0, 8] = "\x00" * 8
|
|
207
|
+
slot
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
def self.read_uint64(slot)
|
|
211
|
+
slot[0, 8].unpack1("Q")
|
|
212
|
+
end
|
|
192
213
|
end
|
|
193
214
|
end
|
|
Binary file
|
data/lib/hide_protocol.rb
CHANGED
|
@@ -292,6 +292,77 @@ module Hide
|
|
|
292
292
|
nil
|
|
293
293
|
end
|
|
294
294
|
|
|
295
|
+
# Verifies an identity log against the root the caller pinned out of band.
|
|
296
|
+
#
|
|
297
|
+
# recovery_binding establishes the recovery key, so a log extended by a
|
|
298
|
+
# Recover under a stranger's key fails — a bare verify_identity with a
|
|
299
|
+
# recovery key taken from the same untrusted source does not catch that.
|
|
300
|
+
# Returns how many devices the log trusts now; raises MalformedError for
|
|
301
|
+
# bytes that do not decode and AuthenticationError for a log that is not
|
|
302
|
+
# this identity's.
|
|
303
|
+
def verify_identity_pinned(log, recovery_binding, pinned_root)
|
|
304
|
+
bytes = binary(log, "log")
|
|
305
|
+
binding = binary(recovery_binding, "recovery binding")
|
|
306
|
+
root = binary(pinned_root, "pinned root")
|
|
307
|
+
slot = Binding.pointer_slot
|
|
308
|
+
check(Binding.call(
|
|
309
|
+
:hide_identity_verify_pinned,
|
|
310
|
+
buffer_arg(bytes), bytes.bytesize,
|
|
311
|
+
buffer_arg(binding), binding.bytesize,
|
|
312
|
+
buffer_arg(root), root.bytesize,
|
|
313
|
+
slot
|
|
314
|
+
))
|
|
315
|
+
Binding.read_count(slot)
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
# Verifies that an epoch chain belongs to the pinned identity.
|
|
319
|
+
#
|
|
320
|
+
# epoch_binding must be signed by a device the log trusts now, over this
|
|
321
|
+
# exact chain. Returns how many epochs the chain holds.
|
|
322
|
+
def verify_epoch_chain_bound(log, recovery_binding, pinned_root, chain, epoch_binding)
|
|
323
|
+
bytes = binary(log, "log")
|
|
324
|
+
binding = binary(recovery_binding, "recovery binding")
|
|
325
|
+
root = binary(pinned_root, "pinned root")
|
|
326
|
+
chain_bytes = binary(chain, "chain")
|
|
327
|
+
epoch_bytes = binary(epoch_binding, "epoch binding")
|
|
328
|
+
slot = Binding.pointer_slot
|
|
329
|
+
check(Binding.call(
|
|
330
|
+
:hide_epoch_verify_bound,
|
|
331
|
+
buffer_arg(bytes), bytes.bytesize,
|
|
332
|
+
buffer_arg(binding), binding.bytesize,
|
|
333
|
+
buffer_arg(root), root.bytesize,
|
|
334
|
+
buffer_arg(chain_bytes), chain_bytes.bytesize,
|
|
335
|
+
buffer_arg(epoch_bytes), epoch_bytes.bytesize,
|
|
336
|
+
slot
|
|
337
|
+
))
|
|
338
|
+
Binding.read_count(slot)
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
# Verifies a signed checkpoint note from the log named origin, under the
|
|
342
|
+
# log's 1984-byte public key. Returns [size, root]: the tree size and its
|
|
343
|
+
# 32-byte root. Raises AuthenticationError when the note was altered,
|
|
344
|
+
# names another origin, or is not signed under log_public.
|
|
345
|
+
def verify_checkpoint(note, origin, log_public)
|
|
346
|
+
bytes = binary(note, "note")
|
|
347
|
+
key = binary(log_public, "log public key")
|
|
348
|
+
size = Binding.uint64_slot
|
|
349
|
+
out = Binding.empty_buffer
|
|
350
|
+
begin
|
|
351
|
+
check(Binding.call(
|
|
352
|
+
:hide_checkpoint_verify,
|
|
353
|
+
buffer_arg(bytes), bytes.bytesize,
|
|
354
|
+
cstring(origin.to_s),
|
|
355
|
+
buffer_arg(key), key.bytesize,
|
|
356
|
+
size, out
|
|
357
|
+
))
|
|
358
|
+
rescue StandardError
|
|
359
|
+
# On failure the core leaves out untouched; freeing it releases the scratch space.
|
|
360
|
+
Binding.take(out)
|
|
361
|
+
raise
|
|
362
|
+
end
|
|
363
|
+
[Binding.read_uint64(size), Binding.take(out)]
|
|
364
|
+
end
|
|
365
|
+
|
|
295
366
|
def check(code)
|
|
296
367
|
return if code == Binding::OK
|
|
297
368
|
|