@smartledger/envelope 1.0.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/LICENSE +23 -0
- package/README.md +452 -0
- package/dist/cjs/envelope.d.ts +70 -0
- package/dist/cjs/envelope.d.ts.map +1 -0
- package/dist/cjs/envelope.js +191 -0
- package/dist/cjs/envelope.js.map +1 -0
- package/dist/cjs/helpers.d.ts +133 -0
- package/dist/cjs/helpers.d.ts.map +1 -0
- package/dist/cjs/helpers.js +159 -0
- package/dist/cjs/helpers.js.map +1 -0
- package/dist/cjs/index.d.ts +12 -0
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +11 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/types.d.ts +151 -0
- package/dist/cjs/types.d.ts.map +1 -0
- package/dist/cjs/types.js +20 -0
- package/dist/cjs/types.js.map +1 -0
- package/dist/esm/envelope.d.ts +70 -0
- package/dist/esm/envelope.d.ts.map +1 -0
- package/dist/esm/envelope.js +191 -0
- package/dist/esm/envelope.js.map +1 -0
- package/dist/esm/helpers.d.ts +133 -0
- package/dist/esm/helpers.d.ts.map +1 -0
- package/dist/esm/helpers.js +159 -0
- package/dist/esm/helpers.js.map +1 -0
- package/dist/esm/index.d.ts +12 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +11 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/package.json +1 -0
- package/dist/esm/types.d.ts +151 -0
- package/dist/esm/types.d.ts.map +1 -0
- package/dist/esm/types.js +20 -0
- package/dist/esm/types.js.map +1 -0
- package/dist/tsconfig.esm.tsbuildinfo +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +71 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SignedEnvelope - Canonical schema for verifiable AI outputs and content provenance
|
|
3
|
+
*
|
|
4
|
+
* This is the standard envelope format for any content that needs cryptographic verification:
|
|
5
|
+
* - AI-generated responses
|
|
6
|
+
* - User submissions
|
|
7
|
+
* - Agent communications
|
|
8
|
+
* - Contract artifacts
|
|
9
|
+
* - Audit logs
|
|
10
|
+
*
|
|
11
|
+
* Philosophy: Every piece of digital content should be able to answer:
|
|
12
|
+
* - WHO created it (cryptographically proven identity)
|
|
13
|
+
* - WHAT they created (content hash)
|
|
14
|
+
* - WHEN they created it (timestamp)
|
|
15
|
+
* - HOW to verify it (algorithm + public key)
|
|
16
|
+
*
|
|
17
|
+
* This envelope can be verified in 2025, 2045, or 2075.
|
|
18
|
+
*/
|
|
19
|
+
export {};
|
|
20
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import type { KeySDK } from '@smartledger/keys';
|
|
2
|
+
import type { SignedEnvelope, CreateEnvelopeOptions, VerifyEnvelopeOptions, VerificationResult, EnvelopeMetadata } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Create a signed envelope from payload
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```typescript
|
|
8
|
+
* import { createKeySDK } from '@smartledger/keys';
|
|
9
|
+
* import { createSignedEnvelope } from '@smartledger/envelope';
|
|
10
|
+
*
|
|
11
|
+
* const sdk = createKeySDK();
|
|
12
|
+
* const key = await sdk.createKey('my-agent', { primarySignatureSuite: 'ml-dsa-87' });
|
|
13
|
+
*
|
|
14
|
+
* const envelope = await createSignedEnvelope(
|
|
15
|
+
* sdk,
|
|
16
|
+
* key.meta.keyId,
|
|
17
|
+
* { message: "Hello, world!" },
|
|
18
|
+
* { creator: 'my-agent', contentType: 'greeting' }
|
|
19
|
+
* );
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export declare function createSignedEnvelope<T>(sdk: KeySDK, keyId: string, payload: T, options: CreateEnvelopeOptions): Promise<SignedEnvelope<T>>;
|
|
23
|
+
/**
|
|
24
|
+
* Verify a signed envelope
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```typescript
|
|
28
|
+
* const result = await verifySignedEnvelope(sdk, envelope);
|
|
29
|
+
* if (result.valid) {
|
|
30
|
+
* console.log('Verified! Created by:', result.creator);
|
|
31
|
+
* console.log('Payload:', envelope.payload);
|
|
32
|
+
* }
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export declare function verifySignedEnvelope<T>(sdk: KeySDK, envelope: SignedEnvelope<T>, options?: VerifyEnvelopeOptions): Promise<VerificationResult>;
|
|
36
|
+
/**
|
|
37
|
+
* Extract payload from envelope without verification
|
|
38
|
+
* Use only when verification was done previously
|
|
39
|
+
*/
|
|
40
|
+
export declare function extractPayload<T>(envelope: SignedEnvelope<T>): T;
|
|
41
|
+
/**
|
|
42
|
+
* Get envelope metadata
|
|
43
|
+
*/
|
|
44
|
+
export declare function getEnvelopeMeta<T>(envelope: SignedEnvelope<T>): EnvelopeMetadata;
|
|
45
|
+
/**
|
|
46
|
+
* Check if envelope has PQ signature
|
|
47
|
+
*/
|
|
48
|
+
export declare function hasPQSignature<T>(envelope: SignedEnvelope<T>): boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Check if envelope has on-chain anchor
|
|
51
|
+
*/
|
|
52
|
+
export declare function hasAnchor<T>(envelope: SignedEnvelope<T>): boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Create a chain of custody by linking envelopes
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* ```typescript
|
|
58
|
+
* const original = await createSignedEnvelope(sdk, keyId, data, { creator: 'alice' });
|
|
59
|
+
* const updated = await createEnvelopeChain(
|
|
60
|
+
* sdk,
|
|
61
|
+
* keyId,
|
|
62
|
+
* updatedData,
|
|
63
|
+
* original,
|
|
64
|
+
* { creator: 'bob', contentType: 'revision' }
|
|
65
|
+
* );
|
|
66
|
+
* // updated.meta.parentId === hash(original)
|
|
67
|
+
* ```
|
|
68
|
+
*/
|
|
69
|
+
export declare function createEnvelopeChain<T>(sdk: KeySDK, keyId: string, payload: T, parentEnvelope: SignedEnvelope<any>, options: Omit<CreateEnvelopeOptions, 'parentId'>): Promise<SignedEnvelope<T>>;
|
|
70
|
+
//# sourceMappingURL=envelope.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"envelope.d.ts","sourceRoot":"","sources":["../../src/envelope.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,KAAK,EACV,cAAc,EACd,qBAAqB,EACrB,qBAAqB,EACrB,kBAAkB,EAClB,gBAAgB,EAEjB,MAAM,YAAY,CAAC;AAIpB;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,oBAAoB,CAAC,CAAC,EAC1C,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,CAAC,EACV,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAmD5B;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,oBAAoB,CAAC,CAAC,EAC1C,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,cAAc,CAAC,CAAC,CAAC,EAC3B,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAAC,kBAAkB,CAAC,CAsE7B;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,QAAQ,EAAE,cAAc,CAAC,CAAC,CAAC,GAAG,CAAC,CAEhE;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,QAAQ,EAAE,cAAc,CAAC,CAAC,CAAC,GAAG,gBAAgB,CAEhF;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,QAAQ,EAAE,cAAc,CAAC,CAAC,CAAC,GAAG,OAAO,CAEtE;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,QAAQ,EAAE,cAAc,CAAC,CAAC,CAAC,GAAG,OAAO,CAEjE;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,mBAAmB,CAAC,CAAC,EACzC,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,CAAC,EACV,cAAc,EAAE,cAAc,CAAC,GAAG,CAAC,EACnC,OAAO,EAAE,IAAI,CAAC,qBAAqB,EAAE,UAAU,CAAC,GAC/C,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAW5B"}
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
const ENVELOPE_VERSION = '1.0.0';
|
|
2
|
+
/**
|
|
3
|
+
* Create a signed envelope from payload
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```typescript
|
|
7
|
+
* import { createKeySDK } from '@smartledger/keys';
|
|
8
|
+
* import { createSignedEnvelope } from '@smartledger/envelope';
|
|
9
|
+
*
|
|
10
|
+
* const sdk = createKeySDK();
|
|
11
|
+
* const key = await sdk.createKey('my-agent', { primarySignatureSuite: 'ml-dsa-87' });
|
|
12
|
+
*
|
|
13
|
+
* const envelope = await createSignedEnvelope(
|
|
14
|
+
* sdk,
|
|
15
|
+
* key.meta.keyId,
|
|
16
|
+
* { message: "Hello, world!" },
|
|
17
|
+
* { creator: 'my-agent', contentType: 'greeting' }
|
|
18
|
+
* );
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export async function createSignedEnvelope(sdk, keyId, payload, options) {
|
|
22
|
+
const now = new Date().toISOString();
|
|
23
|
+
// Build metadata
|
|
24
|
+
const meta = {
|
|
25
|
+
version: ENVELOPE_VERSION,
|
|
26
|
+
creator: options.creator,
|
|
27
|
+
creatorType: options.creatorType,
|
|
28
|
+
createdAt: now,
|
|
29
|
+
contentType: options.contentType,
|
|
30
|
+
anchor: options.anchor,
|
|
31
|
+
parentId: options.parentId,
|
|
32
|
+
...options.metadata,
|
|
33
|
+
};
|
|
34
|
+
// Create canonical payload to sign
|
|
35
|
+
const canonical = {
|
|
36
|
+
payload,
|
|
37
|
+
meta,
|
|
38
|
+
};
|
|
39
|
+
const message = new TextEncoder().encode(JSON.stringify(canonical));
|
|
40
|
+
// Sign with primary key
|
|
41
|
+
const signature = await sdk.signWithKey(keyId, message);
|
|
42
|
+
const key = await sdk.getKey(keyId);
|
|
43
|
+
if (!key) {
|
|
44
|
+
throw new Error(`Key ${keyId} not found`);
|
|
45
|
+
}
|
|
46
|
+
const signatureMetadata = {
|
|
47
|
+
algorithm: key.meta.suiteId,
|
|
48
|
+
keyId,
|
|
49
|
+
publicKey: Buffer.from(key.publicKey).toString('base64'),
|
|
50
|
+
signature: Buffer.from(signature).toString('base64'),
|
|
51
|
+
timestamp: now,
|
|
52
|
+
};
|
|
53
|
+
// Optional: dual-sign with PQ if requested and available
|
|
54
|
+
if (options.dualSign) {
|
|
55
|
+
// Check if suite has PQ capability or if there's a secondary suite
|
|
56
|
+
// For now, just document the pattern - implementation would check
|
|
57
|
+
// if key has a secondary PQ suite and sign with that too
|
|
58
|
+
}
|
|
59
|
+
return {
|
|
60
|
+
payload,
|
|
61
|
+
meta,
|
|
62
|
+
_signature: signatureMetadata,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Verify a signed envelope
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* ```typescript
|
|
70
|
+
* const result = await verifySignedEnvelope(sdk, envelope);
|
|
71
|
+
* if (result.valid) {
|
|
72
|
+
* console.log('Verified! Created by:', result.creator);
|
|
73
|
+
* console.log('Payload:', envelope.payload);
|
|
74
|
+
* }
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
77
|
+
export async function verifySignedEnvelope(sdk, envelope, options = {}) {
|
|
78
|
+
try {
|
|
79
|
+
// Check age if maxAge specified
|
|
80
|
+
if (options.maxAge) {
|
|
81
|
+
const signatureTime = new Date(envelope._signature.timestamp).getTime();
|
|
82
|
+
const age = Date.now() - signatureTime;
|
|
83
|
+
if (age > options.maxAge) {
|
|
84
|
+
return {
|
|
85
|
+
valid: false,
|
|
86
|
+
error: `Signature too old: ${age}ms > ${options.maxAge}ms`,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
// Check expected creator if specified
|
|
91
|
+
if (options.expectedCreator && envelope.meta.creator !== options.expectedCreator) {
|
|
92
|
+
return {
|
|
93
|
+
valid: false,
|
|
94
|
+
error: `Unexpected creator: ${envelope.meta.creator} !== ${options.expectedCreator}`,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
// Reconstruct canonical message
|
|
98
|
+
const canonical = {
|
|
99
|
+
payload: envelope.payload,
|
|
100
|
+
meta: envelope.meta,
|
|
101
|
+
};
|
|
102
|
+
const message = new TextEncoder().encode(JSON.stringify(canonical));
|
|
103
|
+
const signature = Buffer.from(envelope._signature.signature, 'base64');
|
|
104
|
+
// Verify signature
|
|
105
|
+
const keyId = envelope._signature.keyId;
|
|
106
|
+
if (!keyId) {
|
|
107
|
+
return {
|
|
108
|
+
valid: false,
|
|
109
|
+
error: 'No keyId in signature metadata',
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
const valid = await sdk.verifySignature(keyId, message, signature);
|
|
113
|
+
if (!valid) {
|
|
114
|
+
return {
|
|
115
|
+
valid: false,
|
|
116
|
+
error: 'Signature verification failed',
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
// Verify PQ signature if present and requested
|
|
120
|
+
let verified = 'primary';
|
|
121
|
+
if (options.verifyPQ && envelope._signature.pqSignature) {
|
|
122
|
+
// Would verify PQ signature here
|
|
123
|
+
// For now, just document the pattern
|
|
124
|
+
verified = 'both';
|
|
125
|
+
}
|
|
126
|
+
return {
|
|
127
|
+
valid: true,
|
|
128
|
+
verified,
|
|
129
|
+
creator: envelope.meta.creator,
|
|
130
|
+
timestamp: envelope._signature.timestamp,
|
|
131
|
+
contentMatch: true,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
catch (error) {
|
|
135
|
+
return {
|
|
136
|
+
valid: false,
|
|
137
|
+
error: error instanceof Error ? error.message : String(error),
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Extract payload from envelope without verification
|
|
143
|
+
* Use only when verification was done previously
|
|
144
|
+
*/
|
|
145
|
+
export function extractPayload(envelope) {
|
|
146
|
+
return envelope.payload;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Get envelope metadata
|
|
150
|
+
*/
|
|
151
|
+
export function getEnvelopeMeta(envelope) {
|
|
152
|
+
return envelope.meta;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Check if envelope has PQ signature
|
|
156
|
+
*/
|
|
157
|
+
export function hasPQSignature(envelope) {
|
|
158
|
+
return !!envelope._signature.pqSignature;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Check if envelope has on-chain anchor
|
|
162
|
+
*/
|
|
163
|
+
export function hasAnchor(envelope) {
|
|
164
|
+
return !!envelope.meta.anchor;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Create a chain of custody by linking envelopes
|
|
168
|
+
*
|
|
169
|
+
* @example
|
|
170
|
+
* ```typescript
|
|
171
|
+
* const original = await createSignedEnvelope(sdk, keyId, data, { creator: 'alice' });
|
|
172
|
+
* const updated = await createEnvelopeChain(
|
|
173
|
+
* sdk,
|
|
174
|
+
* keyId,
|
|
175
|
+
* updatedData,
|
|
176
|
+
* original,
|
|
177
|
+
* { creator: 'bob', contentType: 'revision' }
|
|
178
|
+
* );
|
|
179
|
+
* // updated.meta.parentId === hash(original)
|
|
180
|
+
* ```
|
|
181
|
+
*/
|
|
182
|
+
export async function createEnvelopeChain(sdk, keyId, payload, parentEnvelope, options) {
|
|
183
|
+
// Create a hash of parent envelope as parentId
|
|
184
|
+
const parentJson = JSON.stringify(parentEnvelope);
|
|
185
|
+
const parentHash = Buffer.from(await crypto.subtle.digest('SHA-256', new TextEncoder().encode(parentJson))).toString('hex');
|
|
186
|
+
return createSignedEnvelope(sdk, keyId, payload, {
|
|
187
|
+
...options,
|
|
188
|
+
parentId: parentHash,
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
//# sourceMappingURL=envelope.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"envelope.js","sourceRoot":"","sources":["../../src/envelope.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { type KeySDK } from '@smartledger/keys';
|
|
2
|
+
import type { SignedEnvelope, VerificationResult } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* High-level app identity interface
|
|
5
|
+
* This is the "1-2 line setup" API that makes adoption trivial
|
|
6
|
+
*/
|
|
7
|
+
export interface AppIdentity {
|
|
8
|
+
/** App/agent name */
|
|
9
|
+
name: string;
|
|
10
|
+
/** Key ID being used */
|
|
11
|
+
keyId: string;
|
|
12
|
+
/** Sign any JSON-serializable data */
|
|
13
|
+
signJson<T>(data: T, options?: {
|
|
14
|
+
contentType?: string;
|
|
15
|
+
}): Promise<SignedEnvelope<T>>;
|
|
16
|
+
/** Verify any signed envelope */
|
|
17
|
+
verifyJson<T>(envelope: SignedEnvelope<T>): Promise<VerificationResult>;
|
|
18
|
+
/** Get the underlying SDK (for advanced usage) */
|
|
19
|
+
getSDK(): KeySDK;
|
|
20
|
+
/** Get public key for sharing */
|
|
21
|
+
getPublicKey(): Promise<Uint8Array>;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Create an app identity in 1-2 lines
|
|
25
|
+
*
|
|
26
|
+
* This is the "killer API" that makes people go: "Oh, I get it."
|
|
27
|
+
*
|
|
28
|
+
* Creates an in-memory identity for signing/verification. Keys are ephemeral by default.
|
|
29
|
+
* For persistence, see examples/file-storage or provide your own KeySDK with custom storage.
|
|
30
|
+
*
|
|
31
|
+
* @example Dead simple setup
|
|
32
|
+
* ```typescript
|
|
33
|
+
* import { createAppIdentity } from '@smartledger/envelope';
|
|
34
|
+
*
|
|
35
|
+
* // That's it. You're ready to sign things (in-memory).
|
|
36
|
+
* const identity = await createAppIdentity({ name: 'MyCoolApp' });
|
|
37
|
+
*
|
|
38
|
+
* // Sign anything
|
|
39
|
+
* const signed = await identity.signJson({ message: "Hello, world!" });
|
|
40
|
+
*
|
|
41
|
+
* // Verify anything
|
|
42
|
+
* const result = await identity.verifyJson(signed);
|
|
43
|
+
* console.log('Valid:', result.valid);
|
|
44
|
+
* ```
|
|
45
|
+
*
|
|
46
|
+
* @example Use existing SDK with custom storage
|
|
47
|
+
* ```typescript
|
|
48
|
+
* import { createKeySDK } from '@smartledger/keys';
|
|
49
|
+
* import { FileKeyStorage } from './storage'; // See examples/
|
|
50
|
+
*
|
|
51
|
+
* const sdk = createKeySDK({ storage: new FileKeyStorage('./keys') });
|
|
52
|
+
* const key = await sdk.createKey('MyCoolApp', { primarySignatureSuite: 'ml-dsa-87' });
|
|
53
|
+
*
|
|
54
|
+
* const identity = await createAppIdentity({
|
|
55
|
+
* name: 'MyCoolApp',
|
|
56
|
+
* sdk, // Use your SDK with persistence
|
|
57
|
+
* existingKeyId: key.meta.keyId
|
|
58
|
+
* });
|
|
59
|
+
* ```
|
|
60
|
+
*
|
|
61
|
+
* @example Sign AI responses
|
|
62
|
+
* ```typescript
|
|
63
|
+
* const identity = await createAppIdentity({ name: 'MyAI' });
|
|
64
|
+
*
|
|
65
|
+
* const response = await openai.chat.completions.create({
|
|
66
|
+
* messages: [{ role: 'user', content: 'Hello!' }]
|
|
67
|
+
* });
|
|
68
|
+
*
|
|
69
|
+
* const signed = await identity.signJson(response, {
|
|
70
|
+
* contentType: 'ai-response'
|
|
71
|
+
* });
|
|
72
|
+
*
|
|
73
|
+
* // Now you have cryptographic proof of what your AI said and when
|
|
74
|
+
* ```
|
|
75
|
+
*
|
|
76
|
+
* @example Verify third-party content
|
|
77
|
+
* ```typescript
|
|
78
|
+
* const theirIdentity = await createAppIdentity({
|
|
79
|
+
* name: 'TheirApp',
|
|
80
|
+
* existingKeyId: 'their-public-key-id'
|
|
81
|
+
* });
|
|
82
|
+
*
|
|
83
|
+
* const result = await theirIdentity.verifyJson(receivedEnvelope);
|
|
84
|
+
* if (result.valid) {
|
|
85
|
+
* console.log('Verified from:', result.creator);
|
|
86
|
+
* }
|
|
87
|
+
* ```
|
|
88
|
+
*/
|
|
89
|
+
export declare function createAppIdentity(options: {
|
|
90
|
+
/** App/agent name */
|
|
91
|
+
name: string;
|
|
92
|
+
/** Signature algorithm (default: 'ml-dsa-87') */
|
|
93
|
+
algorithm?: 'ml-dsa-87' | 'bsv-ecdsa-secp256k1';
|
|
94
|
+
/** Provide your own SDK (e.g., with custom storage) */
|
|
95
|
+
sdk?: KeySDK;
|
|
96
|
+
/** Use existing key ID instead of creating new */
|
|
97
|
+
existingKeyId?: string;
|
|
98
|
+
}): Promise<AppIdentity>;
|
|
99
|
+
/**
|
|
100
|
+
* Convenience: Sign JSON and return envelope in one call
|
|
101
|
+
* For when you don't need to keep the identity around
|
|
102
|
+
*
|
|
103
|
+
* Uses a singleton SDK instance so keys persist across calls.
|
|
104
|
+
* This allows verifyJson() to verify envelopes from signJson().
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* ```typescript
|
|
108
|
+
* import { signJson } from '@smartledger/envelope';
|
|
109
|
+
*
|
|
110
|
+
* const signed = await signJson('MyApp', { message: "Hello!" });
|
|
111
|
+
* ```
|
|
112
|
+
*/
|
|
113
|
+
export declare function signJson<T>(appName: string, data: T, options?: {
|
|
114
|
+
algorithm?: 'ml-dsa-87' | 'bsv-ecdsa-secp256k1';
|
|
115
|
+
contentType?: string;
|
|
116
|
+
}): Promise<SignedEnvelope<T>>;
|
|
117
|
+
/**
|
|
118
|
+
* Convenience: Verify JSON envelope in one call
|
|
119
|
+
*
|
|
120
|
+
* Uses a singleton SDK instance to verify envelopes created with signJson().
|
|
121
|
+
*
|
|
122
|
+
* @example
|
|
123
|
+
* ```typescript
|
|
124
|
+
* import { verifyJson } from '@smartledger/envelope';
|
|
125
|
+
*
|
|
126
|
+
* const result = await verifyJson(receivedEnvelope);
|
|
127
|
+
* if (result.valid) {
|
|
128
|
+
* console.log('Payload:', receivedEnvelope.payload);
|
|
129
|
+
* }
|
|
130
|
+
* ```
|
|
131
|
+
*/
|
|
132
|
+
export declare function verifyJson<T>(envelope: SignedEnvelope<T>): Promise<VerificationResult>;
|
|
133
|
+
//# sourceMappingURL=helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC9D,OAAO,KAAK,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAcrE;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B,qBAAqB;IACrB,IAAI,EAAE,MAAM,CAAC;IAEb,wBAAwB;IACxB,KAAK,EAAE,MAAM,CAAC;IAEd,sCAAsC;IACtC,QAAQ,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC;IAErF,iCAAiC;IACjC,UAAU,CAAC,CAAC,EAAE,QAAQ,EAAE,cAAc,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;IAExE,kDAAkD;IAClD,MAAM,IAAI,MAAM,CAAC;IAEjB,iCAAiC;IACjC,YAAY,IAAI,OAAO,CAAC,UAAU,CAAC,CAAC;CACrC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiEG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE;IAC/C,qBAAqB;IACrB,IAAI,EAAE,MAAM,CAAC;IAEb,iDAAiD;IACjD,SAAS,CAAC,EAAE,WAAW,GAAG,qBAAqB,CAAC;IAEhD,uDAAuD;IACvD,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb,kDAAkD;IAClD,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,GAAG,OAAO,CAAC,WAAW,CAAC,CA8CvB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,QAAQ,CAAC,CAAC,EAC9B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,CAAC,EACP,OAAO,CAAC,EAAE;IACR,SAAS,CAAC,EAAE,WAAW,GAAG,qBAAqB,CAAC;IAChD,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,GACA,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAQ5B;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,UAAU,CAAC,CAAC,EAChC,QAAQ,EAAE,cAAc,CAAC,CAAC,CAAC,GAC1B,OAAO,CAAC,kBAAkB,CAAC,CAG7B"}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { createKeySDK } from '@smartledger/keys';
|
|
2
|
+
import { createSignedEnvelope, verifySignedEnvelope } from './envelope.js';
|
|
3
|
+
// Singleton SDK for convenience functions
|
|
4
|
+
// This allows signJson() and verifyJson() to work across calls
|
|
5
|
+
let _globalSDK = null;
|
|
6
|
+
function getGlobalSDK() {
|
|
7
|
+
if (!_globalSDK) {
|
|
8
|
+
_globalSDK = createKeySDK();
|
|
9
|
+
}
|
|
10
|
+
return _globalSDK;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Create an app identity in 1-2 lines
|
|
14
|
+
*
|
|
15
|
+
* This is the "killer API" that makes people go: "Oh, I get it."
|
|
16
|
+
*
|
|
17
|
+
* Creates an in-memory identity for signing/verification. Keys are ephemeral by default.
|
|
18
|
+
* For persistence, see examples/file-storage or provide your own KeySDK with custom storage.
|
|
19
|
+
*
|
|
20
|
+
* @example Dead simple setup
|
|
21
|
+
* ```typescript
|
|
22
|
+
* import { createAppIdentity } from '@smartledger/envelope';
|
|
23
|
+
*
|
|
24
|
+
* // That's it. You're ready to sign things (in-memory).
|
|
25
|
+
* const identity = await createAppIdentity({ name: 'MyCoolApp' });
|
|
26
|
+
*
|
|
27
|
+
* // Sign anything
|
|
28
|
+
* const signed = await identity.signJson({ message: "Hello, world!" });
|
|
29
|
+
*
|
|
30
|
+
* // Verify anything
|
|
31
|
+
* const result = await identity.verifyJson(signed);
|
|
32
|
+
* console.log('Valid:', result.valid);
|
|
33
|
+
* ```
|
|
34
|
+
*
|
|
35
|
+
* @example Use existing SDK with custom storage
|
|
36
|
+
* ```typescript
|
|
37
|
+
* import { createKeySDK } from '@smartledger/keys';
|
|
38
|
+
* import { FileKeyStorage } from './storage'; // See examples/
|
|
39
|
+
*
|
|
40
|
+
* const sdk = createKeySDK({ storage: new FileKeyStorage('./keys') });
|
|
41
|
+
* const key = await sdk.createKey('MyCoolApp', { primarySignatureSuite: 'ml-dsa-87' });
|
|
42
|
+
*
|
|
43
|
+
* const identity = await createAppIdentity({
|
|
44
|
+
* name: 'MyCoolApp',
|
|
45
|
+
* sdk, // Use your SDK with persistence
|
|
46
|
+
* existingKeyId: key.meta.keyId
|
|
47
|
+
* });
|
|
48
|
+
* ```
|
|
49
|
+
*
|
|
50
|
+
* @example Sign AI responses
|
|
51
|
+
* ```typescript
|
|
52
|
+
* const identity = await createAppIdentity({ name: 'MyAI' });
|
|
53
|
+
*
|
|
54
|
+
* const response = await openai.chat.completions.create({
|
|
55
|
+
* messages: [{ role: 'user', content: 'Hello!' }]
|
|
56
|
+
* });
|
|
57
|
+
*
|
|
58
|
+
* const signed = await identity.signJson(response, {
|
|
59
|
+
* contentType: 'ai-response'
|
|
60
|
+
* });
|
|
61
|
+
*
|
|
62
|
+
* // Now you have cryptographic proof of what your AI said and when
|
|
63
|
+
* ```
|
|
64
|
+
*
|
|
65
|
+
* @example Verify third-party content
|
|
66
|
+
* ```typescript
|
|
67
|
+
* const theirIdentity = await createAppIdentity({
|
|
68
|
+
* name: 'TheirApp',
|
|
69
|
+
* existingKeyId: 'their-public-key-id'
|
|
70
|
+
* });
|
|
71
|
+
*
|
|
72
|
+
* const result = await theirIdentity.verifyJson(receivedEnvelope);
|
|
73
|
+
* if (result.valid) {
|
|
74
|
+
* console.log('Verified from:', result.creator);
|
|
75
|
+
* }
|
|
76
|
+
* ```
|
|
77
|
+
*/
|
|
78
|
+
export async function createAppIdentity(options) {
|
|
79
|
+
const sdk = options.sdk || createKeySDK();
|
|
80
|
+
const algorithm = options.algorithm || 'ml-dsa-87';
|
|
81
|
+
// Create or use existing key
|
|
82
|
+
let keyId;
|
|
83
|
+
if (options.existingKeyId) {
|
|
84
|
+
keyId = options.existingKeyId;
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
const key = await sdk.createKey(options.name, {
|
|
88
|
+
primarySignatureSuite: algorithm,
|
|
89
|
+
});
|
|
90
|
+
keyId = key.meta.keyId;
|
|
91
|
+
}
|
|
92
|
+
return {
|
|
93
|
+
name: options.name,
|
|
94
|
+
keyId,
|
|
95
|
+
async signJson(data, opts) {
|
|
96
|
+
return createSignedEnvelope(sdk, keyId, data, {
|
|
97
|
+
creator: options.name,
|
|
98
|
+
creatorType: 'service',
|
|
99
|
+
contentType: opts?.contentType,
|
|
100
|
+
});
|
|
101
|
+
},
|
|
102
|
+
async verifyJson(envelope) {
|
|
103
|
+
return verifySignedEnvelope(sdk, envelope);
|
|
104
|
+
},
|
|
105
|
+
getSDK() {
|
|
106
|
+
return sdk;
|
|
107
|
+
},
|
|
108
|
+
async getPublicKey() {
|
|
109
|
+
const key = await sdk.getKey(keyId);
|
|
110
|
+
if (!key) {
|
|
111
|
+
throw new Error(`Key ${keyId} not found`);
|
|
112
|
+
}
|
|
113
|
+
return key.publicKey;
|
|
114
|
+
},
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Convenience: Sign JSON and return envelope in one call
|
|
119
|
+
* For when you don't need to keep the identity around
|
|
120
|
+
*
|
|
121
|
+
* Uses a singleton SDK instance so keys persist across calls.
|
|
122
|
+
* This allows verifyJson() to verify envelopes from signJson().
|
|
123
|
+
*
|
|
124
|
+
* @example
|
|
125
|
+
* ```typescript
|
|
126
|
+
* import { signJson } from '@smartledger/envelope';
|
|
127
|
+
*
|
|
128
|
+
* const signed = await signJson('MyApp', { message: "Hello!" });
|
|
129
|
+
* ```
|
|
130
|
+
*/
|
|
131
|
+
export async function signJson(appName, data, options) {
|
|
132
|
+
const sdk = getGlobalSDK();
|
|
133
|
+
const identity = await createAppIdentity({
|
|
134
|
+
name: appName,
|
|
135
|
+
algorithm: options?.algorithm,
|
|
136
|
+
sdk,
|
|
137
|
+
});
|
|
138
|
+
return identity.signJson(data, { contentType: options?.contentType });
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Convenience: Verify JSON envelope in one call
|
|
142
|
+
*
|
|
143
|
+
* Uses a singleton SDK instance to verify envelopes created with signJson().
|
|
144
|
+
*
|
|
145
|
+
* @example
|
|
146
|
+
* ```typescript
|
|
147
|
+
* import { verifyJson } from '@smartledger/envelope';
|
|
148
|
+
*
|
|
149
|
+
* const result = await verifyJson(receivedEnvelope);
|
|
150
|
+
* if (result.valid) {
|
|
151
|
+
* console.log('Payload:', receivedEnvelope.payload);
|
|
152
|
+
* }
|
|
153
|
+
* ```
|
|
154
|
+
*/
|
|
155
|
+
export async function verifyJson(envelope) {
|
|
156
|
+
const sdk = getGlobalSDK();
|
|
157
|
+
return verifySignedEnvelope(sdk, envelope);
|
|
158
|
+
}
|
|
159
|
+
//# sourceMappingURL=helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../src/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAe,MAAM,mBAAmB,CAAC;AAE9D,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAE3E,0CAA0C;AAC1C,+DAA+D;AAC/D,IAAI,UAAU,GAAkB,IAAI,CAAC;AAErC,SAAS,YAAY;IACnB,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,UAAU,GAAG,YAAY,EAAE,CAAC;IAC9B,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC;AA0BD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiEG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,OAYvC;IACC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,YAAY,EAAE,CAAC;IAC1C,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,WAAW,CAAC;IAEnD,6BAA6B;IAC7B,IAAI,KAAa,CAAC;IAClB,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;QAC1B,KAAK,GAAG,OAAO,CAAC,aAAa,CAAC;IAChC,CAAC;SAAM,CAAC;QACN,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,EAAE;YAC5C,qBAAqB,EAAE,SAAS;SACjC,CAAC,CAAC;QACH,KAAK,GAAG,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC;IACzB,CAAC;IAED,OAAO;QACL,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,KAAK;QAEL,KAAK,CAAC,QAAQ,CACZ,IAAO,EACP,IAA+B;YAE/B,OAAO,oBAAoB,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE;gBAC5C,OAAO,EAAE,OAAO,CAAC,IAAI;gBACrB,WAAW,EAAE,SAAS;gBACtB,WAAW,EAAE,IAAI,EAAE,WAAW;aAC/B,CAAC,CAAC;QACL,CAAC;QAED,KAAK,CAAC,UAAU,CAAI,QAA2B;YAC7C,OAAO,oBAAoB,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;QAC7C,CAAC;QAED,MAAM;YACJ,OAAO,GAAG,CAAC;QACb,CAAC;QAED,KAAK,CAAC,YAAY;YAChB,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACpC,IAAI,CAAC,GAAG,EAAE,CAAC;gBACT,MAAM,IAAI,KAAK,CAAC,OAAO,KAAK,YAAY,CAAC,CAAC;YAC5C,CAAC;YACD,OAAO,GAAG,CAAC,SAAS,CAAC;QACvB,CAAC;KACF,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,OAAe,EACf,IAAO,EACP,OAGC;IAED,MAAM,GAAG,GAAG,YAAY,EAAE,CAAC;IAC3B,MAAM,QAAQ,GAAG,MAAM,iBAAiB,CAAC;QACvC,IAAI,EAAE,OAAO;QACb,SAAS,EAAE,OAAO,EAAE,SAAS;QAC7B,GAAG;KACJ,CAAC,CAAC;IACH,OAAO,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,WAAW,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC;AACxE,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,QAA2B;IAE3B,MAAM,GAAG,GAAG,YAAY,EAAE,CAAC;IAC3B,OAAO,oBAAoB,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;AAC7C,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @smartledger/envelope - Canonical SignedEnvelope for verifiable content
|
|
3
|
+
*
|
|
4
|
+
* The standard way to wrap any content with cryptographic verification.
|
|
5
|
+
*/
|
|
6
|
+
export * from './types.js';
|
|
7
|
+
export * from './envelope.js';
|
|
8
|
+
export * from './helpers.js';
|
|
9
|
+
export type { SignedEnvelope, SignatureMetadata, EnvelopeMetadata, CreateEnvelopeOptions, VerifyEnvelopeOptions, VerificationResult, } from './types.js';
|
|
10
|
+
export { createSignedEnvelope, verifySignedEnvelope, extractPayload, getEnvelopeMeta, hasPQSignature, hasAnchor, createEnvelopeChain, } from './envelope.js';
|
|
11
|
+
export { createAppIdentity, type AppIdentity, } from './helpers.js';
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAG7B,YAAY,EACV,cAAc,EACd,iBAAiB,EACjB,gBAAgB,EAChB,qBAAqB,EACrB,qBAAqB,EACrB,kBAAkB,GACnB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACpB,cAAc,EACd,eAAe,EACf,cAAc,EACd,SAAS,EACT,mBAAmB,GACpB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,iBAAiB,EACjB,KAAK,WAAW,GACjB,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @smartledger/envelope - Canonical SignedEnvelope for verifiable content
|
|
3
|
+
*
|
|
4
|
+
* The standard way to wrap any content with cryptographic verification.
|
|
5
|
+
*/
|
|
6
|
+
export * from './types.js';
|
|
7
|
+
export * from './envelope.js';
|
|
8
|
+
export * from './helpers.js';
|
|
9
|
+
export { createSignedEnvelope, verifySignedEnvelope, extractPayload, getEnvelopeMeta, hasPQSignature, hasAnchor, createEnvelopeChain, } from './envelope.js';
|
|
10
|
+
export { createAppIdentity, } from './helpers.js';
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAY7B,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACpB,cAAc,EACd,eAAe,EACf,cAAc,EACd,SAAS,EACT,mBAAmB,GACpB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,iBAAiB,GAElB,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type": "module"}
|