confium 0.6.3 → 0.7.1
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/CHANGELOG.md +67 -0
- data/Cargo.lock +180 -11
- data/README.adoc +72 -4
- data/confium.gemspec +2 -0
- data/ext/confium_native/Cargo.toml +4 -1
- data/ext/confium_native/src/gvl.rs +56 -0
- data/ext/confium_native/src/lib.rs +26 -0
- data/ext/confium_native/src/net.rs +125 -0
- data/ext/confium_native/src/ots.rs +183 -0
- data/ext/confium_native/src/winsock.rs +784 -0
- data/lib/confium/transparency/ots.rb +42 -39
- data/lib/confium/transparency.rb +5 -5
- data/lib/confium/version.rb +1 -1
- metadata +6 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 80f1cc9387a28284e32d2c8b92fbdb5555f675f05e2ec8e6c38cd213a65e215f
|
|
4
|
+
data.tar.gz: d9ccaaf8e4297e8a731be6e19be9a5ee6566d3aa24d8398598f48fd6b2cf50fa
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b0fe995dbf54fcbc0b8fe57d815eedcba6abb10f8c4b26cd1713b62042798390861eb6faaf96168dcfcc8baa03dd54dd1d5c89d0f826f3d68f1a2bfb60416096
|
|
7
|
+
data.tar.gz: 4dde75f2b6d9c9143c546facb59bd249a1d87b6451d18a6036c1deec428773a553e2aedb8f9047465c4d0933e9f502d9d63341b74dac34ddfab3b31abafbd572
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,72 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.7.1] — UNRELEASED (code on main; release on the owner's tag)
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- `Confium::Transparency::OTS` is now the real OpenTimestamps
|
|
8
|
+
wire-protocol binding (confium-transparency 0.9): `OTS::Client#stamp`
|
|
9
|
+
POSTs the 32-byte digest to the calendar pool and returns a `Proof`
|
|
10
|
+
carrying the parsed partial proof; `#upgrade` polls for a confirmed
|
|
11
|
+
one; `Proof#verify` replays the op tree and classifies attestations
|
|
12
|
+
(pending URIs, Bitcoin/Litecoin heights, `anchored`). Module-level
|
|
13
|
+
`OTS.stamp`/`verify`/`upgrade` over the default calendar pool.
|
|
14
|
+
Network failures raise (`IOError`/`ParseError`) — the stub-era
|
|
15
|
+
silent nil is gone.
|
|
16
|
+
- The calendar round trip releases the GVL (direct
|
|
17
|
+
`rb_thread_call_without_gvl` trampoline — magnus 0.8 does not wrap
|
|
18
|
+
it), so a slow calendar never freezes the VM.
|
|
19
|
+
|
|
20
|
+
### Fixed
|
|
21
|
+
|
|
22
|
+
- The workspace's OTS file magic was missing its final two salt bytes
|
|
23
|
+
(29 vs 31; shifted every parse offset for real .ots files) — caught
|
|
24
|
+
by this binding's cross-checked specs, fixed in confium-transparency
|
|
25
|
+
v0.9.1.
|
|
26
|
+
|
|
27
|
+
## [0.7.0] — 2026-09-07
|
|
28
|
+
|
|
29
|
+
### Added
|
|
30
|
+
|
|
31
|
+
- `Confium::Transport::SignerClient` / `CoordinatorServer` —
|
|
32
|
+
coordinator sessions over any registry transport the extension
|
|
33
|
+
links, addressed by URL: `tcp://host:port` for local/trusted
|
|
34
|
+
networks, `noise://host:port` for Noise_XX
|
|
35
|
+
(`Noise_XX_25519_ChaChaPoly_BLAKE2s`) encrypted sessions.
|
|
36
|
+
`noise://` URLs take `key=<hex>` (local static private key;
|
|
37
|
+
ephemeral and trust-on-first-use when omitted) and `pinned=<hex>`
|
|
38
|
+
(SHA-256 fingerprint of the expected peer static key — the
|
|
39
|
+
handshake aborts on mismatch). The handshake carries a 10-second
|
|
40
|
+
deadline so a non-Noise peer fails fast instead of hanging.
|
|
41
|
+
`SignerClient` exposes `#register`, `#create_session`,
|
|
42
|
+
`#submit_commitment`, `#submit_share` (returns the aggregated
|
|
43
|
+
signature once the threshold is met, else nil);
|
|
44
|
+
`CoordinatorServer.new(url)` serves any linked scheme for tests
|
|
45
|
+
and single-process deployments.
|
|
46
|
+
|
|
47
|
+
### Changed
|
|
48
|
+
|
|
49
|
+
- **BREAKING**: `Confium::Net` is `Confium::Transport`. Defining
|
|
50
|
+
`Confium::Net` shadowed Ruby stdlib `Net` for every constant
|
|
51
|
+
lookup under the `Confium` namespace — `Confium::Audit::OtlpSink`'s
|
|
52
|
+
`Net::HTTP` resolved to `Confium::Net::HTTP` and raised
|
|
53
|
+
`NameError`. No prior release shipped the `Net` names.
|
|
54
|
+
|
|
55
|
+
## [0.6.3] — 2026-08-26
|
|
56
|
+
|
|
57
|
+
### Added
|
|
58
|
+
|
|
59
|
+
- `Confium::TC::Session` — per-party threshold protocol sessions
|
|
60
|
+
over confium-tc-core 0.4: each signer process runs its own
|
|
61
|
+
session (`"FROST-ed25519-dkg"` for distributed key generation,
|
|
62
|
+
`"FROST-ed25519"` for signing with the DKG share and message) and
|
|
63
|
+
exchanges only `round_step` messages — the share never leaves the
|
|
64
|
+
process. `#round_step(incoming)` returns
|
|
65
|
+
`{ "outgoing" => [...], "complete" => bool }`; the completed DKG
|
|
66
|
+
session's `#result` is the party's share blob, the signing
|
|
67
|
+
session's `#result` an RFC 8032 Ed25519 signature verifiable under
|
|
68
|
+
the group public key.
|
|
69
|
+
|
|
3
70
|
## [0.6.2] — 2026-08-26
|
|
4
71
|
|
|
5
72
|
### Added
|
data/Cargo.lock
CHANGED
|
@@ -135,6 +135,15 @@ dependencies = [
|
|
|
135
135
|
"wyz",
|
|
136
136
|
]
|
|
137
137
|
|
|
138
|
+
[[package]]
|
|
139
|
+
name = "blake2"
|
|
140
|
+
version = "0.10.6"
|
|
141
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
142
|
+
checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe"
|
|
143
|
+
dependencies = [
|
|
144
|
+
"digest 0.10.7",
|
|
145
|
+
]
|
|
146
|
+
|
|
138
147
|
[[package]]
|
|
139
148
|
name = "block-buffer"
|
|
140
149
|
version = "0.10.4"
|
|
@@ -207,6 +216,30 @@ version = "1.0.4"
|
|
|
207
216
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
208
217
|
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
|
209
218
|
|
|
219
|
+
[[package]]
|
|
220
|
+
name = "chacha20"
|
|
221
|
+
version = "0.9.1"
|
|
222
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
223
|
+
checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818"
|
|
224
|
+
dependencies = [
|
|
225
|
+
"cfg-if",
|
|
226
|
+
"cipher",
|
|
227
|
+
"cpufeatures 0.2.17",
|
|
228
|
+
]
|
|
229
|
+
|
|
230
|
+
[[package]]
|
|
231
|
+
name = "chacha20poly1305"
|
|
232
|
+
version = "0.10.1"
|
|
233
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
234
|
+
checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35"
|
|
235
|
+
dependencies = [
|
|
236
|
+
"aead",
|
|
237
|
+
"chacha20",
|
|
238
|
+
"cipher",
|
|
239
|
+
"poly1305",
|
|
240
|
+
"zeroize",
|
|
241
|
+
]
|
|
242
|
+
|
|
210
243
|
[[package]]
|
|
211
244
|
name = "chrono"
|
|
212
245
|
version = "0.4.45"
|
|
@@ -229,6 +262,7 @@ checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
|
|
|
229
262
|
dependencies = [
|
|
230
263
|
"crypto-common 0.1.7",
|
|
231
264
|
"inout",
|
|
265
|
+
"zeroize",
|
|
232
266
|
]
|
|
233
267
|
|
|
234
268
|
[[package]]
|
|
@@ -301,7 +335,7 @@ checksum = "e8c96d4d5997726cf0eb794410e3e8bbce839cfba9c4a32e26ede0c076b02e64"
|
|
|
301
335
|
dependencies = [
|
|
302
336
|
"chrono",
|
|
303
337
|
"confium-api",
|
|
304
|
-
"confium-net",
|
|
338
|
+
"confium-net 0.3.0",
|
|
305
339
|
"confium-store 0.3.0",
|
|
306
340
|
"confium-tc-core 0.3.0",
|
|
307
341
|
"data-encoding",
|
|
@@ -321,6 +355,26 @@ dependencies = [
|
|
|
321
355
|
"zeroize",
|
|
322
356
|
]
|
|
323
357
|
|
|
358
|
+
[[package]]
|
|
359
|
+
name = "confium-coordinator"
|
|
360
|
+
version = "0.8.5"
|
|
361
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
362
|
+
checksum = "52f49eae3301b6f1f2f36b2eb66d0fdd863bcecb1dc18b51ec51e5f8d1bb9dc3"
|
|
363
|
+
dependencies = [
|
|
364
|
+
"chrono",
|
|
365
|
+
"confium-net 0.8.5",
|
|
366
|
+
"getrandom 0.4.3",
|
|
367
|
+
"hex",
|
|
368
|
+
"hmac 0.13.0",
|
|
369
|
+
"p256 0.14.0",
|
|
370
|
+
"rand_core 0.6.4",
|
|
371
|
+
"serde",
|
|
372
|
+
"serde_json",
|
|
373
|
+
"sha2 0.11.0",
|
|
374
|
+
"thiserror 2.0.20",
|
|
375
|
+
"tracing",
|
|
376
|
+
]
|
|
377
|
+
|
|
324
378
|
[[package]]
|
|
325
379
|
name = "confium-core"
|
|
326
380
|
version = "0.2.0"
|
|
@@ -413,6 +467,44 @@ dependencies = [
|
|
|
413
467
|
"url",
|
|
414
468
|
]
|
|
415
469
|
|
|
470
|
+
[[package]]
|
|
471
|
+
name = "confium-net"
|
|
472
|
+
version = "0.8.5"
|
|
473
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
474
|
+
checksum = "2bd7098e54033a09b1f6a4ebd0c0f54d6c44da8f46cfdff7ae156895f1083fc6"
|
|
475
|
+
dependencies = [
|
|
476
|
+
"inventory",
|
|
477
|
+
"snafu 0.9.2",
|
|
478
|
+
"url",
|
|
479
|
+
]
|
|
480
|
+
|
|
481
|
+
[[package]]
|
|
482
|
+
name = "confium-net-noise"
|
|
483
|
+
version = "0.8.5"
|
|
484
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
485
|
+
checksum = "213e90ce6daa40d1ec92d8e524276744a07f027c453bd32815f80c29ba947237"
|
|
486
|
+
dependencies = [
|
|
487
|
+
"confium-net 0.8.5",
|
|
488
|
+
"inventory",
|
|
489
|
+
"sha2 0.11.0",
|
|
490
|
+
"snafu 0.9.2",
|
|
491
|
+
"snow",
|
|
492
|
+
"url",
|
|
493
|
+
"x25519-dalek",
|
|
494
|
+
]
|
|
495
|
+
|
|
496
|
+
[[package]]
|
|
497
|
+
name = "confium-net-tcp"
|
|
498
|
+
version = "0.8.3"
|
|
499
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
500
|
+
checksum = "1b80e3d692ed5328a72e754a0f73d81f6c8fde3714d05fc0be1953f657e05f76"
|
|
501
|
+
dependencies = [
|
|
502
|
+
"confium-net 0.8.5",
|
|
503
|
+
"inventory",
|
|
504
|
+
"snafu 0.9.2",
|
|
505
|
+
"url",
|
|
506
|
+
]
|
|
507
|
+
|
|
416
508
|
[[package]]
|
|
417
509
|
name = "confium-observability"
|
|
418
510
|
version = "0.3.0"
|
|
@@ -493,8 +585,8 @@ checksum = "3dd7d4965aef12324cb76d397294c317b83b774de029f1d37b387cf54ba9593c"
|
|
|
493
585
|
dependencies = [
|
|
494
586
|
"chrono",
|
|
495
587
|
"confium-api",
|
|
496
|
-
"confium-coordinator",
|
|
497
|
-
"confium-net",
|
|
588
|
+
"confium-coordinator 0.3.0",
|
|
589
|
+
"confium-net 0.3.0",
|
|
498
590
|
"confium-store 0.3.0",
|
|
499
591
|
"confium-tc-keys",
|
|
500
592
|
"data-encoding",
|
|
@@ -566,7 +658,7 @@ checksum = "add3e15337ce81944f78c9ce844d870a081cbe91506a85b9a5c4e4c0da983771"
|
|
|
566
658
|
dependencies = [
|
|
567
659
|
"chrono",
|
|
568
660
|
"confium-api",
|
|
569
|
-
"confium-net",
|
|
661
|
+
"confium-net 0.3.0",
|
|
570
662
|
"confium-store 0.3.0",
|
|
571
663
|
"data-encoding",
|
|
572
664
|
"hex",
|
|
@@ -683,17 +775,18 @@ dependencies = [
|
|
|
683
775
|
|
|
684
776
|
[[package]]
|
|
685
777
|
name = "confium-transparency"
|
|
686
|
-
version = "0.
|
|
778
|
+
version = "0.9.1"
|
|
687
779
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
688
|
-
checksum = "
|
|
780
|
+
checksum = "b4ec484381b582f508f774babbc1bf1b4a98c6aadd43cde806952c6e416b62ca"
|
|
689
781
|
dependencies = [
|
|
690
782
|
"chrono",
|
|
691
|
-
"
|
|
783
|
+
"hex",
|
|
692
784
|
"serde",
|
|
693
785
|
"serde_json",
|
|
694
|
-
"sha2 0.
|
|
695
|
-
"
|
|
696
|
-
"thiserror
|
|
786
|
+
"sha2 0.11.0",
|
|
787
|
+
"subtle",
|
|
788
|
+
"thiserror 2.0.20",
|
|
789
|
+
"ureq",
|
|
697
790
|
]
|
|
698
791
|
|
|
699
792
|
[[package]]
|
|
@@ -703,10 +796,13 @@ dependencies = [
|
|
|
703
796
|
"chrono",
|
|
704
797
|
"confium-attributes",
|
|
705
798
|
"confium-composite",
|
|
799
|
+
"confium-coordinator 0.8.5",
|
|
706
800
|
"confium-core",
|
|
707
801
|
"confium-crypto-vss",
|
|
708
802
|
"confium-crypto-zk",
|
|
709
803
|
"confium-deployment",
|
|
804
|
+
"confium-net-noise",
|
|
805
|
+
"confium-net-tcp",
|
|
710
806
|
"confium-observability",
|
|
711
807
|
"confium-pki",
|
|
712
808
|
"confium-privacy",
|
|
@@ -1215,6 +1311,18 @@ dependencies = [
|
|
|
1215
1311
|
"wasi",
|
|
1216
1312
|
]
|
|
1217
1313
|
|
|
1314
|
+
[[package]]
|
|
1315
|
+
name = "getrandom"
|
|
1316
|
+
version = "0.3.4"
|
|
1317
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1318
|
+
checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd"
|
|
1319
|
+
dependencies = [
|
|
1320
|
+
"cfg-if",
|
|
1321
|
+
"libc",
|
|
1322
|
+
"r-efi 5.3.0",
|
|
1323
|
+
"wasip2",
|
|
1324
|
+
]
|
|
1325
|
+
|
|
1218
1326
|
[[package]]
|
|
1219
1327
|
name = "getrandom"
|
|
1220
1328
|
version = "0.4.3"
|
|
@@ -1223,7 +1331,7 @@ checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099"
|
|
|
1223
1331
|
dependencies = [
|
|
1224
1332
|
"cfg-if",
|
|
1225
1333
|
"libc",
|
|
1226
|
-
"r-efi",
|
|
1334
|
+
"r-efi 6.0.0",
|
|
1227
1335
|
"rand_core 0.10.1",
|
|
1228
1336
|
]
|
|
1229
1337
|
|
|
@@ -1785,6 +1893,17 @@ version = "0.3.34"
|
|
|
1785
1893
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1786
1894
|
checksum = "f6b464fbc74e149a392436b17d523f769e057cb6877f6a5c4618bc6f11800548"
|
|
1787
1895
|
|
|
1896
|
+
[[package]]
|
|
1897
|
+
name = "poly1305"
|
|
1898
|
+
version = "0.8.0"
|
|
1899
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1900
|
+
checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf"
|
|
1901
|
+
dependencies = [
|
|
1902
|
+
"cpufeatures 0.2.17",
|
|
1903
|
+
"opaque-debug",
|
|
1904
|
+
"universal-hash",
|
|
1905
|
+
]
|
|
1906
|
+
|
|
1788
1907
|
[[package]]
|
|
1789
1908
|
name = "polyval"
|
|
1790
1909
|
version = "0.6.2"
|
|
@@ -1879,6 +1998,12 @@ dependencies = [
|
|
|
1879
1998
|
"proc-macro2",
|
|
1880
1999
|
]
|
|
1881
2000
|
|
|
2001
|
+
[[package]]
|
|
2002
|
+
name = "r-efi"
|
|
2003
|
+
version = "5.3.0"
|
|
2004
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2005
|
+
checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
|
|
2006
|
+
|
|
1882
2007
|
[[package]]
|
|
1883
2008
|
name = "r-efi"
|
|
1884
2009
|
version = "6.0.0"
|
|
@@ -2348,6 +2473,23 @@ dependencies = [
|
|
|
2348
2473
|
"syn 2.0.119",
|
|
2349
2474
|
]
|
|
2350
2475
|
|
|
2476
|
+
[[package]]
|
|
2477
|
+
name = "snow"
|
|
2478
|
+
version = "0.10.0"
|
|
2479
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2480
|
+
checksum = "599b506ccc4aff8cf7844bc42cf783009a434c1e26c964432560fb6d6ad02d82"
|
|
2481
|
+
dependencies = [
|
|
2482
|
+
"aes-gcm",
|
|
2483
|
+
"blake2",
|
|
2484
|
+
"chacha20poly1305",
|
|
2485
|
+
"curve25519-dalek",
|
|
2486
|
+
"getrandom 0.3.4",
|
|
2487
|
+
"ring",
|
|
2488
|
+
"rustc_version",
|
|
2489
|
+
"sha2 0.10.9",
|
|
2490
|
+
"subtle",
|
|
2491
|
+
]
|
|
2492
|
+
|
|
2351
2493
|
[[package]]
|
|
2352
2494
|
name = "spki"
|
|
2353
2495
|
version = "0.7.3"
|
|
@@ -2666,6 +2808,15 @@ version = "0.11.1+wasi-snapshot-preview1"
|
|
|
2666
2808
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2667
2809
|
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
|
|
2668
2810
|
|
|
2811
|
+
[[package]]
|
|
2812
|
+
name = "wasip2"
|
|
2813
|
+
version = "1.0.4+wasi-0.2.12"
|
|
2814
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2815
|
+
checksum = "b67efb37e106e55ce722a510d6b5f9c17f083e5fc79afc2badeb12cc313d9487"
|
|
2816
|
+
dependencies = [
|
|
2817
|
+
"wit-bindgen",
|
|
2818
|
+
]
|
|
2819
|
+
|
|
2669
2820
|
[[package]]
|
|
2670
2821
|
name = "wasm-bindgen"
|
|
2671
2822
|
version = "0.2.126"
|
|
@@ -2870,6 +3021,12 @@ dependencies = [
|
|
|
2870
3021
|
"memchr",
|
|
2871
3022
|
]
|
|
2872
3023
|
|
|
3024
|
+
[[package]]
|
|
3025
|
+
name = "wit-bindgen"
|
|
3026
|
+
version = "0.57.1"
|
|
3027
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
3028
|
+
checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e"
|
|
3029
|
+
|
|
2873
3030
|
[[package]]
|
|
2874
3031
|
name = "wnaf"
|
|
2875
3032
|
version = "0.14.0"
|
|
@@ -2896,6 +3053,18 @@ dependencies = [
|
|
|
2896
3053
|
"tap",
|
|
2897
3054
|
]
|
|
2898
3055
|
|
|
3056
|
+
[[package]]
|
|
3057
|
+
name = "x25519-dalek"
|
|
3058
|
+
version = "2.0.1"
|
|
3059
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
3060
|
+
checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277"
|
|
3061
|
+
dependencies = [
|
|
3062
|
+
"curve25519-dalek",
|
|
3063
|
+
"rand_core 0.6.4",
|
|
3064
|
+
"serde",
|
|
3065
|
+
"zeroize",
|
|
3066
|
+
]
|
|
3067
|
+
|
|
2899
3068
|
[[package]]
|
|
2900
3069
|
name = "x509-cert"
|
|
2901
3070
|
version = "0.3.0"
|
data/README.adoc
CHANGED
|
@@ -18,7 +18,7 @@ Add to your Gemfile:
|
|
|
18
18
|
|
|
19
19
|
[source,ruby]
|
|
20
20
|
----
|
|
21
|
-
gem "confium", "~> 0.
|
|
21
|
+
gem "confium", "~> 0.7"
|
|
22
22
|
----
|
|
23
23
|
|
|
24
24
|
Or install directly:
|
|
@@ -78,18 +78,38 @@ kp = Confium::TC::FrostP256.generate_keypair
|
|
|
78
78
|
shares = Confium::TC::FrostP256.split_secret(kp["private_key"], 3, 5)
|
|
79
79
|
recovered = Confium::TC::FrostP256.recover_secret(shares.first(3).map { |s| { "x" => s.x, "y" => s.y_bytes } })
|
|
80
80
|
recovered == kp["private_key"] # => true
|
|
81
|
+
|
|
82
|
+
# Distributed key generation + 2-of-3 FROST-ed25519 signing (each party
|
|
83
|
+
# holds its own Confium::TC::Session and only exchanges round messages)
|
|
84
|
+
parties = %w[alice bob carol]
|
|
85
|
+
sessions = parties.each_with_index.map do |id, i|
|
|
86
|
+
Confium::TC::Session.new("FROST-ed25519-dkg", parties: parties, threshold: 2, this_party_idx: i)
|
|
87
|
+
end
|
|
88
|
+
# run rounds: session.round_step(messages_in) -> {"outgoing" => [...], "complete" => bool}
|
|
89
|
+
# broadcast "outgoing" payloads between sessions until every session is complete
|
|
90
|
+
dkg_share = sessions.first.result # this party's share (embeds the group public key)
|
|
91
|
+
|
|
92
|
+
signers = sessions.first(2).map.with_index do |s, i|
|
|
93
|
+
Confium::TC::Session.new("FROST-ed25519",
|
|
94
|
+
parties: parties.first(2), threshold: 2, this_party_idx: i,
|
|
95
|
+
local_share: dkg_share, message: "authentic message")
|
|
96
|
+
end
|
|
97
|
+
# run rounds as above; the completed session's #result is an RFC 8032
|
|
98
|
+
# Ed25519 signature verifiable under the group public key
|
|
81
99
|
----
|
|
82
100
|
|
|
83
|
-
== API surface (v0.
|
|
101
|
+
== API surface (v0.7)
|
|
84
102
|
|
|
85
103
|
=== `Confium::Transparency`
|
|
86
104
|
- `MerkleTree.new` / `#append(artifact_hash)` / `#root` / `#length` / `#empty?` / `#inclusion_proof(seq)`
|
|
87
105
|
- `InclusionProof#sequence` / `#steps` / `#verify(root)`
|
|
106
|
+
- `Ots.stamp(hash)` / `Ots.verify(proof)` / `Ots.upgrade(proof)` — real OpenTimestamps anchoring over the wire protocol (calendar HTTP, servers tried in order; the network round trip releases the GVL). `Ots::Client.new(servers)` for a custom pool; `Ots::Proof#verify` replays the op tree and classifies attestations. Network failures raise — there is no silent nil
|
|
88
107
|
|
|
89
108
|
=== `Confium::Composite` — PQ migration
|
|
90
109
|
- `.generate_ed25519_keypair` → `{ private_key:, public_key: }`
|
|
91
110
|
- `.sign_ed25519(private_key, message)` → component Hash
|
|
92
|
-
- `Signature.new(components)` / `#verify(message)` / `#component_count` / `#algorithms`
|
|
111
|
+
- `Signature.new(components)` / `#verify(message)` / `#component_count` / `#algorithms` / `#to_json`
|
|
112
|
+
- `.from_json(json)` / `.components_to_json(components)` / `.canonical_json(json, data)`
|
|
93
113
|
- `VerificationResult#all_verified?` / `#per_component`
|
|
94
114
|
|
|
95
115
|
=== `Confium::Attributes` — threshold policy DSL
|
|
@@ -99,11 +119,14 @@ recovered == kp["private_key"] # => true
|
|
|
99
119
|
- DSL: `min_count("attr", n)`, `min_distinct("attr", n)`, `any("attr")`, `all("attr")`, `none("attr")`, `and(...)`, `or(...)`, `not(p)`
|
|
100
120
|
|
|
101
121
|
=== `Confium::PKI`
|
|
102
|
-
- `Certificate.from_der(bytes)` / `.from_pem(str)` / `#to_der` / `#to_pem` / `#fingerprint_sha256` / `#serial_hex` / `#not_before` / `#not_after` / `#valid_at?(iso8601)` / `#public_key_bytes`
|
|
122
|
+
- `Certificate.from_der(bytes)` / `.from_pem(str)` / `#to_der` / `#to_pem` / `#fingerprint_sha256` / `#serial_hex` / `#not_before` / `#not_after` / `#valid_at?(iso8601)` / `#public_key_bytes`; DER parse failures carry a byte `offset` in the error details
|
|
123
|
+
- `CertificateBuilder` / `CMS::SignedDataBuilder` — build certificates and signed data in Ruby
|
|
124
|
+
- `PathValidator.validate(leaf, intermediates, root, now_iso8601 = nil)` → `PathValidationResult` (chain validation leaf → root at a point in time)
|
|
103
125
|
- `CSR.from_der` / `.from_pem` / `#to_der` / `#to_pem`
|
|
104
126
|
- `CMS::SignedData.from_json` / `#to_json` / `#signer_count` / `#content_type` / `#content` / `#certificate_count` / `#certificate_at(i)`
|
|
105
127
|
- `CMS::Content#bytes` / `#length`
|
|
106
128
|
- `XMLDSig.canonicalize(xml)` / `.canonicalize_exclusive(xml)` (Canonical XML RFC 3076 + Exclusive C14N)
|
|
129
|
+
- `Cnml` — institutional certificate workflow helpers
|
|
107
130
|
|
|
108
131
|
=== `Confium::Identity` — actor roles
|
|
109
132
|
- `.actor_types` → `["manufacturer", "testing_lab", "issuing_authority_officer", "biml_director", "quorum_coordinator", "verifier"]`
|
|
@@ -123,6 +146,51 @@ recovered == kp["private_key"] # => true
|
|
|
123
146
|
- `.partial_decrypt(party_index, share_bytes, ciphertext)` → `{ party_index:, bytes: }`
|
|
124
147
|
- `.aggregate_partials(partials, threshold, ciphertext)` → shared_secret bytes
|
|
125
148
|
|
|
149
|
+
=== `Confium::TC::Cmp20` / `Confium::TC::Gg18` — threshold ECDSA protocols
|
|
150
|
+
- `.keygen(threshold, parties)` → `{ public_key, shares }`
|
|
151
|
+
- `.sign(shares, public_key, message)` → DER ECDSA signature
|
|
152
|
+
|
|
153
|
+
=== `Confium::TC::Session` — per-party threshold sessions (real FROST)
|
|
154
|
+
- `Session.new(scheme, parties:, threshold:, this_party_idx:, local_share: nil, message: nil)` — `"FROST-ed25519-dkg"` for distributed key generation, `"FROST-ed25519"` for signing (pass the DKG share and the message)
|
|
155
|
+
- `#scheme_name` / `#threshold` / `#party_count` / `#this_party_idx` / `#round` / `#complete?`
|
|
156
|
+
- `#round_step(messages)` → `{ "outgoing" => [{from, to, round, payload}...], "complete" => bool }` — feed each round's incoming messages, broadcast the outgoing ones
|
|
157
|
+
- `#result` — after DKG: share blob (group public key + party share); after signing: RFC 8032 Ed25519 signature
|
|
158
|
+
|
|
159
|
+
=== `Confium::TC::Coordinator` — quorum signing orchestration
|
|
160
|
+
- `Coordinator.new(quorum_id:)` / `#create_session(message:, threshold:, scheme: "CMP20-ECDSA-P256")` / `#submit_commitment` / `#submit_share` / `#aggregate` / `#session_state`
|
|
161
|
+
- `SigningSession#add_commitment` / `#add_share` / `#threshold_met?` / `#aggregate` — the seam every transport adapts to
|
|
162
|
+
- `NetworkCoordinator` — TCP/NDJSON server (`#start` / `#stop` / `#running?`); `SignerClient` — remote submit + aggregate with typed `RemoteError`
|
|
163
|
+
- `ShareFile` — encrypted share-file persistence
|
|
164
|
+
|
|
165
|
+
=== `Confium::Store::Keystore` — key handles and remote signing
|
|
166
|
+
- `Keystore.new(backend, **options)` / `.backends`
|
|
167
|
+
- `#sign(key_id, algorithm, message)` → signature bytes (sign-with-handle contract; cloud KMS backends `aws-kms` / `gcp-kms` / `azure-keyvault` via cargo features)
|
|
168
|
+
|
|
169
|
+
=== `Confium::Audit` — structured audit trail
|
|
170
|
+
- `Audit.sink =` / `Audit.sink` / `Audit.enabled?` / `Audit.record(...)`
|
|
171
|
+
- `Sink` (base) / `MemorySink` / `StderrSink` / `FileSink`
|
|
172
|
+
- `OtlpSink.new(endpoint:, headers:, service_name:, ...)` — OTLP/HTTP export with retry and `#dropped` counter
|
|
173
|
+
|
|
174
|
+
=== `Confium::OpenPGP`
|
|
175
|
+
- `.armor(data, type)` / `.dearmor(data)` — RFC 9580 §6 ASCII armor with CRC-24 (pure Ruby)
|
|
176
|
+
- `.verify_detached(message, signature, keys)` / `.verify(...)` — real signature verification when the extension is built with the `pgp` feature; `PGP_AVAILABLE` reports it
|
|
177
|
+
|
|
178
|
+
=== `Confium::Transport` — coordinator clients over any transport
|
|
179
|
+
- `SignerClient.new(url)` — connect over any registry transport: `tcp://host:port` (local/trusted) or `noise://host:port?key=<hex>&pinned=<hex>` (Noise_XX encrypted, stable identity + peer pinning)
|
|
180
|
+
- `#register(signer_id, quorum_id)` / `#create_session(quorum_id, scheme, message, threshold, num_parties)` → session id
|
|
181
|
+
- `#submit_commitment(session_id, signer_id, bytes)` / `#submit_share(session_id, signer_id, bytes)`
|
|
182
|
+
- `CoordinatorServer.new(url)` — serve coordinator sessions over any linked scheme (test/in-process use)
|
|
183
|
+
|
|
184
|
+
=== `Confium::ERS` — evidence records
|
|
185
|
+
- `EvidenceRecord.build_initial(...)` / `#renew(...)` / `#renewal_count` (RFC 4998 / RFC 6283 archival)
|
|
186
|
+
|
|
187
|
+
=== `Confium::Policy` / `Confium::SecureBytes`
|
|
188
|
+
- `Policy.jurisdiction = :eu` — jurisdictional algorithm policy (EU/US profiles; SM2/SM3/SM4 for CN planned)
|
|
189
|
+
- `SecureBytes.wrap(raw)` — zeroize-on-clear wrapper for private keys, shares, and secrets (`#bytes` non-destructive read, `#clear`)
|
|
190
|
+
|
|
191
|
+
=== Errors
|
|
192
|
+
- Typed error hierarchy (`ParseError`, `ThresholdError`, `VerificationError`, `PolicyViolationError`, ...) — native failures surface positional `details` hashes (including DER byte offsets for parse errors)
|
|
193
|
+
|
|
126
194
|
== Development
|
|
127
195
|
|
|
128
196
|
After checking out the repo:
|
data/confium.gemspec
CHANGED
|
@@ -40,6 +40,8 @@ Gem::Specification.new do |spec|
|
|
|
40
40
|
]
|
|
41
41
|
spec.files.reject! { |f| File.directory?(f) }
|
|
42
42
|
spec.files.reject! { |f| f =~ /\.(dll|so|dylib|lib|bundle)\Z/ }
|
|
43
|
+
# Windows socket diagnostic crate — development-only, never shipped.
|
|
44
|
+
spec.files.reject! { |f| f.start_with?('ext/socket-smoke/') }
|
|
43
45
|
spec.require_paths = ['lib']
|
|
44
46
|
|
|
45
47
|
spec.required_ruby_version = '>= 3.1.0'
|
|
@@ -25,6 +25,9 @@ build = "build.rs"
|
|
|
25
25
|
pgp = ["rnp"]
|
|
26
26
|
|
|
27
27
|
[dependencies]
|
|
28
|
+
confium-coordinator = "0.8"
|
|
29
|
+
confium-net-noise = "0.8"
|
|
30
|
+
confium-net-tcp = "0.8"
|
|
28
31
|
# rb-sys for Ruby C API access.
|
|
29
32
|
rb-sys = { version = "0.9.124", features = ["global-allocator"] }
|
|
30
33
|
|
|
@@ -33,7 +36,7 @@ magnus = { version = "0.8", features = ["bytes"] }
|
|
|
33
36
|
|
|
34
37
|
# Confium crates — all from crates.io so gem install works without workspace checkout.
|
|
35
38
|
confium-core = "0.2"
|
|
36
|
-
confium-transparency = "0.
|
|
39
|
+
confium-transparency = { version = "0.9", features = ["calendar"] }
|
|
37
40
|
confium-composite = "0.3.1"
|
|
38
41
|
confium-attributes = "0.3.1"
|
|
39
42
|
confium-pki = "0.5.6"
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
//! GVL release for long blocking calls.
|
|
2
|
+
//!
|
|
3
|
+
//! magnus 0.8 does not wrap `rb_thread_call_without_gvl`, so the OTS
|
|
4
|
+
//! calendar round trip (up to 30s) would hold the GVL and freeze the
|
|
5
|
+
//! entire Ruby VM — including any Ruby thread serving as the peer.
|
|
6
|
+
//! This is the standard MRI mechanism: release the GVL for the
|
|
7
|
+
//! duration of a blocking FFI call, reacquire before touching Ruby
|
|
8
|
+
//! objects again. The closure must not touch the Ruby API.
|
|
9
|
+
|
|
10
|
+
use std::ffi::c_void;
|
|
11
|
+
|
|
12
|
+
unsafe extern "C" {
|
|
13
|
+
fn rb_thread_call_without_gvl(
|
|
14
|
+
func: extern "C" fn(*mut c_void) -> *mut c_void,
|
|
15
|
+
data1: *mut c_void,
|
|
16
|
+
ubf: Option<extern "C" fn(*mut c_void) -> *mut c_void>,
|
|
17
|
+
data2: *mut c_void,
|
|
18
|
+
) -> *mut c_void;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
struct CallBox<F: FnOnce() -> T, T> {
|
|
22
|
+
func: Option<F>,
|
|
23
|
+
out: Option<T>,
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
extern "C" fn trampoline<F: FnOnce() -> T, T>(data: *mut c_void) -> *mut c_void {
|
|
27
|
+
// SAFETY: data points at the CallBox constructed by without_gvl,
|
|
28
|
+
// live for the duration of the call, on this same thread.
|
|
29
|
+
let box_ = unsafe { &mut *(data as *mut CallBox<F, T>) };
|
|
30
|
+
let func = box_.func.take().expect("trampoline runs once");
|
|
31
|
+
box_.out = Some(func());
|
|
32
|
+
std::ptr::null_mut()
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/// Run `func` with the GVL released. Reacquires before returning.
|
|
36
|
+
///
|
|
37
|
+
/// # Safety (caller obligations)
|
|
38
|
+
///
|
|
39
|
+
/// `func` must not call the Ruby C API (no Ruby objects) and must be
|
|
40
|
+
/// callable from this thread while the GVL is released.
|
|
41
|
+
pub unsafe fn without_gvl<F: FnOnce() -> T, T>(func: F) -> T {
|
|
42
|
+
let mut call = CallBox {
|
|
43
|
+
func: Some(func),
|
|
44
|
+
out: None,
|
|
45
|
+
};
|
|
46
|
+
// SAFETY: the trampoline and box are used per the contract above.
|
|
47
|
+
unsafe {
|
|
48
|
+
rb_thread_call_without_gvl(
|
|
49
|
+
trampoline::<F, T>,
|
|
50
|
+
&mut call as *mut CallBox<F, T> as *mut c_void,
|
|
51
|
+
None,
|
|
52
|
+
std::ptr::null_mut(),
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
call.out.take().expect("trampoline stored the result")
|
|
56
|
+
}
|
|
@@ -9,15 +9,21 @@ mod attributes;
|
|
|
9
9
|
mod composite;
|
|
10
10
|
mod deployment;
|
|
11
11
|
mod ers;
|
|
12
|
+
mod gvl;
|
|
12
13
|
mod openpgp_verify;
|
|
13
14
|
mod path;
|
|
14
15
|
mod pki;
|
|
15
16
|
mod store;
|
|
16
17
|
mod tc;
|
|
18
|
+
mod net;
|
|
19
|
+
mod ots;
|
|
17
20
|
mod tc_session;
|
|
18
21
|
mod transparency;
|
|
19
22
|
mod util;
|
|
20
23
|
|
|
24
|
+
#[cfg(windows)]
|
|
25
|
+
mod winsock;
|
|
26
|
+
|
|
21
27
|
use magnus::{function, Error, Module, Ruby};
|
|
22
28
|
|
|
23
29
|
const VERSION: &str = env!("CARGO_PKG_VERSION");
|
|
@@ -30,6 +36,19 @@ fn native_loaded() -> bool {
|
|
|
30
36
|
true
|
|
31
37
|
}
|
|
32
38
|
|
|
39
|
+
/// `Confium::Native.winsock_probe(tag)` — run the winsock diagnostic
|
|
40
|
+
/// sequence at an arbitrary point (Windows only; no-op elsewhere).
|
|
41
|
+
/// Timeline bisect for the listener bind failure: call it at ext
|
|
42
|
+
/// load, suite start, and just before a ceremony to see exactly when
|
|
43
|
+
/// each std net operation degrades.
|
|
44
|
+
fn winsock_probe_fn(tag: String) -> Result<(), Error> {
|
|
45
|
+
#[cfg(windows)]
|
|
46
|
+
winsock::probe_on_demand(&tag);
|
|
47
|
+
#[cfg(not(windows))]
|
|
48
|
+
let _ = tag;
|
|
49
|
+
Ok(())
|
|
50
|
+
}
|
|
51
|
+
|
|
33
52
|
fn core_version() -> &'static str {
|
|
34
53
|
// Set by build.rs at compile time from Cargo.lock. Always matches the
|
|
35
54
|
// confium-core crate version the extension was built against.
|
|
@@ -38,13 +57,19 @@ fn core_version() -> &'static str {
|
|
|
38
57
|
|
|
39
58
|
#[magnus::init]
|
|
40
59
|
fn init(ruby: &Ruby) -> Result<(), Error> {
|
|
60
|
+
#[cfg(windows)]
|
|
61
|
+
winsock::probe();
|
|
62
|
+
|
|
41
63
|
let confium = ruby.define_module("Confium")?;
|
|
42
64
|
let native = confium.define_module("Native")?;
|
|
43
65
|
native.define_module_function("version", function!(native_version, 0))?;
|
|
44
66
|
native.define_module_function("loaded?", function!(native_loaded, 0))?;
|
|
45
67
|
confium.define_module_function("core_version", function!(core_version, 0))?;
|
|
68
|
+
native.define_module_function("winsock_probe", function!(winsock_probe_fn, 1))?;
|
|
46
69
|
|
|
47
70
|
transparency::init(ruby, confium)?;
|
|
71
|
+
let transparency = confium.define_module("Transparency")?;
|
|
72
|
+
ots::init(ruby, transparency)?;
|
|
48
73
|
openpgp_verify::init(ruby, confium)?;
|
|
49
74
|
#[cfg(feature = "pgp")]
|
|
50
75
|
openpgp_verify::init_pgp(ruby, &confium)?;
|
|
@@ -56,6 +81,7 @@ fn init(ruby: &Ruby) -> Result<(), Error> {
|
|
|
56
81
|
deployment::init(ruby, confium)?;
|
|
57
82
|
tc::init(ruby, confium)?;
|
|
58
83
|
tc_session::init(ruby, confium)?;
|
|
84
|
+
net::init(ruby, confium)?;
|
|
59
85
|
audit::init(ruby, confium)?;
|
|
60
86
|
ers::init(ruby, confium)?;
|
|
61
87
|
Ok(())
|