pq_crypto 0.5.2 → 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/.github/workflows/ci.yml +1 -1
- data/CHANGELOG.md +30 -0
- data/GET_STARTED.md +75 -10
- data/README.md +14 -7
- data/ext/pqcrypto/extconf.rb +7 -0
- data/ext/pqcrypto/pq_externalmu.c +23 -18
- data/ext/pqcrypto/pqcrypto_native_api.h +10 -0
- data/ext/pqcrypto/pqcrypto_ruby_secure.c +242 -70
- data/ext/pqcrypto/pqcrypto_secure.c +83 -84
- data/ext/pqcrypto/pqcrypto_secure.h +15 -10
- data/ext/pqcrypto/pqcrypto_version.h +1 -1
- data/lib/pq_crypto/hybrid_kem.rb +1 -0
- data/lib/pq_crypto/kem.rb +71 -29
- data/lib/pq_crypto/key.rb +90 -0
- data/lib/pq_crypto/pkcs8.rb +184 -10
- data/lib/pq_crypto/signature.rb +74 -37
- data/lib/pq_crypto/version.rb +1 -1
- data/lib/pq_crypto.rb +6 -4
- metadata +8 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 11bb63e90651697a30709e9621678c7a53224facc67264a331291a8c57520880
|
|
4
|
+
data.tar.gz: 111c87fa0809924f0c2997fc0d9c2ea41c43e88044c2802d35370c01ed5f88ca
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c95c38ec77fce342cb92febfbdbecdee5c35495323e7f153a2e263e04b89dc6cb13e8bd2874b8abb0b5e19e5b26cde13fb7f6b9d99ef107c5d6e3e41b20d819c
|
|
7
|
+
data.tar.gz: 1aa62a91a03203fcd6253e3175d1166b5bf2a3590889509517b8b5eaa57ff6fac49023b253f0859b45c7c2e0f4b28b849a657a5d089890b328da8a234ef7b5c9
|
data/.github/workflows/ci.yml
CHANGED
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,35 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.6.0] - 2026-05-14
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- Added seed-aware `SecretKey.from_seed` helpers for ML-KEM and ML-DSA, with PKCS#8 `:seed` / `:both` re-export when seed material is retained.
|
|
8
|
+
- Added one-shot ML-DSA `context:` support, ML-DSA-44/65/87 streaming coverage, encrypted PKCS#8, and `PQCrypto::Key.from_pem/from_der` auto-dispatch.
|
|
9
|
+
|
|
10
|
+
### Security
|
|
11
|
+
|
|
12
|
+
- Tightened secret-key lifetime handling for PKCS#8 temporary buffers, key equality, and HybridKEM expanded-key wiping.
|
|
13
|
+
|
|
14
|
+
## [0.5.3] - 2026-05-08
|
|
15
|
+
|
|
16
|
+
### Compatibility
|
|
17
|
+
|
|
18
|
+
- Lowered the minimum supported Ruby version from `>= 3.4.0` to `>= 3.1`.
|
|
19
|
+
- Kept the Ruby 3.4+ optimized `rb_nogvl(..., RB_NOGVL_OFFLOAD_SAFE)` path intact.
|
|
20
|
+
- Added explicit native build probes for `ruby/thread.h`, `rb_thread_call_without_gvl`, and `rb_nogvl`.
|
|
21
|
+
- Ruby 3.1-3.3 now build the same selected `rb_nogvl` calls with a local `PQ_RB_NOGVL_OFFLOAD_SAFE` fallback of `0`, preserving ordinary no-GVL behavior without claiming scheduler offload guarantees.
|
|
22
|
+
|
|
23
|
+
### CI
|
|
24
|
+
|
|
25
|
+
- Added Ruby 3.1-3.3 compatibility coverage as compile + smoke checks while keeping full test coverage on Ruby 3.4 and 4.0.
|
|
26
|
+
- Scoped the strict Async/Fiber Scheduler integration assertion to Ruby 3.4+ so compatibility runtimes do not claim `RB_NOGVL_OFFLOAD_SAFE` behavior.
|
|
27
|
+
- Pinned the test-only `async` dependency to the Ruby 3.1-compatible `2.21.x` line, which still contains the worker-pool support needed for the Ruby 3.4+ offload test.
|
|
28
|
+
|
|
29
|
+
### Documentation
|
|
30
|
+
|
|
31
|
+
- Documented the Ruby 3.1+ support policy and the difference between compatibility no-GVL behavior and Ruby 3.4+ scheduler-aware offload.
|
|
32
|
+
|
|
3
33
|
## [0.5.2] - 2026-05-06
|
|
4
34
|
|
|
5
35
|
### Build
|
data/GET_STARTED.md
CHANGED
|
@@ -115,6 +115,19 @@ public_key.verify!(message, signature)
|
|
|
115
115
|
# returns true, or raises on mismatch
|
|
116
116
|
```
|
|
117
117
|
|
|
118
|
+
Use `context:` when the same key is shared across domains or protocols:
|
|
119
|
+
|
|
120
|
+
```ruby
|
|
121
|
+
context = "orders-v1".b
|
|
122
|
+
signature = secret_key.sign(message, context: context)
|
|
123
|
+
|
|
124
|
+
public_key.verify(message, signature, context: context)
|
|
125
|
+
# => true
|
|
126
|
+
|
|
127
|
+
public_key.verify(message, signature, context: "other".b)
|
|
128
|
+
# => false
|
|
129
|
+
```
|
|
130
|
+
|
|
118
131
|
The same API shape applies to other supported ML-DSA parameter sets:
|
|
119
132
|
|
|
120
133
|
```ruby
|
|
@@ -125,7 +138,8 @@ PQCrypto::Signature.generate(:ml_dsa_87)
|
|
|
125
138
|
## 5. ML-DSA for large files
|
|
126
139
|
|
|
127
140
|
For large inputs, use the streaming helpers so the whole message does not need
|
|
128
|
-
to be materialized as one Ruby string.
|
|
141
|
+
to be materialized as one Ruby string. Streaming is available for
|
|
142
|
+
`:ml_dsa_44`, `:ml_dsa_65`, and `:ml_dsa_87`.
|
|
129
143
|
|
|
130
144
|
```ruby
|
|
131
145
|
keypair = PQCrypto::Signature.generate(:ml_dsa_65)
|
|
@@ -246,10 +260,19 @@ der = keypair.secret_key.to_pkcs8_der
|
|
|
246
260
|
imported = PQCrypto::KEM.secret_key_from_pkcs8_der(der)
|
|
247
261
|
```
|
|
248
262
|
|
|
249
|
-
ML-KEM PKCS#8 supports `:seed`, `:expanded`, and `:both` formats.
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
263
|
+
ML-KEM PKCS#8 supports `:seed`, `:expanded`, and `:both` formats. Generated
|
|
264
|
+
keys export `:expanded` by default. If you have 64-byte seed material, build a
|
|
265
|
+
seed-aware key to allow `:seed` and `:both` re-export:
|
|
266
|
+
|
|
267
|
+
```ruby
|
|
268
|
+
require "securerandom"
|
|
269
|
+
|
|
270
|
+
seed = SecureRandom.random_bytes(PQCrypto::PKCS8::ML_KEM_SEED_BYTES)
|
|
271
|
+
secret_key = PQCrypto::KEM.secret_key_from_seed(:ml_kem_768, seed)
|
|
272
|
+
|
|
273
|
+
pem = secret_key.to_pkcs8_pem(format: :both)
|
|
274
|
+
imported = PQCrypto::KEM.secret_key_from_pkcs8_pem(pem)
|
|
275
|
+
```
|
|
253
276
|
|
|
254
277
|
### ML-DSA PKCS#8
|
|
255
278
|
|
|
@@ -269,10 +292,48 @@ PQCrypto::PKCS8.allow_ml_dsa_seed_format = true
|
|
|
269
292
|
imported = PQCrypto::Signature.secret_key_from_pkcs8_pem(pem)
|
|
270
293
|
```
|
|
271
294
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
295
|
+
If you have 32-byte seed material, build a seed-aware key to allow `:seed` and
|
|
296
|
+
`:both` re-export:
|
|
297
|
+
|
|
298
|
+
```ruby
|
|
299
|
+
require "securerandom"
|
|
300
|
+
|
|
301
|
+
PQCrypto::PKCS8.allow_ml_dsa_seed_format = true
|
|
302
|
+
|
|
303
|
+
seed = SecureRandom.random_bytes(PQCrypto::PKCS8::ML_DSA_SEED_BYTES)
|
|
304
|
+
secret_key = PQCrypto::Signature.secret_key_from_seed(:ml_dsa_65, seed)
|
|
305
|
+
|
|
306
|
+
pem = secret_key.to_pkcs8_pem(format: :both)
|
|
307
|
+
imported = PQCrypto::Signature.secret_key_from_pkcs8_pem(pem)
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
### Encrypted PKCS#8
|
|
311
|
+
|
|
312
|
+
Pass `passphrase:` to export encrypted private keys:
|
|
313
|
+
|
|
314
|
+
```ruby
|
|
315
|
+
keypair = PQCrypto::Signature.generate(:ml_dsa_65)
|
|
316
|
+
|
|
317
|
+
pem = keypair.secret_key.to_pkcs8_pem(passphrase: "correct horse")
|
|
318
|
+
imported = PQCrypto::Signature.secret_key_from_pkcs8_pem(
|
|
319
|
+
pem,
|
|
320
|
+
passphrase: "correct horse",
|
|
321
|
+
)
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
The same option is available for DER and ML-KEM secret keys.
|
|
325
|
+
|
|
326
|
+
### Auto-dispatch key loading
|
|
327
|
+
|
|
328
|
+
Use `PQCrypto::Key` when you want the gem to detect SPKI vs PKCS#8 and the
|
|
329
|
+
algorithm family from the encoded key:
|
|
330
|
+
|
|
331
|
+
```ruby
|
|
332
|
+
key = PQCrypto::Key.from_pem(pem, passphrase: "correct horse")
|
|
333
|
+
key = PQCrypto::Key.from_der(der)
|
|
334
|
+
|
|
335
|
+
keypair = PQCrypto::Key.generate(:ml_kem_768)
|
|
336
|
+
```
|
|
276
337
|
|
|
277
338
|
## 9. pq_crypto-local container serialization
|
|
278
339
|
|
|
@@ -379,11 +440,15 @@ PQCRYPTO_NATIVE_ASM=1 bundle exec rake compile
|
|
|
379
440
|
|
|
380
441
|
## 14. Async / Fiber scheduler behavior
|
|
381
442
|
|
|
382
|
-
On Ruby 3.4, signing and verification
|
|
443
|
+
On Ruby 3.4 and later, signing and verification keep Ruby's scheduler-aware
|
|
383
444
|
`rb_nogvl(..., RB_NOGVL_OFFLOAD_SAFE)` path automatically. With a scheduler
|
|
384
445
|
that implements `blocking_operation_wait`, blocking native work can be moved
|
|
385
446
|
off the event loop.
|
|
386
447
|
|
|
448
|
+
Ruby 3.1-3.3 are supported as a compatibility path: native operations still
|
|
449
|
+
release the GVL, but `RB_NOGVL_OFFLOAD_SAFE` is not available there, so the gem
|
|
450
|
+
does not claim Fiber Scheduler offload guarantees on those runtimes.
|
|
451
|
+
|
|
387
452
|
## 15. Test-only deterministic helpers
|
|
388
453
|
|
|
389
454
|
`PQCrypto::Testing` exposes deterministic helpers for regression tests:
|
data/README.md
CHANGED
|
@@ -35,10 +35,10 @@ bundle exec rake test
|
|
|
35
35
|
|
|
36
36
|
| Area | Capabilities |
|
|
37
37
|
| --- | --- |
|
|
38
|
-
| ML-KEM | Key generation, encapsulation, decapsulation, raw key import/export, SPKI public keys, PKCS#8 private keys. |
|
|
39
|
-
| ML-DSA | Key generation,
|
|
38
|
+
| ML-KEM | Key generation, seed-aware secret keys, encapsulation, decapsulation, raw key import/export, SPKI public keys, PKCS#8 private keys. |
|
|
39
|
+
| ML-DSA | Key generation, seed-aware secret keys, signing/verification with optional FIPS 204 context, streaming signing/verification for large inputs, raw key import/export, SPKI public keys, PKCS#8 private keys. |
|
|
40
40
|
| Hybrid KEM | ML-KEM-768 + X25519 using the X-Wing combiner. |
|
|
41
|
-
| Serialization | Standard SPKI / PKCS#8 for NIST PQC keys, plus frozen `pqc_container_*` compatibility formats for the original algorithms. |
|
|
41
|
+
| Serialization | Standard SPKI / PKCS#8 for NIST PQC keys, encrypted PKCS#8 private keys, auto-dispatch key loading, plus frozen `pqc_container_*` compatibility formats for the original algorithms. |
|
|
42
42
|
| Safety helpers | Best-effort secret wiping and constant-time equality for key comparisons. |
|
|
43
43
|
| Introspection | Supported algorithm lists, algorithm metadata, backend/version helpers. |
|
|
44
44
|
|
|
@@ -63,7 +63,9 @@ original algorithms:
|
|
|
63
63
|
|
|
64
64
|
## Requirements
|
|
65
65
|
|
|
66
|
-
- Ruby 3.
|
|
66
|
+
- Ruby 3.1 or later
|
|
67
|
+
- Ruby 3.4+ keeps the optimized Fiber Scheduler offload path via `RB_NOGVL_OFFLOAD_SAFE`
|
|
68
|
+
- Ruby 3.1-3.3 use the compatibility no-GVL path without scheduler offload guarantees
|
|
67
69
|
- a C toolchain with C11 support
|
|
68
70
|
- OpenSSL 3.0 or later with SHA3-256 and SHAKE256 available
|
|
69
71
|
- vendored minimal PQ Code Package native snapshot in `ext/pqcrypto/vendor`
|
|
@@ -109,8 +111,13 @@ PQCrypto.supported_signatures
|
|
|
109
111
|
PQCrypto.supported_hybrid_kems
|
|
110
112
|
|
|
111
113
|
PQCrypto::KEM.generate(:ml_kem_768)
|
|
114
|
+
PQCrypto::KEM.secret_key_from_seed(:ml_kem_768, seed_64_bytes)
|
|
115
|
+
|
|
112
116
|
PQCrypto::Signature.generate(:ml_dsa_65)
|
|
117
|
+
PQCrypto::Signature.secret_key_from_seed(:ml_dsa_65, seed_32_bytes)
|
|
118
|
+
|
|
113
119
|
PQCrypto::HybridKEM.generate(:ml_kem_768_x25519_xwing)
|
|
120
|
+
PQCrypto::Key.from_pem(pem, passphrase: passphrase)
|
|
114
121
|
```
|
|
115
122
|
|
|
116
123
|
## More examples
|
|
@@ -119,9 +126,9 @@ Detailed usage examples live in [`GET_STARTED.md`](GET_STARTED.md):
|
|
|
119
126
|
|
|
120
127
|
- generating keys
|
|
121
128
|
- ML-KEM encapsulation / decapsulation
|
|
122
|
-
- ML-DSA signing / verification
|
|
129
|
+
- ML-DSA signing / verification with optional FIPS 204 context
|
|
123
130
|
- streaming ML-DSA for large files
|
|
124
|
-
- SPKI
|
|
131
|
+
- SPKI, PKCS#8, encrypted PKCS#8, and auto-dispatch key loading
|
|
125
132
|
- `pqc_container_*` compatibility serialization
|
|
126
133
|
- native backend / vendoring notes
|
|
127
|
-
- secure wiping and practical safety notes
|
|
134
|
+
- seed-aware keys, secure wiping, and practical safety notes
|
data/ext/pqcrypto/extconf.rb
CHANGED
|
@@ -187,6 +187,12 @@ def find_vendor_dir
|
|
|
187
187
|
candidates.find { |path| native_vendor_ready?(path) }
|
|
188
188
|
end
|
|
189
189
|
|
|
190
|
+
def configure_ruby_c_api!
|
|
191
|
+
abort "ruby/thread.h is required" unless have_header("ruby/thread.h")
|
|
192
|
+
abort "rb_thread_call_without_gvl is required" unless have_func("rb_thread_call_without_gvl", "ruby/thread.h")
|
|
193
|
+
abort "rb_nogvl is required" unless have_func("rb_nogvl", "ruby/thread.h")
|
|
194
|
+
end
|
|
195
|
+
|
|
190
196
|
def configure_openssl!
|
|
191
197
|
configure_compiler_environment
|
|
192
198
|
|
|
@@ -349,6 +355,7 @@ vendor_dir = find_vendor_dir
|
|
|
349
355
|
|
|
350
356
|
puts
|
|
351
357
|
puts "=== PQCrypto build configuration ==="
|
|
358
|
+
configure_ruby_c_api!
|
|
352
359
|
configure_openssl!
|
|
353
360
|
native_config = native_vendor_config(vendor_dir)
|
|
354
361
|
puts "OpenSSL: system"
|
|
@@ -34,57 +34,62 @@ cleanup:
|
|
|
34
34
|
return ret;
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
int pq_mldsa_extract_tr_from_secret_key(uint8_t *tr_out, const uint8_t *secret_key
|
|
38
|
-
|
|
37
|
+
int pq_mldsa_extract_tr_from_secret_key(uint8_t *tr_out, const uint8_t *secret_key,
|
|
38
|
+
size_t public_key_len,
|
|
39
|
+
int (*pk_from_sk)(uint8_t *, const uint8_t *)) {
|
|
40
|
+
uint8_t public_key[MLDSA87_PUBLICKEYBYTES];
|
|
39
41
|
int rc;
|
|
40
42
|
|
|
41
|
-
if (tr_out == NULL || secret_key == NULL
|
|
43
|
+
if (tr_out == NULL || secret_key == NULL || pk_from_sk == NULL || public_key_len == 0 ||
|
|
44
|
+
public_key_len > sizeof(public_key)) {
|
|
42
45
|
return PQ_ERROR_BUFFER;
|
|
43
46
|
}
|
|
44
47
|
|
|
45
48
|
memset(public_key, 0, sizeof(public_key));
|
|
46
|
-
rc =
|
|
49
|
+
rc = pk_from_sk(public_key, secret_key);
|
|
47
50
|
if (rc != 0) {
|
|
48
51
|
pq_secure_wipe(public_key, sizeof(public_key));
|
|
49
52
|
return PQ_ERROR_KEYPAIR;
|
|
50
53
|
}
|
|
51
54
|
|
|
52
|
-
rc = pq_shake256(tr_out, PQ_MLDSA_TRBYTES, public_key,
|
|
55
|
+
rc = pq_shake256(tr_out, PQ_MLDSA_TRBYTES, public_key, public_key_len);
|
|
53
56
|
pq_secure_wipe(public_key, sizeof(public_key));
|
|
54
57
|
return rc;
|
|
55
58
|
}
|
|
56
59
|
|
|
57
|
-
int pq_mldsa_compute_tr_from_public_key(uint8_t *tr_out, const uint8_t *public_key
|
|
60
|
+
int pq_mldsa_compute_tr_from_public_key(uint8_t *tr_out, const uint8_t *public_key,
|
|
61
|
+
size_t public_key_len) {
|
|
58
62
|
if (tr_out == NULL || public_key == NULL) {
|
|
59
63
|
return PQ_ERROR_BUFFER;
|
|
60
64
|
}
|
|
61
65
|
|
|
62
|
-
return pq_shake256(tr_out, PQ_MLDSA_TRBYTES, public_key,
|
|
66
|
+
return pq_shake256(tr_out, PQ_MLDSA_TRBYTES, public_key, public_key_len);
|
|
63
67
|
}
|
|
64
68
|
|
|
65
69
|
int pq_sign_mu(uint8_t *signature, size_t *signature_len, const uint8_t *mu,
|
|
66
|
-
const uint8_t *secret_key
|
|
67
|
-
|
|
70
|
+
const uint8_t *secret_key,
|
|
71
|
+
int (*signature_extmu)(uint8_t *, size_t *, const uint8_t *, const uint8_t *)) {
|
|
72
|
+
if (signature == NULL || signature_len == NULL || mu == NULL || secret_key == NULL ||
|
|
73
|
+
signature_extmu == NULL) {
|
|
68
74
|
return PQ_ERROR_BUFFER;
|
|
69
75
|
}
|
|
70
76
|
|
|
71
|
-
return
|
|
72
|
-
|
|
73
|
-
: PQ_ERROR_SIGN;
|
|
77
|
+
return signature_extmu(signature, signature_len, mu, secret_key) == 0 ? PQ_SUCCESS
|
|
78
|
+
: PQ_ERROR_SIGN;
|
|
74
79
|
}
|
|
75
80
|
|
|
76
81
|
int pq_verify_mu(const uint8_t *signature, size_t signature_len, const uint8_t *mu,
|
|
77
|
-
const uint8_t *public_key
|
|
78
|
-
|
|
82
|
+
const uint8_t *public_key, size_t expected_signature_len,
|
|
83
|
+
int (*verify_extmu)(const uint8_t *, size_t, const uint8_t *, const uint8_t *)) {
|
|
84
|
+
if (signature == NULL || mu == NULL || public_key == NULL || verify_extmu == NULL) {
|
|
79
85
|
return PQ_ERROR_BUFFER;
|
|
80
86
|
}
|
|
81
|
-
if (signature_len !=
|
|
87
|
+
if (signature_len != expected_signature_len) {
|
|
82
88
|
return PQ_ERROR_VERIFY;
|
|
83
89
|
}
|
|
84
90
|
|
|
85
|
-
return
|
|
86
|
-
|
|
87
|
-
: PQ_ERROR_VERIFY;
|
|
91
|
+
return verify_extmu(signature, signature_len, mu, public_key) == 0 ? PQ_SUCCESS
|
|
92
|
+
: PQ_ERROR_VERIFY;
|
|
88
93
|
}
|
|
89
94
|
|
|
90
95
|
void *pq_mu_builder_new(void) {
|
|
@@ -95,6 +95,11 @@ int pqcr_mldsa44_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, siz
|
|
|
95
95
|
size_t pqcr_mldsa44_prepare_domain_separation_prefix(
|
|
96
96
|
uint8_t prefix[MLDSA_DOMAIN_SEPARATION_MAX_BYTES], const uint8_t *ph, size_t phlen,
|
|
97
97
|
const uint8_t *ctx, size_t ctxlen, int hashalg);
|
|
98
|
+
int pqcr_mldsa44_signature_extmu(uint8_t *sig, size_t *siglen, const uint8_t mu[MLDSA_CRHBYTES],
|
|
99
|
+
const uint8_t *sk);
|
|
100
|
+
int pqcr_mldsa44_verify_extmu(const uint8_t *sig, size_t siglen, const uint8_t mu[MLDSA_CRHBYTES],
|
|
101
|
+
const uint8_t *pk);
|
|
102
|
+
int pqcr_mldsa44_pk_from_sk(uint8_t *pk, const uint8_t *sk);
|
|
98
103
|
|
|
99
104
|
int pqcr_mldsa65_keypair(uint8_t *pk, uint8_t *sk);
|
|
100
105
|
int pqcr_mldsa65_keypair_internal(uint8_t *pk, uint8_t *sk, const uint8_t seed[MLDSA_SEEDBYTES]);
|
|
@@ -128,5 +133,10 @@ int pqcr_mldsa87_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, siz
|
|
|
128
133
|
size_t pqcr_mldsa87_prepare_domain_separation_prefix(
|
|
129
134
|
uint8_t prefix[MLDSA_DOMAIN_SEPARATION_MAX_BYTES], const uint8_t *ph, size_t phlen,
|
|
130
135
|
const uint8_t *ctx, size_t ctxlen, int hashalg);
|
|
136
|
+
int pqcr_mldsa87_signature_extmu(uint8_t *sig, size_t *siglen, const uint8_t mu[MLDSA_CRHBYTES],
|
|
137
|
+
const uint8_t *sk);
|
|
138
|
+
int pqcr_mldsa87_verify_extmu(const uint8_t *sig, size_t siglen, const uint8_t mu[MLDSA_CRHBYTES],
|
|
139
|
+
const uint8_t *pk);
|
|
140
|
+
int pqcr_mldsa87_pk_from_sk(uint8_t *pk, const uint8_t *sk);
|
|
131
141
|
|
|
132
142
|
#endif
|