pq_crypto-seal 0.1.2 → 0.1.4
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 +74 -0
- data/FORMAT.md +1 -1
- data/README.md +8 -7
- data/RELEASING.md +8 -9
- data/SECURITY.md +9 -2
- data/VENDORING.md +1 -1
- data/ext/pq_crypto_seal/aegis_unused_stubs.c +6 -5
- data/ext/pq_crypto_seal/extconf.rb +361 -247
- data/ext/pq_crypto_seal/pq_crypto_seal.c +511 -293
- data/ext/pq_crypto_seal/pqs_core.c +272 -0
- data/ext/pq_crypto_seal/pqs_core.h +86 -0
- data/ext/pq_crypto_seal/vendor/libaegis/LICENSE +1 -1
- data/ext/pq_crypto_seal/vendor/libaegis/TREE_SHA256 +1 -1
- data/ext/pq_crypto_seal/vendor/libaegis/src/aegis256/aegis256_common.h +5 -0
- data/ext/pq_crypto_seal/vendor/libaegis/src/aegis256/aegis256_soft.c +3 -10
- data/ext/pq_crypto_seal/vendor/libaegis/src/common/common.h +1 -1
- data/ext/pq_crypto_seal/vendor/libaegis/src/common/softaes.c +879 -118
- data/ext/pq_crypto_seal/vendor/libaegis/src/common/softaes.h +210 -9
- data/ext/pq_crypto_seal/vendor/libaegis/src/include/aegis_raf.h +26 -0
- data/lib/pq_crypto/seal/binary.rb +24 -28
- data/lib/pq_crypto/seal/core.rb +100 -172
- data/lib/pq_crypto/seal/envelope.rb +161 -95
- data/lib/pq_crypto/seal/errors.rb +8 -0
- data/lib/pq_crypto/seal/files.rb +76 -106
- data/lib/pq_crypto/seal/format.rb +133 -243
- data/lib/pq_crypto/seal/format_codecs.rb +195 -0
- data/lib/pq_crypto/seal/io.rb +40 -78
- data/lib/pq_crypto/seal/io_helpers.rb +165 -98
- data/lib/pq_crypto/seal/native.rb +1 -1
- data/lib/pq_crypto/seal/options.rb +31 -0
- data/lib/pq_crypto/seal/padding.rb +80 -142
- data/lib/pq_crypto/seal/recipients.rb +190 -128
- data/lib/pq_crypto/seal/resource_limits.rb +29 -20
- data/lib/pq_crypto/seal/secrets.rb +1 -5
- data/lib/pq_crypto/seal/streaming.rb +164 -183
- data/lib/pq_crypto/seal/version.rb +1 -1
- data/lib/pq_crypto/seal.rb +32 -26
- data/pq_crypto-seal.gemspec +33 -32
- metadata +10 -51
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ba33e05dfec6b3dc0b81bddd6a2b715f954c94ed73ea854024f2376244f8e785
|
|
4
|
+
data.tar.gz: 6c86441cbed8a97ae0014f824a194496c581578b3e894ce1731bc8ba20aa3e7c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 91f80804510c93a6a381cbf1c10f0584c2f1efe96c2a898a42c2db6f7700eaa821adedc20de95b41e42aee822ad33d8b35d25d356380f117e3b171b8cd46c270
|
|
7
|
+
data.tar.gz: 4f077ede4fa61486e9ba2925efeb626aac1dcc4a80067f5c50628c5579a94dce2683cffaaa9838a35b5399a11fb399b824d39a4b39ff0f6ad3e9b42c9582671c
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,79 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.4
|
|
4
|
+
|
|
5
|
+
Wire format v1, the public API and the error classes are unchanged. The frozen
|
|
6
|
+
golden envelope (`test/frozen_envelope_test.rb`) is byte-identical.
|
|
7
|
+
|
|
8
|
+
### Security
|
|
9
|
+
|
|
10
|
+
- **Native arguments converted before use.** `require_length` converted a
|
|
11
|
+
`#to_str` argument into a local copy only, so the caller then read
|
|
12
|
+
`RSTRING_PTR` of the original, non-String object (segfault under ASan/UBSan).
|
|
13
|
+
All arguments are now converted with `StringValue` first, then validated.
|
|
14
|
+
- **No length check before a later `#to_str` callback.** The key length was
|
|
15
|
+
validated before the nonce was converted; a nonce `#to_str` could shrink the
|
|
16
|
+
key and the following 32-byte copy read out of bounds. Validation now happens
|
|
17
|
+
only after every conversion.
|
|
18
|
+
- **Authentication error class pinned for GC compaction.** The cached
|
|
19
|
+
`AuthenticationError` VALUE was not registered with the GC; after
|
|
20
|
+
`GC.compact` raising it could crash. It is now a registered root.
|
|
21
|
+
- **AEGIS operations without the GVL use private C buffers** for the inputs and
|
|
22
|
+
output. The extension creates the Ruby result with the GVL after the operation,
|
|
23
|
+
then wipes and frees the C buffers.
|
|
24
|
+
- **Interrupts after a GVL-free section are handled.** Work runs under
|
|
25
|
+
`rb_protect`; key copies and snapshots are wiped and outputs cleared before a
|
|
26
|
+
pending `Thread#raise`/`kill` is re-raised. An interrupted or failed
|
|
27
|
+
incremental update finalizes the AEGIS state, so it can no longer emit or
|
|
28
|
+
accept a tag over data the caller never received.
|
|
29
|
+
- **AEGIS state locking uses `atomic_bool`** with acquire/release ordering, as in
|
|
30
|
+
`pq_crypto` 0.6.8. `Encryptor`/`Decryptor` cannot be `dup`ed or `clone`d.
|
|
31
|
+
- **Effective zeroization.** `Secrets.wipe!` used `String#replace`, which frees
|
|
32
|
+
the old buffer without clearing it. Wiping now goes through `Native.wipe`
|
|
33
|
+
(in-place `OPENSSL_cleanse` after `rb_str_modify`). Parsers copy fields with
|
|
34
|
+
`unpack1` instead of `byteslice`, so decrypted plaintext is not kept alive in
|
|
35
|
+
hidden copy-on-write roots, and the private-metadata copy owns its buffer.
|
|
36
|
+
- File recipient rebuilds keep rejecting trailing bytes after the envelope.
|
|
37
|
+
- Stream encryption keeps caller-owned input buffers intact. Stream decryption
|
|
38
|
+
uses the normalized chunk size after authentication.
|
|
39
|
+
- Extension built with `-fstack-protector-strong` and, when the toolchain does
|
|
40
|
+
not already define it, `-D_FORTIFY_SOURCE=2`.
|
|
41
|
+
|
|
42
|
+
### Changed
|
|
43
|
+
|
|
44
|
+
- C extension split into `pqs_core.{c,h}` and Ruby bindings. HKDF-SHA256 uses
|
|
45
|
+
OpenSSL 3 `EVP_MAC`.
|
|
46
|
+
- Vendored sources and their checksum match the pinned upstream
|
|
47
|
+
`libaegis` 0.10.3 archive.
|
|
48
|
+
- Ruby library refactored into small objects (header/section/inner codecs with a
|
|
49
|
+
declarative header layout, encryption plans, stanza sealing/opening, streaming
|
|
50
|
+
writers and readers). The public String and IO APIs retain their Ruby
|
|
51
|
+
keyword signatures.
|
|
52
|
+
- `PQC_SEAL_SANITIZE` accepts a sanitizer list (`1` still means
|
|
53
|
+
`address,undefined`).
|
|
54
|
+
- `extconf.rb` restructured into `PQCSealBuild` modules; OpenSSL selection is
|
|
55
|
+
unchanged.
|
|
56
|
+
- Development dependencies moved from the gemspec to the Gemfile.
|
|
57
|
+
- Internal helpers changed shape: `Format.split_slot(slot)` no longer takes the
|
|
58
|
+
slot size, `Format.validate_capacity!` no longer checks the recipient count
|
|
59
|
+
(`Format.validate_recipient_count!` does), `Format.parse_verified_inner` and
|
|
60
|
+
the `Binary.read_*` helpers were removed, and implementation classes that were
|
|
61
|
+
accidentally public (`OneShotEncryptor`, `OneShotOpener`, `RecipientRebuilder`,
|
|
62
|
+
`DekRotator`) are now private constants. `IOAPI::DEFAULT_CHUNK_SIZE` remains.
|
|
63
|
+
|
|
64
|
+
### Testing
|
|
65
|
+
|
|
66
|
+
- Ruby regression tests cover native arguments, GC, concurrent updates and the
|
|
67
|
+
IO cases above. CI also runs the Ruby-independent C tests under ASan and UBSan.
|
|
68
|
+
|
|
69
|
+
## 0.1.3
|
|
70
|
+
|
|
71
|
+
- Runtime dependency relaxed from `pq_crypto = 0.6.4` to `pq_crypto ~> 0.6`
|
|
72
|
+
so patch/minor releases on the 0.6 line (including 0.6.7) resolve without a
|
|
73
|
+
Seal bump. Wire suite 1 remains pinned by algorithm id and exact
|
|
74
|
+
key/ciphertext/shared-secret sizes inside Seal; do not treat this as carte
|
|
75
|
+
blanche for a future `1.x` / breaking KEM wire change.
|
|
76
|
+
|
|
3
77
|
## 0.1.2
|
|
4
78
|
|
|
5
79
|
### Security
|
data/FORMAT.md
CHANGED
|
@@ -55,7 +55,7 @@ Every complete recipient-section rebuild creates a new random section ID and
|
|
|
55
55
|
recreates all real and dummy slots. Mixed wrapping suites are forbidden.
|
|
56
56
|
|
|
57
57
|
Wrap suite `1` fixes MLKEM768-X25519/X-Wing **draft-10**-compatible encapsulation
|
|
58
|
-
(`pq_crypto
|
|
58
|
+
(`pq_crypto ~> 0.6` algorithm `:ml_kem_768_x25519_xwing`), HKDF-SHA256, AEGIS-256
|
|
59
59
|
DEK wrapping, and 32-byte wrap nonces/tags. The suite id freezes that behaviour
|
|
60
60
|
for at-rest data even if a later RFC text diverges. Exact sizes:
|
|
61
61
|
|
data/README.md
CHANGED
|
@@ -12,17 +12,17 @@ random DEK → AEGIS-256 → document
|
|
|
12
12
|
`libaegis` 0.10.3 is vendored and compiled into the extension. The existing
|
|
13
13
|
`pq_crypto` gem supplies the hybrid KEM and OpenSSL-backed primitives.
|
|
14
14
|
|
|
15
|
-
> **Status:** 0.1.
|
|
15
|
+
> **Status:** 0.1.4 is experimental cryptographic software; format v1; not
|
|
16
16
|
> independently audited. Read `SECURITY.md` before using it for irreplaceable data.
|
|
17
17
|
>
|
|
18
|
-
> `wrap_suite_id = 1` is pinned to `:ml_kem_768_x25519_xwing` and `pq_crypto
|
|
18
|
+
> `wrap_suite_id = 1` is pinned to `:ml_kem_768_x25519_xwing` and `pq_crypto ~> 0.6`
|
|
19
19
|
> (X-Wing draft-10 wire sizes). Content suite 1 is AEGIS-256 via libaegis 0.10.3.
|
|
20
20
|
|
|
21
21
|
## Installation
|
|
22
22
|
|
|
23
23
|
```ruby
|
|
24
|
-
gem "pq_crypto", "~> 0.6
|
|
25
|
-
gem "pq_crypto-seal", "~> 0.1.
|
|
24
|
+
gem "pq_crypto", "~> 0.6"
|
|
25
|
+
gem "pq_crypto-seal", "~> 0.1.4"
|
|
26
26
|
```
|
|
27
27
|
|
|
28
28
|
Ruby `>= 2.7.1` and OpenSSL `>= 3.0` development files are required for a
|
|
@@ -217,10 +217,11 @@ bundle install
|
|
|
217
217
|
bundle exec rake
|
|
218
218
|
```
|
|
219
219
|
|
|
220
|
-
Set `PQC_SEAL_SANITIZE=1`
|
|
220
|
+
Set `PQC_SEAL_SANITIZE=1` (address + undefined) or an explicit sanitizer list
|
|
221
|
+
such as `PQC_SEAL_SANITIZE=thread` when compiling the extension. The suite covers
|
|
221
222
|
AEGIS one-shot/incremental equivalence, tampering, multi-recipient opening,
|
|
222
|
-
full-envelope padding, recipient rebuilds, staged file publication,
|
|
223
|
-
limits.
|
|
223
|
+
full-envelope padding, recipient rebuilds, staged file publication, parser
|
|
224
|
+
limits, concurrent use of one AEGIS state, and argument conversion edge cases.
|
|
224
225
|
|
|
225
226
|
|
|
226
227
|
## Padding enforcement on decrypt
|
data/RELEASING.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Releasing
|
|
2
2
|
|
|
3
3
|
1. Run `bundle exec ruby script/vendor_libs.rb --check`.
|
|
4
|
-
2. Confirm `pq_crypto` dependency remains
|
|
4
|
+
2. Confirm `pq_crypto` dependency remains `~> 0.6` and `WRAP_KEM_ALGORITHM`
|
|
5
5
|
is still `:ml_kem_768_x25519_xwing` with the documented sizes.
|
|
6
6
|
3. Run `bundle exec ruby script/release_contract_check.rb` (also enforced in CI).
|
|
7
7
|
4. Run the full CI matrix: test, sanitize, fuzz, release_contract, gem-smoke.
|
|
@@ -22,15 +22,14 @@ gem; that would break the provenance guarantee. Never update the snapshot
|
|
|
22
22
|
without rerunning official KATs, cross-backend equivalence checks, envelope
|
|
23
23
|
golden vectors, and fuzz tests.
|
|
24
24
|
|
|
25
|
-
The
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
KEM ciphertext region, because X-Wing encapsulation randomness originates inside
|
|
30
|
-
`pq_crypto` and is not injectable here; the wire-contract check pins its exact
|
|
31
|
-
sizes and round-trip instead.
|
|
25
|
+
The frozen envelope test supplies a published X-Wing encapsulation result and
|
|
26
|
+
deterministic randomness for Seal. It checks the digest of the complete envelope
|
|
27
|
+
for both one-shot and streaming encryption. Other golden tests cover header
|
|
28
|
+
bytes, associated data and recipient behaviour.
|
|
32
29
|
|
|
33
30
|
The ASan job sets `detect_leaks=0` because ASan is preloaded into an otherwise
|
|
34
31
|
unsanitized Ruby interpreter; host-process allocator noise would otherwise fail
|
|
35
|
-
the job. Memory-safety errors still abort via `halt_on_error`.
|
|
32
|
+
the job. Memory-safety errors still abort via `halt_on_error`. It also sets
|
|
33
|
+
`use_sigaltstack=0`: Ruby installs its own per-thread alternate signal stack and
|
|
34
|
+
ASan would otherwise try to unmap that buffer when a thread exits.
|
|
36
35
|
|
data/SECURITY.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Security
|
|
2
2
|
|
|
3
3
|
This project has not received an independent cryptographic or implementation
|
|
4
|
-
audit. Do not treat version 0.1.
|
|
4
|
+
audit. Do not treat version 0.1.4 as a substitute for a reviewed storage design.
|
|
5
5
|
|
|
6
6
|
Experimental cryptographic software; format v1; not independently audited.
|
|
7
7
|
|
|
@@ -68,6 +68,13 @@ callers that need residual-data hygiene must clear their own buffers.
|
|
|
68
68
|
`Opened#data` / `Opened#metadata` returned from `open` are the caller's
|
|
69
69
|
responsibility after use.
|
|
70
70
|
|
|
71
|
+
Buffers the library owns (DEK, KEK, X-Wing shared secrets, the decrypted inner
|
|
72
|
+
frame, the private-metadata copy, staged plaintext chunks) are zeroized in place
|
|
73
|
+
by the C extension. Parsed fields are copied out instead of sliced, so no hidden
|
|
74
|
+
copy-on-write root keeps decrypted bytes alive. Zeroization is still best effort:
|
|
75
|
+
Ruby may have copied a string before it reached the library, and the garbage
|
|
76
|
+
collector does not clear freed memory.
|
|
77
|
+
|
|
71
78
|
|
|
72
79
|
## payload_id stability
|
|
73
80
|
|
|
@@ -128,7 +135,7 @@ independent of future RFC text:
|
|
|
128
135
|
|
|
129
136
|
| Component | Pin |
|
|
130
137
|
|---|---|
|
|
131
|
-
| `wrap_suite_id = 1` | MLKEM768-X25519 / X-Wing **draft-10** compatible via `pq_crypto
|
|
138
|
+
| `wrap_suite_id = 1` | MLKEM768-X25519 / X-Wing **draft-10** compatible via `pq_crypto ~> 0.6` algorithm `:ml_kem_768_x25519_xwing` (PK 1216, CT 1120, SS 32) |
|
|
132
139
|
| `content_suite_id = 1` | AEGIS-256, 32-byte nonce/tag, inner-frame-v1, via vendored **libaegis 0.10.3** |
|
|
133
140
|
| AEGIS KATs | CFRG AEGIS draft-18 positive/negative vectors in `test/aegis_vectors_test.rb` |
|
|
134
141
|
| X-Wing KATs | draft-10 decapsulation vectors in `test/fixtures/xwing-draft-10-vector-*.json` (see `test/xwing_kat_test.rb`) |
|
data/VENDORING.md
CHANGED
|
@@ -13,7 +13,7 @@ libaegis 0.10.3.
|
|
|
13
13
|
this snapshot, not to a future RFC that may diverge.
|
|
14
14
|
|
|
15
15
|
X-Wing / MLKEM768-X25519 wrap suite 1 is supplied by runtime dependency
|
|
16
|
-
`pq_crypto
|
|
16
|
+
`pq_crypto ~> 0.6` (not vendored here). External draft-10 decapsulation KATs
|
|
17
17
|
live in `test/fixtures/xwing-draft-10-vector-*.json`.
|
|
18
18
|
|
|
19
19
|
The complete source snapshot is retained, while the Ruby extension compiles only the AEGIS-256 and common implementation files it exposes. No system libaegis is
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
int aegis128l_pick_best_implementation(void);
|
|
2
|
+
int aegis128x2_pick_best_implementation(void);
|
|
3
|
+
int aegis128x4_pick_best_implementation(void);
|
|
4
|
+
int aegis256x2_pick_best_implementation(void);
|
|
5
|
+
int aegis256x4_pick_best_implementation(void);
|
|
6
|
+
|
|
6
7
|
int aegis128l_pick_best_implementation(void) {
|
|
7
8
|
return 0;
|
|
8
9
|
}
|