@omnituum/pqc-shared 0.3.0 → 0.4.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.
- package/dist/crypto/index.cjs +29 -71
- package/dist/crypto/index.d.cts +38 -45
- package/dist/crypto/index.d.ts +38 -45
- package/dist/crypto/index.js +28 -72
- package/dist/crypto/safe/index.cjs +556 -0
- package/dist/crypto/safe/index.d.cts +341 -0
- package/dist/crypto/safe/index.d.ts +341 -0
- package/dist/crypto/safe/index.js +524 -0
- package/dist/fs/index.cjs +6 -34
- package/dist/fs/index.js +6 -34
- package/dist/index.cjs +29 -71
- package/dist/index.d.cts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +28 -72
- package/dist/{integrity-CCYjrap3.d.ts → integrity-BPvNsC50.d.ts} +1 -1
- package/dist/{integrity-Dx9jukMH.d.cts → integrity-ByMp24VA.d.cts} +1 -1
- package/dist/{types-61c7Q9ri.d.ts → types-Dx_AFqow.d.cts} +54 -2
- package/dist/{types-Ch0y-n7K.d.cts → types-Dx_AFqow.d.ts} +54 -2
- package/dist/utils/index.d.cts +2 -3
- package/dist/utils/index.d.ts +2 -3
- package/dist/vault/index.cjs +13 -41
- package/dist/vault/index.d.cts +2 -3
- package/dist/vault/index.d.ts +2 -3
- package/dist/vault/index.js +13 -41
- package/package.json +27 -13
- package/src/crypto/dilithium.ts +8 -4
- package/src/crypto/hybrid.ts +13 -29
- package/src/crypto/index.ts +3 -0
- package/src/crypto/kyber.ts +63 -121
- package/src/crypto/safe/adapters.ts +306 -0
- package/src/crypto/safe/dilithium.ts +74 -0
- package/src/crypto/safe/index.ts +97 -0
- package/src/crypto/safe/kyber.ts +47 -0
- package/src/crypto/safe/manifests.ts +192 -0
- package/src/crypto/safe/secretbox.ts +24 -0
- package/src/crypto/safe/types.ts +88 -0
- package/src/crypto/safe/x25519.ts +31 -0
- package/src/index.ts +7 -4
- package/src/version.ts +9 -4
- package/dist/version-BygzPVGs.d.cts +0 -55
- package/dist/version-BygzPVGs.d.ts +0 -55
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* High-assurance adapter factories.
|
|
3
|
+
*
|
|
4
|
+
* Single-boundary, typed, invariant-checked, manifest-verified.
|
|
5
|
+
*
|
|
6
|
+
* Each factory wraps a low-level positional API into a safe object-parameter API.
|
|
7
|
+
* - Branded types prevent argument confusion at compile time.
|
|
8
|
+
* - Lazy invariant checks catch API drift at runtime.
|
|
9
|
+
* - Manifest checks verify primitive identity (key/signature sizes) to catch
|
|
10
|
+
* supply-chain substitution or silent dependency upgrades.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import type { SignatureManifest, KemManifest, DhManifest, SecretboxManifest } from './manifests'
|
|
14
|
+
|
|
15
|
+
// ---- Generic brand utility ----
|
|
16
|
+
|
|
17
|
+
type Brand<T, B extends string> = T & { readonly __brand: B }
|
|
18
|
+
|
|
19
|
+
// ---- Signature adapter ----
|
|
20
|
+
|
|
21
|
+
export type SigMessage = Brand<Uint8Array, 'SigMessage'>
|
|
22
|
+
export type SigPublicKey<Alg extends string> = Brand<Uint8Array, `${Alg}PublicKey`>
|
|
23
|
+
export type SigSecretKey<Alg extends string> = Brand<Uint8Array, `${Alg}SecretKey`>
|
|
24
|
+
export type SigSignature<Alg extends string> = Brand<Uint8Array, `${Alg}Signature`>
|
|
25
|
+
|
|
26
|
+
export type NobleSigLike = {
|
|
27
|
+
keygen(seed?: Uint8Array): { publicKey: Uint8Array; secretKey: Uint8Array }
|
|
28
|
+
sign(message: Uint8Array, secretKey: Uint8Array): Uint8Array
|
|
29
|
+
verify(signature: Uint8Array, message: Uint8Array, publicKey: Uint8Array): boolean
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function makeSignatureAdapter<Alg extends string>(
|
|
33
|
+
noble: NobleSigLike,
|
|
34
|
+
manifest: SignatureManifest,
|
|
35
|
+
) {
|
|
36
|
+
let checked = false
|
|
37
|
+
const alg = manifest.algorithm
|
|
38
|
+
|
|
39
|
+
function ensureInvariant() {
|
|
40
|
+
if (checked) return
|
|
41
|
+
const msg = new Uint8Array([0xde, 0xad, 0xbe, 0xef])
|
|
42
|
+
const { publicKey, secretKey } = noble.keygen()
|
|
43
|
+
const sig = noble.sign(msg, secretKey)
|
|
44
|
+
|
|
45
|
+
// Manifest size checks — verify primitive identity
|
|
46
|
+
if (publicKey.length !== manifest.publicKeyBytes) {
|
|
47
|
+
throw new Error(`${alg}: publicKey ${publicKey.length}B, expected ${manifest.publicKeyBytes}B`)
|
|
48
|
+
}
|
|
49
|
+
if (secretKey.length !== manifest.secretKeyBytes) {
|
|
50
|
+
throw new Error(`${alg}: secretKey ${secretKey.length}B, expected ${manifest.secretKeyBytes}B`)
|
|
51
|
+
}
|
|
52
|
+
if (sig.length !== manifest.signatureBytes) {
|
|
53
|
+
throw new Error(`${alg}: signature ${sig.length}B, expected ${manifest.signatureBytes}B`)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Behavioral roundtrip
|
|
57
|
+
if (!noble.verify(sig, msg, publicKey)) {
|
|
58
|
+
throw new Error(`${alg}: sign/verify roundtrip failed`)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
checked = true
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return {
|
|
65
|
+
keygen(): { publicKey: SigPublicKey<Alg>; secretKey: SigSecretKey<Alg> } {
|
|
66
|
+
ensureInvariant()
|
|
67
|
+
const kp = noble.keygen()
|
|
68
|
+
return {
|
|
69
|
+
publicKey: kp.publicKey as SigPublicKey<Alg>,
|
|
70
|
+
secretKey: kp.secretKey as SigSecretKey<Alg>,
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
|
|
74
|
+
sign(params: {
|
|
75
|
+
message: SigMessage
|
|
76
|
+
secretKey: SigSecretKey<Alg>
|
|
77
|
+
}): SigSignature<Alg> {
|
|
78
|
+
ensureInvariant()
|
|
79
|
+
return noble.sign(params.message, params.secretKey) as SigSignature<Alg>
|
|
80
|
+
},
|
|
81
|
+
|
|
82
|
+
verify(params: {
|
|
83
|
+
signature: SigSignature<Alg>
|
|
84
|
+
message: SigMessage
|
|
85
|
+
publicKey: SigPublicKey<Alg>
|
|
86
|
+
}): boolean {
|
|
87
|
+
ensureInvariant()
|
|
88
|
+
return noble.verify(params.signature, params.message, params.publicKey)
|
|
89
|
+
},
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export function asSigMessage(v: Uint8Array): SigMessage {
|
|
94
|
+
return v as SigMessage
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// ---- KEM adapter ----
|
|
98
|
+
|
|
99
|
+
export type KemEncapsKey<Alg extends string> = Brand<Uint8Array, `${Alg}EncapsKey`>
|
|
100
|
+
export type KemDecapsKey<Alg extends string> = Brand<Uint8Array, `${Alg}DecapsKey`>
|
|
101
|
+
export type KemCiphertext<Alg extends string> = Brand<Uint8Array, `${Alg}Ciphertext`>
|
|
102
|
+
export type KemSharedSecret = Brand<Uint8Array, 'KemSharedSecret'>
|
|
103
|
+
|
|
104
|
+
export type NobleKemLike = {
|
|
105
|
+
keygen(): { publicKey: Uint8Array; secretKey: Uint8Array }
|
|
106
|
+
encapsulate(publicKey: Uint8Array): { ciphertext: Uint8Array; sharedSecret: Uint8Array }
|
|
107
|
+
decapsulate(ciphertext: Uint8Array, secretKey: Uint8Array): Uint8Array
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export function makeKemAdapter<Alg extends string>(
|
|
111
|
+
noble: NobleKemLike,
|
|
112
|
+
manifest: KemManifest,
|
|
113
|
+
) {
|
|
114
|
+
let checked = false
|
|
115
|
+
const alg = manifest.algorithm
|
|
116
|
+
|
|
117
|
+
function ensureInvariant() {
|
|
118
|
+
if (checked) return
|
|
119
|
+
const { publicKey, secretKey } = noble.keygen()
|
|
120
|
+
const { ciphertext, sharedSecret: ss1 } = noble.encapsulate(publicKey)
|
|
121
|
+
const ss2 = noble.decapsulate(ciphertext, secretKey)
|
|
122
|
+
|
|
123
|
+
// Manifest size checks
|
|
124
|
+
if (publicKey.length !== manifest.encapsulationKeyBytes) {
|
|
125
|
+
throw new Error(`${alg}: encapsKey ${publicKey.length}B, expected ${manifest.encapsulationKeyBytes}B`)
|
|
126
|
+
}
|
|
127
|
+
if (secretKey.length !== manifest.decapsulationKeyBytes) {
|
|
128
|
+
throw new Error(`${alg}: decapsKey ${secretKey.length}B, expected ${manifest.decapsulationKeyBytes}B`)
|
|
129
|
+
}
|
|
130
|
+
if (ciphertext.length !== manifest.ciphertextBytes) {
|
|
131
|
+
throw new Error(`${alg}: ciphertext ${ciphertext.length}B, expected ${manifest.ciphertextBytes}B`)
|
|
132
|
+
}
|
|
133
|
+
if (ss1.length !== manifest.sharedSecretBytes) {
|
|
134
|
+
throw new Error(`${alg}: sharedSecret ${ss1.length}B, expected ${manifest.sharedSecretBytes}B`)
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Behavioral roundtrip
|
|
138
|
+
if (ss2.length !== ss1.length) {
|
|
139
|
+
throw new Error(`${alg}: encap/decap shared secret length mismatch`)
|
|
140
|
+
}
|
|
141
|
+
for (let i = 0; i < ss1.length; i++) {
|
|
142
|
+
if (ss1[i] !== ss2[i]) throw new Error(`${alg}: encap/decap shared secrets differ`)
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
checked = true
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return {
|
|
149
|
+
keygen(): { encapsulationKey: KemEncapsKey<Alg>; decapsulationKey: KemDecapsKey<Alg> } {
|
|
150
|
+
ensureInvariant()
|
|
151
|
+
const kp = noble.keygen()
|
|
152
|
+
return {
|
|
153
|
+
encapsulationKey: kp.publicKey as KemEncapsKey<Alg>,
|
|
154
|
+
decapsulationKey: kp.secretKey as KemDecapsKey<Alg>,
|
|
155
|
+
}
|
|
156
|
+
},
|
|
157
|
+
|
|
158
|
+
encapsulate(params: {
|
|
159
|
+
encapsulationKey: KemEncapsKey<Alg>
|
|
160
|
+
}): { ciphertext: KemCiphertext<Alg>; sharedSecret: KemSharedSecret } {
|
|
161
|
+
ensureInvariant()
|
|
162
|
+
const result = noble.encapsulate(params.encapsulationKey)
|
|
163
|
+
return {
|
|
164
|
+
ciphertext: result.ciphertext as KemCiphertext<Alg>,
|
|
165
|
+
sharedSecret: result.sharedSecret as KemSharedSecret,
|
|
166
|
+
}
|
|
167
|
+
},
|
|
168
|
+
|
|
169
|
+
decapsulate(params: {
|
|
170
|
+
ciphertext: KemCiphertext<Alg>
|
|
171
|
+
decapsulationKey: KemDecapsKey<Alg>
|
|
172
|
+
}): KemSharedSecret {
|
|
173
|
+
ensureInvariant()
|
|
174
|
+
return noble.decapsulate(params.ciphertext, params.decapsulationKey) as KemSharedSecret
|
|
175
|
+
},
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// ---- DH adapter ----
|
|
180
|
+
|
|
181
|
+
export type DhPublicKey<Alg extends string> = Brand<Uint8Array, `${Alg}PublicKey`>
|
|
182
|
+
export type DhSecretKey<Alg extends string> = Brand<Uint8Array, `${Alg}SecretKey`>
|
|
183
|
+
export type DhSharedSecret = Brand<Uint8Array, 'DhSharedSecret'>
|
|
184
|
+
|
|
185
|
+
export type NobleDhLike = {
|
|
186
|
+
getPublicKey(secretKey: Uint8Array): Uint8Array
|
|
187
|
+
getSharedSecret(secretKey: Uint8Array, publicKey: Uint8Array): Uint8Array
|
|
188
|
+
utils: { randomPrivateKey(): Uint8Array }
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
export function makeDhAdapter<Alg extends string>(
|
|
192
|
+
noble: NobleDhLike,
|
|
193
|
+
manifest: DhManifest,
|
|
194
|
+
) {
|
|
195
|
+
let checked = false
|
|
196
|
+
const alg = manifest.algorithm
|
|
197
|
+
|
|
198
|
+
function ensureInvariant() {
|
|
199
|
+
if (checked) return
|
|
200
|
+
const sk = noble.utils.randomPrivateKey()
|
|
201
|
+
const pk = noble.getPublicKey(sk)
|
|
202
|
+
|
|
203
|
+
if (pk.length !== manifest.publicKeyBytes) {
|
|
204
|
+
throw new Error(`${alg}: publicKey ${pk.length}B, expected ${manifest.publicKeyBytes}B`)
|
|
205
|
+
}
|
|
206
|
+
if (sk.length !== manifest.secretKeyBytes) {
|
|
207
|
+
throw new Error(`${alg}: secretKey ${sk.length}B, expected ${manifest.secretKeyBytes}B`)
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// DH commutativity check
|
|
211
|
+
const sk2 = noble.utils.randomPrivateKey()
|
|
212
|
+
const pk2 = noble.getPublicKey(sk2)
|
|
213
|
+
const ss1 = noble.getSharedSecret(sk, pk2)
|
|
214
|
+
const ss2 = noble.getSharedSecret(sk2, pk)
|
|
215
|
+
|
|
216
|
+
if (ss1.length !== manifest.sharedSecretBytes) {
|
|
217
|
+
throw new Error(`${alg}: sharedSecret ${ss1.length}B, expected ${manifest.sharedSecretBytes}B`)
|
|
218
|
+
}
|
|
219
|
+
for (let i = 0; i < ss1.length; i++) {
|
|
220
|
+
if (ss1[i] !== ss2[i]) throw new Error(`${alg}: DH commutativity failed`)
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
checked = true
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
return {
|
|
227
|
+
keygen(): { publicKey: DhPublicKey<Alg>; secretKey: DhSecretKey<Alg> } {
|
|
228
|
+
ensureInvariant()
|
|
229
|
+
const secretKey = noble.utils.randomPrivateKey()
|
|
230
|
+
const publicKey = noble.getPublicKey(secretKey)
|
|
231
|
+
return {
|
|
232
|
+
publicKey: publicKey as DhPublicKey<Alg>,
|
|
233
|
+
secretKey: secretKey as DhSecretKey<Alg>,
|
|
234
|
+
}
|
|
235
|
+
},
|
|
236
|
+
|
|
237
|
+
sharedSecret(params: {
|
|
238
|
+
ourSecretKey: DhSecretKey<Alg>
|
|
239
|
+
theirPublicKey: DhPublicKey<Alg>
|
|
240
|
+
}): DhSharedSecret {
|
|
241
|
+
ensureInvariant()
|
|
242
|
+
return noble.getSharedSecret(params.ourSecretKey, params.theirPublicKey) as DhSharedSecret
|
|
243
|
+
},
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// ---- Secretbox adapter ----
|
|
248
|
+
|
|
249
|
+
export type BoxKey = Brand<Uint8Array, 'BoxKey'>
|
|
250
|
+
export type BoxNonce = Brand<Uint8Array, 'BoxNonce'>
|
|
251
|
+
|
|
252
|
+
export function makeSecretboxAdapter(
|
|
253
|
+
impl: {
|
|
254
|
+
seal: (key: Uint8Array, plaintext: Uint8Array, nonce: Uint8Array) => Uint8Array
|
|
255
|
+
open: (key: Uint8Array, ciphertext: Uint8Array, nonce: Uint8Array) => Uint8Array | null
|
|
256
|
+
},
|
|
257
|
+
manifest: SecretboxManifest,
|
|
258
|
+
) {
|
|
259
|
+
let checked = false
|
|
260
|
+
const alg = manifest.algorithm
|
|
261
|
+
|
|
262
|
+
function ensureInvariant() {
|
|
263
|
+
if (checked) return
|
|
264
|
+
const key = new Uint8Array(manifest.keyBytes)
|
|
265
|
+
crypto.getRandomValues(key)
|
|
266
|
+
const nonce = new Uint8Array(manifest.nonceBytes)
|
|
267
|
+
crypto.getRandomValues(nonce)
|
|
268
|
+
const plaintext = new Uint8Array([0xca, 0xfe, 0xba, 0xbe])
|
|
269
|
+
|
|
270
|
+
const ct = impl.seal(key, plaintext, nonce)
|
|
271
|
+
const overhead = ct.length - plaintext.length
|
|
272
|
+
if (overhead !== manifest.tagBytes) {
|
|
273
|
+
throw new Error(`${alg}: overhead ${overhead}B, expected ${manifest.tagBytes}B tag`)
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
const pt = impl.open(key, ct, nonce)
|
|
277
|
+
if (!pt || pt.length !== plaintext.length) {
|
|
278
|
+
throw new Error(`${alg}: seal/open roundtrip failed`)
|
|
279
|
+
}
|
|
280
|
+
for (let i = 0; i < plaintext.length; i++) {
|
|
281
|
+
if (pt[i] !== plaintext[i]) throw new Error(`${alg}: seal/open roundtrip mismatch`)
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
checked = true
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
return {
|
|
288
|
+
seal(params: { key: BoxKey; plaintext: Uint8Array; nonce: BoxNonce }): Uint8Array {
|
|
289
|
+
ensureInvariant()
|
|
290
|
+
return impl.seal(params.key, params.plaintext, params.nonce)
|
|
291
|
+
},
|
|
292
|
+
|
|
293
|
+
open(params: { key: BoxKey; ciphertext: Uint8Array; nonce: BoxNonce }): Uint8Array | null {
|
|
294
|
+
ensureInvariant()
|
|
295
|
+
return impl.open(params.key, params.ciphertext, params.nonce)
|
|
296
|
+
},
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
export function asBoxKey(v: Uint8Array): BoxKey {
|
|
301
|
+
return v as BoxKey
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
export function asBoxNonce(v: Uint8Array): BoxNonce {
|
|
305
|
+
return v as BoxNonce
|
|
306
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Safe Dilithium ML-DSA-65 adapter.
|
|
3
|
+
*
|
|
4
|
+
* Object parameters + branded types + manifest verification.
|
|
5
|
+
* - Argument inversion is a compile-time error.
|
|
6
|
+
* - Primitive identity verified on first use (key/sig sizes match manifest).
|
|
7
|
+
* - Behavioral roundtrip confirmed before any real operation.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type {
|
|
11
|
+
DilithiumKeyPair,
|
|
12
|
+
DilithiumSecretKey,
|
|
13
|
+
DilithiumPublicKey,
|
|
14
|
+
DilithiumSignature,
|
|
15
|
+
Message,
|
|
16
|
+
} from './types'
|
|
17
|
+
import { ML_DSA_65, assertSignaturePrimitive } from './manifests'
|
|
18
|
+
|
|
19
|
+
let _mod: any = null
|
|
20
|
+
let _invariantChecked = false
|
|
21
|
+
|
|
22
|
+
async function load(): Promise<any> {
|
|
23
|
+
if (!_mod) {
|
|
24
|
+
const { ml_dsa65 } = await import('@noble/post-quantum/ml-dsa.js')
|
|
25
|
+
_mod = ml_dsa65
|
|
26
|
+
}
|
|
27
|
+
return _mod
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Run once on first use. Verifies:
|
|
32
|
+
* 1. Key and signature sizes match ML-DSA-65 manifest
|
|
33
|
+
* 2. sign/verify roundtrip produces correct result
|
|
34
|
+
* Catches both argument order bugs and supply-chain primitive substitution.
|
|
35
|
+
*/
|
|
36
|
+
async function checkInvariant(): Promise<void> {
|
|
37
|
+
if (_invariantChecked) return
|
|
38
|
+
const mod = await load()
|
|
39
|
+
assertSignaturePrimitive(mod, ML_DSA_65)
|
|
40
|
+
_invariantChecked = true
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export async function keygen(): Promise<DilithiumKeyPair> {
|
|
44
|
+
const mod = await load()
|
|
45
|
+
await checkInvariant()
|
|
46
|
+
const kp = mod.keygen()
|
|
47
|
+
return {
|
|
48
|
+
publicKey: kp.publicKey as DilithiumPublicKey,
|
|
49
|
+
secretKey: kp.secretKey as DilithiumSecretKey,
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export async function sign(params: {
|
|
54
|
+
message: Message
|
|
55
|
+
secretKey: DilithiumSecretKey
|
|
56
|
+
}): Promise<DilithiumSignature> {
|
|
57
|
+
const mod = await load()
|
|
58
|
+
await checkInvariant()
|
|
59
|
+
return mod.sign(params.message, params.secretKey) as DilithiumSignature
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export async function verify(params: {
|
|
63
|
+
signature: DilithiumSignature
|
|
64
|
+
message: Message
|
|
65
|
+
publicKey: DilithiumPublicKey
|
|
66
|
+
}): Promise<boolean> {
|
|
67
|
+
const mod = await load()
|
|
68
|
+
await checkInvariant()
|
|
69
|
+
try {
|
|
70
|
+
return mod.verify(params.signature, params.message, params.publicKey)
|
|
71
|
+
} catch {
|
|
72
|
+
return false
|
|
73
|
+
}
|
|
74
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @omnituum/pqc-shared/safe — Type-safe crypto adapter layer.
|
|
3
|
+
*
|
|
4
|
+
* All functions use branded types and object parameters.
|
|
5
|
+
* Argument inversion is a compile-time error.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* import { dilithium, kyber, x25519, secretbox } from '@omnituum/pqc-shared/safe'
|
|
9
|
+
*
|
|
10
|
+
* const kp = await dilithium.keygen()
|
|
11
|
+
* const sig = await dilithium.sign({ message: msg, secretKey: kp.secretKey })
|
|
12
|
+
* const ok = await dilithium.verify({ signature: sig, message: msg, publicKey: kp.publicKey })
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
export * as dilithium from './dilithium'
|
|
16
|
+
export * as kyber from './kyber'
|
|
17
|
+
export * as x25519 from './x25519'
|
|
18
|
+
export * as secretbox from './secretbox'
|
|
19
|
+
|
|
20
|
+
export type {
|
|
21
|
+
DilithiumSecretKey,
|
|
22
|
+
DilithiumPublicKey,
|
|
23
|
+
DilithiumSignature,
|
|
24
|
+
DilithiumKeyPair,
|
|
25
|
+
KyberEncapsulationKey,
|
|
26
|
+
KyberDecapsulationKey,
|
|
27
|
+
KyberCiphertext,
|
|
28
|
+
KyberKeyPair,
|
|
29
|
+
KyberEncapsulation,
|
|
30
|
+
SharedSecret,
|
|
31
|
+
X25519PublicKey,
|
|
32
|
+
X25519SecretKey,
|
|
33
|
+
X25519KeyPair,
|
|
34
|
+
SymmetricKey,
|
|
35
|
+
Nonce,
|
|
36
|
+
Message,
|
|
37
|
+
} from './types'
|
|
38
|
+
|
|
39
|
+
export {
|
|
40
|
+
asMessage,
|
|
41
|
+
asDilithiumSecretKey,
|
|
42
|
+
asDilithiumPublicKey,
|
|
43
|
+
asKyberEncapsulationKey,
|
|
44
|
+
asKyberDecapsulationKey,
|
|
45
|
+
asX25519PublicKey,
|
|
46
|
+
asX25519SecretKey,
|
|
47
|
+
asSymmetricKey,
|
|
48
|
+
asNonce,
|
|
49
|
+
} from './types'
|
|
50
|
+
|
|
51
|
+
// Adapter factories — for building new type-safe wrappers around any noble-like API
|
|
52
|
+
export {
|
|
53
|
+
makeSignatureAdapter,
|
|
54
|
+
makeKemAdapter,
|
|
55
|
+
makeDhAdapter,
|
|
56
|
+
makeSecretboxAdapter,
|
|
57
|
+
asSigMessage,
|
|
58
|
+
asBoxKey,
|
|
59
|
+
asBoxNonce,
|
|
60
|
+
} from './adapters'
|
|
61
|
+
|
|
62
|
+
export type {
|
|
63
|
+
NobleSigLike,
|
|
64
|
+
NobleKemLike,
|
|
65
|
+
NobleDhLike,
|
|
66
|
+
SigMessage,
|
|
67
|
+
SigPublicKey,
|
|
68
|
+
SigSecretKey,
|
|
69
|
+
SigSignature,
|
|
70
|
+
KemEncapsKey,
|
|
71
|
+
KemDecapsKey,
|
|
72
|
+
KemCiphertext,
|
|
73
|
+
KemSharedSecret,
|
|
74
|
+
DhPublicKey,
|
|
75
|
+
DhSecretKey,
|
|
76
|
+
DhSharedSecret,
|
|
77
|
+
BoxKey,
|
|
78
|
+
BoxNonce,
|
|
79
|
+
} from './adapters'
|
|
80
|
+
|
|
81
|
+
// Manifests — primitive identity declarations for supply-chain verification
|
|
82
|
+
export {
|
|
83
|
+
ML_DSA_65,
|
|
84
|
+
ML_KEM_768,
|
|
85
|
+
X25519,
|
|
86
|
+
XSALSA20_POLY1305,
|
|
87
|
+
assertSignaturePrimitive,
|
|
88
|
+
assertKemPrimitive,
|
|
89
|
+
assertDhPrimitive,
|
|
90
|
+
} from './manifests'
|
|
91
|
+
|
|
92
|
+
export type {
|
|
93
|
+
SignatureManifest,
|
|
94
|
+
KemManifest,
|
|
95
|
+
DhManifest,
|
|
96
|
+
SecretboxManifest,
|
|
97
|
+
} from './manifests'
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Safe Kyber ML-KEM-768 adapter.
|
|
3
|
+
*
|
|
4
|
+
* Object parameters + branded types.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { toB64, fromB64 } from '../primitives'
|
|
8
|
+
import {
|
|
9
|
+
kyberEncapsulate as rawEncapsulate,
|
|
10
|
+
kyberDecapsulate as rawDecapsulate,
|
|
11
|
+
generateKyberKeypair as rawKeygen,
|
|
12
|
+
} from '../kyber'
|
|
13
|
+
import type {
|
|
14
|
+
KyberKeyPair,
|
|
15
|
+
KyberEncapsulationKey,
|
|
16
|
+
KyberDecapsulationKey,
|
|
17
|
+
KyberCiphertext,
|
|
18
|
+
KyberEncapsulation,
|
|
19
|
+
SharedSecret,
|
|
20
|
+
} from './types'
|
|
21
|
+
|
|
22
|
+
export async function keygen(): Promise<KyberKeyPair | null> {
|
|
23
|
+
const kp = await rawKeygen()
|
|
24
|
+
if (!kp) return null
|
|
25
|
+
return {
|
|
26
|
+
encapsulationKey: fromB64(kp.publicB64) as KyberEncapsulationKey,
|
|
27
|
+
decapsulationKey: fromB64(kp.secretB64) as KyberDecapsulationKey,
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export async function encapsulate(params: {
|
|
32
|
+
encapsulationKey: KyberEncapsulationKey
|
|
33
|
+
}): Promise<KyberEncapsulation> {
|
|
34
|
+
const result = await rawEncapsulate(toB64(params.encapsulationKey))
|
|
35
|
+
return {
|
|
36
|
+
ciphertext: result.ciphertext as KyberCiphertext,
|
|
37
|
+
sharedSecret: result.sharedSecret as SharedSecret,
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export async function decapsulate(params: {
|
|
42
|
+
ciphertext: KyberCiphertext
|
|
43
|
+
decapsulationKey: KyberDecapsulationKey
|
|
44
|
+
}): Promise<SharedSecret> {
|
|
45
|
+
const ss = await rawDecapsulate(toB64(params.ciphertext), toB64(params.decapsulationKey))
|
|
46
|
+
return ss as SharedSecret
|
|
47
|
+
}
|