@kokuin/token 0.1.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/README.md +7 -0
- package/lib/cache.d.ts +23 -0
- package/lib/cache.js +41 -0
- package/lib/did.d.ts +39 -0
- package/lib/did.js +146 -0
- package/lib/identity.d.ts +119 -0
- package/lib/identity.js +344 -0
- package/lib/index.d.ts +27 -0
- package/lib/index.js +23 -0
- package/lib/jwe.d.ts +67 -0
- package/lib/jwe.js +262 -0
- package/lib/keystore.d.ts +10 -0
- package/lib/keystore.js +1 -0
- package/lib/multibase.d.ts +4 -0
- package/lib/multibase.js +36 -0
- package/lib/peer4.d.ts +112 -0
- package/lib/peer4.js +158 -0
- package/lib/rotation.d.ts +15 -0
- package/lib/rotation.js +12 -0
- package/lib/schemas.d.ts +161 -0
- package/lib/schemas.js +96 -0
- package/lib/signer.d.ts +6 -0
- package/lib/signer.js +6 -0
- package/lib/time.d.ts +29 -0
- package/lib/time.js +18 -0
- package/lib/token.d.ts +53 -0
- package/lib/token.js +181 -0
- package/lib/types.d.ts +17 -0
- package/lib/types.js +1 -0
- package/lib/utils.d.ts +6 -0
- package/lib/utils.js +19 -0
- package/lib/verifier.d.ts +9 -0
- package/lib/verifier.js +19 -0
- package/package.json +49 -0
package/lib/identity.js
ADDED
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
import { ed25519, x25519 } from '@noble/curves/ed25519.js';
|
|
2
|
+
import { b64uFromJSON, fromUTF, toB64U } from '@sozai/codec';
|
|
3
|
+
import { AttributeKeys, createTracer, SpanNames, withSpan } from '@sozai/otel';
|
|
4
|
+
import { CODECS, getDID, normalizeDID } from './did.js';
|
|
5
|
+
import { decryptToken } from './jwe.js';
|
|
6
|
+
import { encodeMultibase } from './multibase.js';
|
|
7
|
+
import { encodePeer4, isPeer4 } from './peer4.js';
|
|
8
|
+
import { concatBytes } from './utils.js';
|
|
9
|
+
const tracer = createTracer('token');
|
|
10
|
+
export function isSigningIdentity(identity) {
|
|
11
|
+
return 'publicKey' in identity && 'signToken' in identity && typeof identity.signToken === 'function';
|
|
12
|
+
}
|
|
13
|
+
export function isDecryptingIdentity(identity) {
|
|
14
|
+
return 'decrypt' in identity && typeof identity.decrypt === 'function' && 'agreeKey' in identity && typeof identity.agreeKey === 'function';
|
|
15
|
+
}
|
|
16
|
+
export function isFullIdentity(identity) {
|
|
17
|
+
return isSigningIdentity(identity) && isDecryptingIdentity(identity);
|
|
18
|
+
}
|
|
19
|
+
export function isOwnIdentity(identity) {
|
|
20
|
+
return isFullIdentity(identity) && 'privateKey' in identity;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Create a signing identity from an Ed25519 private key.
|
|
24
|
+
*/ export function createSigningIdentity(privateKey) {
|
|
25
|
+
const publicKey = ed25519.getPublicKey(privateKey);
|
|
26
|
+
const id = getDID(CODECS.EdDSA, publicKey);
|
|
27
|
+
async function signToken(payload, options = {}) {
|
|
28
|
+
return withSpan(tracer, SpanNames.TOKEN_SIGN, {
|
|
29
|
+
attributes: {
|
|
30
|
+
[AttributeKeys.AUTH_DID]: id,
|
|
31
|
+
[AttributeKeys.AUTH_ALGORITHM]: 'EdDSA'
|
|
32
|
+
}
|
|
33
|
+
}, async ()=>{
|
|
34
|
+
if (payload.iss != null && payload.iss !== id) {
|
|
35
|
+
throw new Error('Invalid payload: issuer does not match signer');
|
|
36
|
+
}
|
|
37
|
+
const fullHeader = {
|
|
38
|
+
...options.header ?? {},
|
|
39
|
+
typ: 'JWT',
|
|
40
|
+
alg: 'EdDSA'
|
|
41
|
+
};
|
|
42
|
+
const fullPayload = {
|
|
43
|
+
...payload,
|
|
44
|
+
iss: id
|
|
45
|
+
};
|
|
46
|
+
const data = `${b64uFromJSON(fullHeader)}.${b64uFromJSON(fullPayload)}`;
|
|
47
|
+
return {
|
|
48
|
+
header: fullHeader,
|
|
49
|
+
payload: fullPayload,
|
|
50
|
+
signature: toB64U(ed25519.sign(fromUTF(data), privateKey)),
|
|
51
|
+
data
|
|
52
|
+
};
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
return {
|
|
56
|
+
id,
|
|
57
|
+
publicKey,
|
|
58
|
+
signToken
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Create a decrypting identity from an Ed25519 private key.
|
|
63
|
+
* Uses X25519 key derivation for ECDH key agreement.
|
|
64
|
+
*/ export function createDecryptingIdentity(privateKey) {
|
|
65
|
+
const publicKey = ed25519.getPublicKey(privateKey);
|
|
66
|
+
const id = getDID(CODECS.EdDSA, publicKey);
|
|
67
|
+
const x25519Private = ed25519.utils.toMontgomerySecret(privateKey);
|
|
68
|
+
async function decrypt(jwe) {
|
|
69
|
+
return decryptToken({
|
|
70
|
+
id,
|
|
71
|
+
decrypt,
|
|
72
|
+
agreeKey
|
|
73
|
+
}, jwe);
|
|
74
|
+
}
|
|
75
|
+
async function agreeKey(ephemeralPublicKey) {
|
|
76
|
+
return x25519.getSharedSecret(x25519Private, ephemeralPublicKey);
|
|
77
|
+
}
|
|
78
|
+
return {
|
|
79
|
+
id,
|
|
80
|
+
decrypt,
|
|
81
|
+
agreeKey
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Create a full identity (signing + decrypting) from an Ed25519 private key.
|
|
86
|
+
*/ export function createFullIdentity(privateKey) {
|
|
87
|
+
const signing = createSigningIdentity(privateKey);
|
|
88
|
+
const decrypting = createDecryptingIdentity(privateKey);
|
|
89
|
+
return {
|
|
90
|
+
...signing,
|
|
91
|
+
...decrypting
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Generate a random identity with a new Ed25519 private key.
|
|
96
|
+
*/ export function randomIdentity() {
|
|
97
|
+
const privateKey = ed25519.utils.randomSecretKey();
|
|
98
|
+
return {
|
|
99
|
+
...createFullIdentity(privateKey),
|
|
100
|
+
privateKey
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
const CODEC_ED25519_PUB = new Uint8Array([
|
|
104
|
+
0xed,
|
|
105
|
+
0x01
|
|
106
|
+
]);
|
|
107
|
+
const CODEC_X25519_PUB = new Uint8Array([
|
|
108
|
+
0xec,
|
|
109
|
+
0x01
|
|
110
|
+
]);
|
|
111
|
+
function codecFor(alg) {
|
|
112
|
+
switch(alg){
|
|
113
|
+
case 'EdDSA':
|
|
114
|
+
return CODEC_ED25519_PUB;
|
|
115
|
+
case 'X25519':
|
|
116
|
+
return CODEC_X25519_PUB;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
function publicKeyMultibase(alg, publicKey) {
|
|
120
|
+
return encodeMultibase(concatBytes(codecFor(alg), publicKey));
|
|
121
|
+
}
|
|
122
|
+
function generateKeyPair(alg, providedPrivate) {
|
|
123
|
+
switch(alg){
|
|
124
|
+
case 'EdDSA':
|
|
125
|
+
{
|
|
126
|
+
const priv = providedPrivate ?? ed25519.utils.randomSecretKey();
|
|
127
|
+
return {
|
|
128
|
+
privateKey: priv,
|
|
129
|
+
publicKey: ed25519.getPublicKey(priv)
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
case 'X25519':
|
|
133
|
+
{
|
|
134
|
+
const priv = providedPrivate ?? x25519.utils.randomSecretKey();
|
|
135
|
+
return {
|
|
136
|
+
privateKey: priv,
|
|
137
|
+
publicKey: x25519.getPublicKey(priv)
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
function isClassical(spec) {
|
|
143
|
+
return spec.alg === 'EdDSA' || spec.alg === 'X25519';
|
|
144
|
+
}
|
|
145
|
+
function chooseMethod(input) {
|
|
146
|
+
if (input.didMethod != null) {
|
|
147
|
+
if (input.didMethod === 'key') {
|
|
148
|
+
if (input.keys.length !== 1) {
|
|
149
|
+
throw new Error('IdentityError.InvalidMethod: did:key requires exactly one key');
|
|
150
|
+
}
|
|
151
|
+
if (!isClassical(input.keys[0])) {
|
|
152
|
+
throw new Error('IdentityError.InvalidMethod: did:key requires a classical algorithm');
|
|
153
|
+
}
|
|
154
|
+
if (input.keys[0].purpose !== 'sig') {
|
|
155
|
+
throw new Error('IdentityError.InvalidMethod: did:key requires a signing key');
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return input.didMethod;
|
|
159
|
+
}
|
|
160
|
+
if (input.keys.length === 1 && isClassical(input.keys[0]) && input.keys[0].purpose === 'sig') {
|
|
161
|
+
return 'key';
|
|
162
|
+
}
|
|
163
|
+
return 'peer:4';
|
|
164
|
+
}
|
|
165
|
+
function resolveKeys(input) {
|
|
166
|
+
return input.keys.map((spec, i)=>{
|
|
167
|
+
const { privateKey, publicKey } = generateKeyPair(spec.alg, spec.privateKey);
|
|
168
|
+
return {
|
|
169
|
+
fragment: `#key-${i}`,
|
|
170
|
+
alg: spec.alg,
|
|
171
|
+
purpose: spec.purpose,
|
|
172
|
+
privateKey,
|
|
173
|
+
publicKey
|
|
174
|
+
};
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
function buildDoc(keys) {
|
|
178
|
+
const verificationMethod = keys.map((k)=>({
|
|
179
|
+
id: k.fragment,
|
|
180
|
+
type: 'Multikey',
|
|
181
|
+
publicKeyMultibase: publicKeyMultibase(k.alg, k.publicKey)
|
|
182
|
+
}));
|
|
183
|
+
const authentication = keys.filter((k)=>k.purpose === 'sig').map((k)=>k.fragment);
|
|
184
|
+
const keyAgreement = keys.filter((k)=>k.purpose === 'kem').map((k)=>k.fragment);
|
|
185
|
+
const doc = {
|
|
186
|
+
'@context': [
|
|
187
|
+
'https://www.w3.org/ns/did/v1'
|
|
188
|
+
],
|
|
189
|
+
verificationMethod
|
|
190
|
+
};
|
|
191
|
+
if (authentication.length > 0) doc.authentication = authentication;
|
|
192
|
+
if (keyAgreement.length > 0) doc.keyAgreement = keyAgreement;
|
|
193
|
+
return doc;
|
|
194
|
+
}
|
|
195
|
+
function pickSigningKey(keys, kid) {
|
|
196
|
+
if (kid != null) {
|
|
197
|
+
const found = keys.find((k)=>k.fragment === kid);
|
|
198
|
+
if (found == null) throw new Error(`KidNotFound: ${kid}`);
|
|
199
|
+
if (found.purpose !== 'sig') throw new Error(`Kid is not a signing key: ${kid}`);
|
|
200
|
+
return found;
|
|
201
|
+
}
|
|
202
|
+
const first = keys.find((k)=>k.purpose === 'sig');
|
|
203
|
+
if (first == null) throw new Error('No signing key in identity');
|
|
204
|
+
return first;
|
|
205
|
+
}
|
|
206
|
+
function signWith(key, data) {
|
|
207
|
+
switch(key.alg){
|
|
208
|
+
case 'EdDSA':
|
|
209
|
+
return ed25519.sign(data, key.privateKey);
|
|
210
|
+
case 'X25519':
|
|
211
|
+
throw new Error('X25519 cannot sign');
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
function pickKemKey(keys, kid) {
|
|
215
|
+
if (kid != null) {
|
|
216
|
+
const found = keys.find((k)=>k.fragment === kid);
|
|
217
|
+
if (found == null) throw new Error(`KidNotFound: ${kid}`);
|
|
218
|
+
if (found.purpose !== 'kem' || found.alg !== 'X25519') {
|
|
219
|
+
throw new Error(`Kid is not a KEM X25519 key: ${kid}`);
|
|
220
|
+
}
|
|
221
|
+
return found;
|
|
222
|
+
}
|
|
223
|
+
const first = keys.find((k)=>k.purpose === 'kem' && k.alg === 'X25519');
|
|
224
|
+
if (first == null) throw new Error('No KEM key in identity');
|
|
225
|
+
return first;
|
|
226
|
+
}
|
|
227
|
+
function buildIdentity(id, longForm, doc, keys) {
|
|
228
|
+
const primarySig = keys.find((k)=>k.purpose === 'sig');
|
|
229
|
+
if (primarySig == null) {
|
|
230
|
+
throw new Error('createIdentity requires at least one signing key');
|
|
231
|
+
}
|
|
232
|
+
const sentTo = new Set();
|
|
233
|
+
const isPeer = isPeer4(id);
|
|
234
|
+
function pickIss(payload, embedLongForm) {
|
|
235
|
+
if (!isPeer) return id;
|
|
236
|
+
if (embedLongForm === true) return longForm;
|
|
237
|
+
if (embedLongForm === false) return id;
|
|
238
|
+
const aud = payload.aud;
|
|
239
|
+
if (typeof aud !== 'string') return id;
|
|
240
|
+
const normalizedAud = normalizeDID(aud);
|
|
241
|
+
if (sentTo.has(normalizedAud)) return id;
|
|
242
|
+
// Concurrent sign() calls with the same new aud may both emit long-form; recipient cache writes are idempotent so this is acceptable.
|
|
243
|
+
sentTo.add(normalizedAud);
|
|
244
|
+
return longForm;
|
|
245
|
+
}
|
|
246
|
+
async function signToken(payload, options = {}) {
|
|
247
|
+
const key = pickSigningKey(keys, options.kid);
|
|
248
|
+
const iss = pickIss(payload, options.embedLongForm);
|
|
249
|
+
const header = {
|
|
250
|
+
...options.header ?? {},
|
|
251
|
+
typ: 'JWT',
|
|
252
|
+
alg: 'EdDSA',
|
|
253
|
+
...isPeer ? {
|
|
254
|
+
kid: key.fragment
|
|
255
|
+
} : {}
|
|
256
|
+
};
|
|
257
|
+
const fullPayload = {
|
|
258
|
+
...payload,
|
|
259
|
+
iss
|
|
260
|
+
};
|
|
261
|
+
const data = `${b64uFromJSON(header)}.${b64uFromJSON(fullPayload)}`;
|
|
262
|
+
return {
|
|
263
|
+
header: header,
|
|
264
|
+
payload: fullPayload,
|
|
265
|
+
signature: toB64U(signWith(key, fromUTF(data))),
|
|
266
|
+
data
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
async function agreeKey(ephemeralPublicKey, kid) {
|
|
270
|
+
const key = pickKemKey(keys, kid);
|
|
271
|
+
return x25519.getSharedSecret(key.privateKey, ephemeralPublicKey);
|
|
272
|
+
}
|
|
273
|
+
async function decrypt(jwe) {
|
|
274
|
+
pickKemKey(keys);
|
|
275
|
+
return decryptToken({
|
|
276
|
+
id,
|
|
277
|
+
decrypt,
|
|
278
|
+
agreeKey
|
|
279
|
+
}, jwe);
|
|
280
|
+
}
|
|
281
|
+
return {
|
|
282
|
+
id,
|
|
283
|
+
longForm,
|
|
284
|
+
doc,
|
|
285
|
+
keys,
|
|
286
|
+
publicKey: primarySig.publicKey,
|
|
287
|
+
privateKey: primarySig.privateKey,
|
|
288
|
+
signToken,
|
|
289
|
+
decrypt,
|
|
290
|
+
agreeKey
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Build a multi-key identity from one or more key specs.
|
|
295
|
+
*
|
|
296
|
+
* DID method selection:
|
|
297
|
+
* - Single classical (`EdDSA` / `X25519`) signing key with no override → `did:key`.
|
|
298
|
+
* - Anything else (multiple keys, KEM-only, any non-classical algorithm) → `did:peer:4`.
|
|
299
|
+
* - Caller may force a method via `input.didMethod`. Invalid combinations throw
|
|
300
|
+
* `IdentityError.InvalidMethod` (e.g. forcing `did:key` with multiple keys).
|
|
301
|
+
*
|
|
302
|
+
* Key resolution:
|
|
303
|
+
* - Each `IdentityKeySpec.privateKey` is honored when present (deterministic), otherwise
|
|
304
|
+
* a fresh random key is generated. See {@link IdentityKeySpec.privateKey}.
|
|
305
|
+
* - At least one signing key (`purpose: 'sig'`) is required; the first becomes the
|
|
306
|
+
* identity's primary signing key and seeds `publicKey` / `privateKey` on the result.
|
|
307
|
+
*
|
|
308
|
+
* For `did:peer:4`, the returned `id` is the short form (hash of the doc) and is
|
|
309
|
+
* deterministic with respect to the resolved keys — providing the same `privateKey`
|
|
310
|
+
* bytes across runs yields the same short form. `longForm` carries the full doc and
|
|
311
|
+
* is what peers exchange for first contact (see `signToken({ embedLongForm })`).
|
|
312
|
+
*
|
|
313
|
+
* @throws `Error` when `input.keys` is empty or no `sig` key is provided.
|
|
314
|
+
* @throws `IdentityError.InvalidMethod` when `didMethod` cannot satisfy the key set.
|
|
315
|
+
*/ export async function createIdentity(input) {
|
|
316
|
+
if (input.keys.length === 0) {
|
|
317
|
+
throw new Error('createIdentity requires at least one key');
|
|
318
|
+
}
|
|
319
|
+
const method = chooseMethod(input);
|
|
320
|
+
const keys = resolveKeys(input);
|
|
321
|
+
if (method === 'key') {
|
|
322
|
+
const [k] = keys;
|
|
323
|
+
const id = getDID(CODECS.EdDSA, k.publicKey);
|
|
324
|
+
const doc = {
|
|
325
|
+
'@context': [
|
|
326
|
+
'https://www.w3.org/ns/did/v1'
|
|
327
|
+
],
|
|
328
|
+
verificationMethod: [
|
|
329
|
+
{
|
|
330
|
+
id: '#key-0',
|
|
331
|
+
type: 'Multikey',
|
|
332
|
+
publicKeyMultibase: publicKeyMultibase(k.alg, k.publicKey)
|
|
333
|
+
}
|
|
334
|
+
],
|
|
335
|
+
authentication: [
|
|
336
|
+
'#key-0'
|
|
337
|
+
]
|
|
338
|
+
};
|
|
339
|
+
return buildIdentity(id, id, doc, keys);
|
|
340
|
+
}
|
|
341
|
+
const doc = buildDoc(keys);
|
|
342
|
+
const { longForm, shortForm } = encodePeer4(doc);
|
|
343
|
+
return buildIdentity(shortForm, longForm, doc, keys);
|
|
344
|
+
}
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JWT signing and verification.
|
|
3
|
+
*
|
|
4
|
+
* ## Installation
|
|
5
|
+
*
|
|
6
|
+
* ```sh
|
|
7
|
+
* npm install @kokuin/token
|
|
8
|
+
* ```
|
|
9
|
+
*
|
|
10
|
+
* @module token
|
|
11
|
+
*/
|
|
12
|
+
export { type CreateInMemoryDIDCacheOptions, createInMemoryDIDCache, type DIDCache, type DIDResolver, } from './cache.js';
|
|
13
|
+
export { CODECS, getAlgorithmAndPublicKey, getDID, getSignatureInfo, normalizeDID, type ResolveIssuerHeader, type ResolveIssuerWithDocResult, resolveIssuer, resolveIssuerWithDoc, } from './did.js';
|
|
14
|
+
export { type CreateIdentityInput, createDecryptingIdentity, createFullIdentity, createIdentity, createSigningIdentity, type DecryptingIdentity, type FullIdentity, type Identity, type IdentityKeySpec, type IdentityProvider, isDecryptingIdentity, isFullIdentity, isOwnIdentity, isSigningIdentity, type KeyAlg, type KeyPurpose, type MultiKeyIdentity, type OwnIdentity, type ResolvedKey, randomIdentity, type SigningIdentity, type SignTokenOptions, } from './identity.js';
|
|
15
|
+
export type { ConcatKDFParams, EncryptOptions, EnvelopeMode, JWEHeader, TokenEncrypter, UnwrapOptions, UnwrappedEnvelope, WrapOptions, } from './jwe.js';
|
|
16
|
+
export { concatKDF, createTokenEncrypter, decryptToken, encryptToken, unwrapEnvelope, wrapEnvelope, } from './jwe.js';
|
|
17
|
+
export type { KeyEntry, KeyStore } from './keystore.js';
|
|
18
|
+
export { decodeMultibase, encodeMultibase, multihashSHA256, verifyMultihash, } from './multibase.js';
|
|
19
|
+
export { type DecodePeer4Options, type DIDDoc, decodePeer4, encodePeer4, getPeer4ShortForm, isPeer4, type VerificationMethod, validateDIDDoc, } from './peer4.js';
|
|
20
|
+
export { createRotationAssertion, type RotationPayload, } from './rotation.js';
|
|
21
|
+
export { capabilitySchema, type SignatureAlgorithm, type SignedHeader, type SignedPayload, type SupportedHeader, signedHeaderSchema, signedPayloadSchema, supportedHeaderSchema, type UnsignedHeader, unsignedHeaderSchema, validateAlgorithm, validateSignedHeader, validateSignedPayload, validateUnsignedHeader, } from './schemas.js';
|
|
22
|
+
export { decodePrivateKey, encodePrivateKey, randomPrivateKey, } from './signer.js';
|
|
23
|
+
export { assertTimeClaimsValid, now, type TimeClaimsPayload, type TimeValidationOptions, } from './time.js';
|
|
24
|
+
export { createUnsignedToken, isSignedToken, isUnsignedToken, isVerifiedToken, signToken, type VerifyTokenOptions, verifyToken, } from './token.js';
|
|
25
|
+
export type * from './types.js';
|
|
26
|
+
export { stringifyToken } from './utils.js';
|
|
27
|
+
export { getVerifier, type Verifier, type Verifiers, } from './verifier.js';
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JWT signing and verification.
|
|
3
|
+
*
|
|
4
|
+
* ## Installation
|
|
5
|
+
*
|
|
6
|
+
* ```sh
|
|
7
|
+
* npm install @kokuin/token
|
|
8
|
+
* ```
|
|
9
|
+
*
|
|
10
|
+
* @module token
|
|
11
|
+
*/ export { createInMemoryDIDCache } from './cache.js';
|
|
12
|
+
export { CODECS, getAlgorithmAndPublicKey, getDID, getSignatureInfo, normalizeDID, resolveIssuer, resolveIssuerWithDoc } from './did.js';
|
|
13
|
+
export { createDecryptingIdentity, createFullIdentity, createIdentity, createSigningIdentity, isDecryptingIdentity, isFullIdentity, isOwnIdentity, isSigningIdentity, randomIdentity } from './identity.js';
|
|
14
|
+
export { concatKDF, createTokenEncrypter, decryptToken, encryptToken, unwrapEnvelope, wrapEnvelope } from './jwe.js';
|
|
15
|
+
export { decodeMultibase, encodeMultibase, multihashSHA256, verifyMultihash } from './multibase.js';
|
|
16
|
+
export { decodePeer4, encodePeer4, getPeer4ShortForm, isPeer4, validateDIDDoc } from './peer4.js';
|
|
17
|
+
export { createRotationAssertion } from './rotation.js';
|
|
18
|
+
export { capabilitySchema, signedHeaderSchema, signedPayloadSchema, supportedHeaderSchema, unsignedHeaderSchema, validateAlgorithm, validateSignedHeader, validateSignedPayload, validateUnsignedHeader } from './schemas.js';
|
|
19
|
+
export { decodePrivateKey, encodePrivateKey, randomPrivateKey } from './signer.js';
|
|
20
|
+
export { assertTimeClaimsValid, now } from './time.js';
|
|
21
|
+
export { createUnsignedToken, isSignedToken, isUnsignedToken, isVerifiedToken, signToken, verifyToken } from './token.js';
|
|
22
|
+
export { stringifyToken } from './utils.js';
|
|
23
|
+
export { getVerifier } from './verifier.js';
|
package/lib/jwe.d.ts
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { DecryptingIdentity, SigningIdentity } from './identity.js';
|
|
2
|
+
import type { Verifiers } from './verifier.js';
|
|
3
|
+
export type ConcatKDFParams = {
|
|
4
|
+
sharedSecret: Uint8Array;
|
|
5
|
+
keyLength: number;
|
|
6
|
+
algorithmID: string;
|
|
7
|
+
partyUInfo: Uint8Array;
|
|
8
|
+
partyVInfo: Uint8Array;
|
|
9
|
+
};
|
|
10
|
+
export type JWEHeader = {
|
|
11
|
+
alg: string;
|
|
12
|
+
enc: string;
|
|
13
|
+
epk: {
|
|
14
|
+
kty: string;
|
|
15
|
+
crv: string;
|
|
16
|
+
x: string;
|
|
17
|
+
};
|
|
18
|
+
apu?: string;
|
|
19
|
+
apv?: string;
|
|
20
|
+
};
|
|
21
|
+
export type TokenEncrypter = {
|
|
22
|
+
recipientID?: string;
|
|
23
|
+
encrypt(plaintext: Uint8Array): Promise<string>;
|
|
24
|
+
};
|
|
25
|
+
export type EncryptOptions = {
|
|
26
|
+
algorithm: 'X25519';
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Concat KDF per RFC 7518 Section 4.6.2.
|
|
30
|
+
* Single SHA-256 iteration (sufficient for 256-bit keys).
|
|
31
|
+
*/
|
|
32
|
+
export declare function concatKDF(params: ConcatKDFParams): Uint8Array;
|
|
33
|
+
/**
|
|
34
|
+
* Create a token encrypter for a recipient identified by X25519 public key or DID string.
|
|
35
|
+
*/
|
|
36
|
+
export declare function createTokenEncrypter(recipient: Uint8Array, options: EncryptOptions): TokenEncrypter;
|
|
37
|
+
export declare function createTokenEncrypter(recipient: string): TokenEncrypter;
|
|
38
|
+
/**
|
|
39
|
+
* Encrypt plaintext to JWE compact serialization using the given encrypter.
|
|
40
|
+
*/
|
|
41
|
+
export declare function encryptToken(encrypter: TokenEncrypter, plaintext: Uint8Array): Promise<string>;
|
|
42
|
+
/**
|
|
43
|
+
* Decrypt a JWE compact serialization string.
|
|
44
|
+
*/
|
|
45
|
+
export declare function decryptToken(decrypter: DecryptingIdentity, jwe: string): Promise<Uint8Array>;
|
|
46
|
+
export type EnvelopeMode = 'plain' | 'jws' | 'jws-in-jwe' | 'jwe-in-jws';
|
|
47
|
+
export type UnwrappedEnvelope = {
|
|
48
|
+
payload: Record<string, unknown>;
|
|
49
|
+
mode: EnvelopeMode;
|
|
50
|
+
};
|
|
51
|
+
export type WrapOptions = {
|
|
52
|
+
signer?: SigningIdentity;
|
|
53
|
+
encrypter?: TokenEncrypter;
|
|
54
|
+
header?: Record<string, unknown>;
|
|
55
|
+
};
|
|
56
|
+
export type UnwrapOptions = {
|
|
57
|
+
decrypter?: DecryptingIdentity;
|
|
58
|
+
verifiers?: Verifiers;
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* Wrap a payload into a token string according to the specified envelope mode.
|
|
62
|
+
*/
|
|
63
|
+
export declare function wrapEnvelope(mode: EnvelopeMode, payload: Record<string, unknown>, options: WrapOptions): Promise<string>;
|
|
64
|
+
/**
|
|
65
|
+
* Unwrap a token string, auto-detecting the envelope mode from its structure.
|
|
66
|
+
*/
|
|
67
|
+
export declare function unwrapEnvelope(message: string, options: UnwrapOptions): Promise<UnwrappedEnvelope>;
|