@peac/crypto 0.9.18
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 +23 -0
- package/dist/base64url.d.ts +21 -0
- package/dist/base64url.d.ts.map +1 -0
- package/dist/base64url.js +44 -0
- package/dist/base64url.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +24 -0
- package/dist/index.js.map +1 -0
- package/dist/jcs.d.ts +17 -0
- package/dist/jcs.d.ts.map +1 -0
- package/dist/jcs.js +72 -0
- package/dist/jcs.js.map +1 -0
- package/dist/jws.d.ts +58 -0
- package/dist/jws.d.ts.map +1 -0
- package/dist/jws.js +148 -0
- package/dist/jws.js.map +1 -0
- package/package.json +40 -0
package/README.md
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# @peac/crypto
|
|
2
|
+
|
|
3
|
+
Ed25519 JWS signing and verification for PEAC protocol
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm add @peac/crypto
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Documentation
|
|
12
|
+
|
|
13
|
+
See [peacprotocol.org](https://peacprotocol.org) for full documentation.
|
|
14
|
+
|
|
15
|
+
## License
|
|
16
|
+
|
|
17
|
+
Apache-2.0
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
PEAC Protocol is an open source project stewarded by Originary and community contributors.
|
|
22
|
+
|
|
23
|
+
[Originary](https://www.originary.xyz) | [Docs](https://peacprotocol.org) | [GitHub](https://github.com/peacprotocol/peac)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base64url encoding/decoding (RFC 4648 §5)
|
|
3
|
+
* Used for JWS compact serialization
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Encode bytes to base64url string (no padding)
|
|
7
|
+
*/
|
|
8
|
+
export declare function base64urlEncode(bytes: Uint8Array): string;
|
|
9
|
+
/**
|
|
10
|
+
* Decode base64url string to bytes
|
|
11
|
+
*/
|
|
12
|
+
export declare function base64urlDecode(str: string): Uint8Array;
|
|
13
|
+
/**
|
|
14
|
+
* Encode UTF-8 string to base64url
|
|
15
|
+
*/
|
|
16
|
+
export declare function base64urlEncodeString(str: string): string;
|
|
17
|
+
/**
|
|
18
|
+
* Decode base64url to UTF-8 string
|
|
19
|
+
*/
|
|
20
|
+
export declare function base64urlDecodeString(str: string): string;
|
|
21
|
+
//# sourceMappingURL=base64url.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base64url.d.ts","sourceRoot":"","sources":["../src/base64url.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAGzD;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAYvD;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEzD"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Base64url encoding/decoding (RFC 4648 §5)
|
|
4
|
+
* Used for JWS compact serialization
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.base64urlEncode = base64urlEncode;
|
|
8
|
+
exports.base64urlDecode = base64urlDecode;
|
|
9
|
+
exports.base64urlEncodeString = base64urlEncodeString;
|
|
10
|
+
exports.base64urlDecodeString = base64urlDecodeString;
|
|
11
|
+
/**
|
|
12
|
+
* Encode bytes to base64url string (no padding)
|
|
13
|
+
*/
|
|
14
|
+
function base64urlEncode(bytes) {
|
|
15
|
+
const base64 = Buffer.from(bytes).toString('base64');
|
|
16
|
+
return base64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Decode base64url string to bytes
|
|
20
|
+
*/
|
|
21
|
+
function base64urlDecode(str) {
|
|
22
|
+
// Add padding if needed
|
|
23
|
+
let padded = str;
|
|
24
|
+
const mod = str.length % 4;
|
|
25
|
+
if (mod > 0) {
|
|
26
|
+
padded += '='.repeat(4 - mod);
|
|
27
|
+
}
|
|
28
|
+
// Convert base64url to base64
|
|
29
|
+
const base64 = padded.replace(/-/g, '+').replace(/_/g, '/');
|
|
30
|
+
return new Uint8Array(Buffer.from(base64, 'base64'));
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Encode UTF-8 string to base64url
|
|
34
|
+
*/
|
|
35
|
+
function base64urlEncodeString(str) {
|
|
36
|
+
return base64urlEncode(new TextEncoder().encode(str));
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Decode base64url to UTF-8 string
|
|
40
|
+
*/
|
|
41
|
+
function base64urlDecodeString(str) {
|
|
42
|
+
return new TextDecoder().decode(base64urlDecode(str));
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=base64url.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base64url.js","sourceRoot":"","sources":["../src/base64url.ts"],"names":[],"mappings":";AAAA;;;GAGG;;AAKH,0CAGC;AAKD,0CAYC;AAKD,sDAEC;AAKD,sDAEC;AArCD;;GAEG;AACH,SAAgB,eAAe,CAAC,KAAiB;IAC/C,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACrD,OAAO,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;AAC1E,CAAC;AAED;;GAEG;AACH,SAAgB,eAAe,CAAC,GAAW;IACzC,wBAAwB;IACxB,IAAI,MAAM,GAAG,GAAG,CAAC;IACjB,MAAM,GAAG,GAAG,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC;IAC3B,IAAI,GAAG,GAAG,CAAC,EAAE,CAAC;QACZ,MAAM,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC;IAChC,CAAC;IAED,8BAA8B;IAC9B,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAE5D,OAAO,IAAI,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;AACvD,CAAC;AAED;;GAEG;AACH,SAAgB,qBAAqB,CAAC,GAAW;IAC/C,OAAO,eAAe,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;AACxD,CAAC;AAED;;GAEG;AACH,SAAgB,qBAAqB,CAAC,GAAW;IAC/C,OAAO,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC;AACxD,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,cAAc,aAAa,CAAC;AAC5B,cAAc,OAAO,CAAC;AACtB,cAAc,OAAO,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* PEAC Protocol Crypto Package
|
|
4
|
+
* Ed25519 JWS signing/verification and JSON Canonicalization (RFC 8785)
|
|
5
|
+
*/
|
|
6
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
|
+
if (k2 === undefined) k2 = k;
|
|
8
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
9
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
10
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
11
|
+
}
|
|
12
|
+
Object.defineProperty(o, k2, desc);
|
|
13
|
+
}) : (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
o[k2] = m[k];
|
|
16
|
+
}));
|
|
17
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
18
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
19
|
+
};
|
|
20
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
+
__exportStar(require("./base64url"), exports);
|
|
22
|
+
__exportStar(require("./jcs"), exports);
|
|
23
|
+
__exportStar(require("./jws"), exports);
|
|
24
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;;;;;;;;;;;AAEH,8CAA4B;AAC5B,wCAAsB;AACtB,wCAAsB"}
|
package/dist/jcs.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JSON Canonicalization Scheme (RFC 8785)
|
|
3
|
+
* Deterministic JSON serialization for cryptographic hashing
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Canonicalize a JSON value according to RFC 8785
|
|
7
|
+
*/
|
|
8
|
+
export declare function canonicalize(obj: unknown): string;
|
|
9
|
+
/**
|
|
10
|
+
* Canonicalize and encode as UTF-8 bytes
|
|
11
|
+
*/
|
|
12
|
+
export declare function canonicalizeBytes(obj: unknown): Uint8Array;
|
|
13
|
+
/**
|
|
14
|
+
* Compute JCS+SHA-256 hash of an object
|
|
15
|
+
*/
|
|
16
|
+
export declare function jcsHash(obj: unknown): Promise<string>;
|
|
17
|
+
//# sourceMappingURL=jcs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jcs.d.ts","sourceRoot":"","sources":["../src/jcs.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;GAEG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CA8CjD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,GAAG,UAAU,CAG1D;AAED;;GAEG;AACH,wBAAsB,OAAO,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAO3D"}
|
package/dist/jcs.js
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* JSON Canonicalization Scheme (RFC 8785)
|
|
4
|
+
* Deterministic JSON serialization for cryptographic hashing
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.canonicalize = canonicalize;
|
|
8
|
+
exports.canonicalizeBytes = canonicalizeBytes;
|
|
9
|
+
exports.jcsHash = jcsHash;
|
|
10
|
+
/**
|
|
11
|
+
* Canonicalize a JSON value according to RFC 8785
|
|
12
|
+
*/
|
|
13
|
+
function canonicalize(obj) {
|
|
14
|
+
if (obj === null) {
|
|
15
|
+
return 'null';
|
|
16
|
+
}
|
|
17
|
+
if (typeof obj === 'boolean') {
|
|
18
|
+
return obj ? 'true' : 'false';
|
|
19
|
+
}
|
|
20
|
+
if (typeof obj === 'number') {
|
|
21
|
+
// RFC 8785 number serialization (no trailing zeros, no exponential for small numbers)
|
|
22
|
+
if (!Number.isFinite(obj)) {
|
|
23
|
+
throw new Error('Cannot canonicalize non-finite number');
|
|
24
|
+
}
|
|
25
|
+
if (Object.is(obj, -0)) {
|
|
26
|
+
return '0';
|
|
27
|
+
}
|
|
28
|
+
// Use JSON.stringify for proper number formatting per RFC 8785
|
|
29
|
+
const str = JSON.stringify(obj);
|
|
30
|
+
// Ensure no exponential notation for integers
|
|
31
|
+
if (Number.isInteger(obj) && str.includes('e')) {
|
|
32
|
+
return obj.toString();
|
|
33
|
+
}
|
|
34
|
+
return str;
|
|
35
|
+
}
|
|
36
|
+
if (typeof obj === 'string') {
|
|
37
|
+
return JSON.stringify(obj);
|
|
38
|
+
}
|
|
39
|
+
if (Array.isArray(obj)) {
|
|
40
|
+
const elements = obj.map(canonicalize);
|
|
41
|
+
return `[${elements.join(',')}]`;
|
|
42
|
+
}
|
|
43
|
+
if (typeof obj === 'object') {
|
|
44
|
+
// Sort keys lexicographically by UTF-16 code unit
|
|
45
|
+
const keys = Object.keys(obj).sort();
|
|
46
|
+
const pairs = keys.map((key) => {
|
|
47
|
+
const value = obj[key];
|
|
48
|
+
return `${JSON.stringify(key)}:${canonicalize(value)}`;
|
|
49
|
+
});
|
|
50
|
+
return `{${pairs.join(',')}}`;
|
|
51
|
+
}
|
|
52
|
+
throw new Error(`Cannot canonicalize type: ${typeof obj}`);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Canonicalize and encode as UTF-8 bytes
|
|
56
|
+
*/
|
|
57
|
+
function canonicalizeBytes(obj) {
|
|
58
|
+
const canonical = canonicalize(obj);
|
|
59
|
+
return new TextEncoder().encode(canonical);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Compute JCS+SHA-256 hash of an object
|
|
63
|
+
*/
|
|
64
|
+
async function jcsHash(obj) {
|
|
65
|
+
const bytes = canonicalizeBytes(obj);
|
|
66
|
+
const hashBuffer = await crypto.subtle.digest('SHA-256', bytes);
|
|
67
|
+
const hashArray = new Uint8Array(hashBuffer);
|
|
68
|
+
return Array.from(hashArray)
|
|
69
|
+
.map((b) => b.toString(16).padStart(2, '0'))
|
|
70
|
+
.join('');
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=jcs.js.map
|
package/dist/jcs.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jcs.js","sourceRoot":"","sources":["../src/jcs.ts"],"names":[],"mappings":";AAAA;;;GAGG;;AAKH,oCA8CC;AAKD,8CAGC;AAKD,0BAOC;AArED;;GAEG;AACH,SAAgB,YAAY,CAAC,GAAY;IACvC,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;QACjB,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,IAAI,OAAO,GAAG,KAAK,SAAS,EAAE,CAAC;QAC7B,OAAO,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;IAChC,CAAC;IAED,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC5B,sFAAsF;QACtF,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;QAC3D,CAAC;QACD,IAAI,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACvB,OAAO,GAAG,CAAC;QACb,CAAC;QACD,+DAA+D;QAC/D,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QAChC,8CAA8C;QAC9C,IAAI,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YAC/C,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAC;QACxB,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IAED,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC5B,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IAC7B,CAAC;IAED,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,QAAQ,GAAG,GAAG,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QACvC,OAAO,IAAI,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;IACnC,CAAC;IAED,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC5B,kDAAkD;QAClD,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;QACrC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;YAC7B,MAAM,KAAK,GAAI,GAA+B,CAAC,GAAG,CAAC,CAAC;YACpD,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;QACzD,CAAC,CAAC,CAAC;QACH,OAAO,IAAI,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;IAChC,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,6BAA6B,OAAO,GAAG,EAAE,CAAC,CAAC;AAC7D,CAAC;AAED;;GAEG;AACH,SAAgB,iBAAiB,CAAC,GAAY;IAC5C,MAAM,SAAS,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;IACpC,OAAO,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;AAC7C,CAAC;AAED;;GAEG;AACI,KAAK,UAAU,OAAO,CAAC,GAAY;IACxC,MAAM,KAAK,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC;IACrC,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IAChE,MAAM,SAAS,GAAG,IAAI,UAAU,CAAC,UAAU,CAAC,CAAC;IAC7C,OAAO,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC;SACzB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;SAC3C,IAAI,CAAC,EAAE,CAAC,CAAC;AACd,CAAC"}
|
package/dist/jws.d.ts
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JWS compact serialization with Ed25519 (RFC 8032)
|
|
3
|
+
* Implements peac.receipt/0.9 wire format
|
|
4
|
+
*/
|
|
5
|
+
import { PEAC_WIRE_TYP, PEAC_ALG } from '@peac/schema';
|
|
6
|
+
/**
|
|
7
|
+
* JWS header for PEAC receipts
|
|
8
|
+
*/
|
|
9
|
+
export interface JWSHeader {
|
|
10
|
+
typ: typeof PEAC_WIRE_TYP;
|
|
11
|
+
alg: typeof PEAC_ALG;
|
|
12
|
+
kid: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Result of JWS verification
|
|
16
|
+
*/
|
|
17
|
+
export interface VerifyResult<T = unknown> {
|
|
18
|
+
header: JWSHeader;
|
|
19
|
+
payload: T;
|
|
20
|
+
valid: boolean;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Sign a payload with Ed25519 and return JWS compact serialization
|
|
24
|
+
*
|
|
25
|
+
* @param payload - JSON-serializable payload
|
|
26
|
+
* @param privateKey - Ed25519 private key (32 bytes)
|
|
27
|
+
* @param kid - Key ID (ISO 8601 timestamp)
|
|
28
|
+
* @returns JWS compact serialization (header.payload.signature)
|
|
29
|
+
*/
|
|
30
|
+
export declare function sign(payload: unknown, privateKey: Uint8Array, kid: string): Promise<string>;
|
|
31
|
+
/**
|
|
32
|
+
* Verify a JWS compact serialization with Ed25519
|
|
33
|
+
*
|
|
34
|
+
* @param jws - JWS compact serialization
|
|
35
|
+
* @param publicKey - Ed25519 public key (32 bytes)
|
|
36
|
+
* @returns Verification result with decoded header and payload
|
|
37
|
+
*/
|
|
38
|
+
export declare function verify<T = unknown>(jws: string, publicKey: Uint8Array): Promise<VerifyResult<T>>;
|
|
39
|
+
/**
|
|
40
|
+
* Decode JWS without verifying signature (use with caution!)
|
|
41
|
+
*
|
|
42
|
+
* @param jws - JWS compact serialization
|
|
43
|
+
* @returns Decoded header and payload (unverified)
|
|
44
|
+
*/
|
|
45
|
+
export declare function decode<T = unknown>(jws: string): {
|
|
46
|
+
header: JWSHeader;
|
|
47
|
+
payload: T;
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* Generate a random Ed25519 keypair
|
|
51
|
+
*
|
|
52
|
+
* @returns Private key (32 bytes) and public key (32 bytes)
|
|
53
|
+
*/
|
|
54
|
+
export declare function generateKeypair(): Promise<{
|
|
55
|
+
privateKey: Uint8Array;
|
|
56
|
+
publicKey: Uint8Array;
|
|
57
|
+
}>;
|
|
58
|
+
//# sourceMappingURL=jws.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jws.d.ts","sourceRoot":"","sources":["../src/jws.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAQvD;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,OAAO,aAAa,CAAC;IAC1B,GAAG,EAAE,OAAO,QAAQ,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;GAEG;AACH,MAAM,WAAW,YAAY,CAAC,CAAC,GAAG,OAAO;IACvC,MAAM,EAAE,SAAS,CAAC;IAClB,OAAO,EAAE,CAAC,CAAC;IACX,KAAK,EAAE,OAAO,CAAC;CAChB;AAED;;;;;;;GAOG;AACH,wBAAsB,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CA4BjG;AAED;;;;;;GAMG;AACH,wBAAsB,MAAM,CAAC,CAAC,GAAG,OAAO,EACtC,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,UAAU,GACpB,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CA2C1B;AAED;;;;;GAKG;AACH,wBAAgB,MAAM,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,CAAC,CAAA;CAAE,CAelF;AAED;;;;GAIG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC;IAC/C,UAAU,EAAE,UAAU,CAAC;IACvB,SAAS,EAAE,UAAU,CAAC;CACvB,CAAC,CAKD"}
|
package/dist/jws.js
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* JWS compact serialization with Ed25519 (RFC 8032)
|
|
4
|
+
* Implements peac.receipt/0.9 wire format
|
|
5
|
+
*/
|
|
6
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
|
+
if (k2 === undefined) k2 = k;
|
|
8
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
9
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
10
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
11
|
+
}
|
|
12
|
+
Object.defineProperty(o, k2, desc);
|
|
13
|
+
}) : (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
o[k2] = m[k];
|
|
16
|
+
}));
|
|
17
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
18
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
19
|
+
}) : function(o, v) {
|
|
20
|
+
o["default"] = v;
|
|
21
|
+
});
|
|
22
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
23
|
+
var ownKeys = function(o) {
|
|
24
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
25
|
+
var ar = [];
|
|
26
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
27
|
+
return ar;
|
|
28
|
+
};
|
|
29
|
+
return ownKeys(o);
|
|
30
|
+
};
|
|
31
|
+
return function (mod) {
|
|
32
|
+
if (mod && mod.__esModule) return mod;
|
|
33
|
+
var result = {};
|
|
34
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
35
|
+
__setModuleDefault(result, mod);
|
|
36
|
+
return result;
|
|
37
|
+
};
|
|
38
|
+
})();
|
|
39
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
+
exports.sign = sign;
|
|
41
|
+
exports.verify = verify;
|
|
42
|
+
exports.decode = decode;
|
|
43
|
+
exports.generateKeypair = generateKeypair;
|
|
44
|
+
const ed25519 = __importStar(require("@noble/ed25519"));
|
|
45
|
+
const schema_1 = require("@peac/schema");
|
|
46
|
+
const base64url_1 = require("./base64url");
|
|
47
|
+
/**
|
|
48
|
+
* Sign a payload with Ed25519 and return JWS compact serialization
|
|
49
|
+
*
|
|
50
|
+
* @param payload - JSON-serializable payload
|
|
51
|
+
* @param privateKey - Ed25519 private key (32 bytes)
|
|
52
|
+
* @param kid - Key ID (ISO 8601 timestamp)
|
|
53
|
+
* @returns JWS compact serialization (header.payload.signature)
|
|
54
|
+
*/
|
|
55
|
+
async function sign(payload, privateKey, kid) {
|
|
56
|
+
if (privateKey.length !== 32) {
|
|
57
|
+
throw new Error('Ed25519 private key must be 32 bytes');
|
|
58
|
+
}
|
|
59
|
+
// Create header
|
|
60
|
+
const header = {
|
|
61
|
+
typ: schema_1.PEAC_WIRE_TYP,
|
|
62
|
+
alg: schema_1.PEAC_ALG,
|
|
63
|
+
kid,
|
|
64
|
+
};
|
|
65
|
+
// Encode header and payload
|
|
66
|
+
const headerB64 = (0, base64url_1.base64urlEncodeString)(JSON.stringify(header));
|
|
67
|
+
const payloadB64 = (0, base64url_1.base64urlEncodeString)(JSON.stringify(payload));
|
|
68
|
+
// Create signing input
|
|
69
|
+
const signingInput = `${headerB64}.${payloadB64}`;
|
|
70
|
+
const signingInputBytes = new TextEncoder().encode(signingInput);
|
|
71
|
+
// Sign with Ed25519
|
|
72
|
+
const signatureBytes = await ed25519.signAsync(signingInputBytes, privateKey);
|
|
73
|
+
// Encode signature
|
|
74
|
+
const signatureB64 = (0, base64url_1.base64urlEncode)(signatureBytes);
|
|
75
|
+
// Return JWS compact serialization
|
|
76
|
+
return `${signingInput}.${signatureB64}`;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Verify a JWS compact serialization with Ed25519
|
|
80
|
+
*
|
|
81
|
+
* @param jws - JWS compact serialization
|
|
82
|
+
* @param publicKey - Ed25519 public key (32 bytes)
|
|
83
|
+
* @returns Verification result with decoded header and payload
|
|
84
|
+
*/
|
|
85
|
+
async function verify(jws, publicKey) {
|
|
86
|
+
if (publicKey.length !== 32) {
|
|
87
|
+
throw new Error('Ed25519 public key must be 32 bytes');
|
|
88
|
+
}
|
|
89
|
+
// Split JWS
|
|
90
|
+
const parts = jws.split('.');
|
|
91
|
+
if (parts.length !== 3) {
|
|
92
|
+
throw new Error('Invalid JWS: must have three dot-separated parts');
|
|
93
|
+
}
|
|
94
|
+
const [headerB64, payloadB64, signatureB64] = parts;
|
|
95
|
+
// Decode header
|
|
96
|
+
const headerJson = (0, base64url_1.base64urlDecodeString)(headerB64);
|
|
97
|
+
const header = JSON.parse(headerJson);
|
|
98
|
+
// Validate header
|
|
99
|
+
if (header.typ !== schema_1.PEAC_WIRE_TYP) {
|
|
100
|
+
throw new Error(`Invalid typ: expected ${schema_1.PEAC_WIRE_TYP}, got ${header.typ}`);
|
|
101
|
+
}
|
|
102
|
+
if (header.alg !== schema_1.PEAC_ALG) {
|
|
103
|
+
throw new Error(`Invalid alg: expected ${schema_1.PEAC_ALG}, got ${header.alg}`);
|
|
104
|
+
}
|
|
105
|
+
// Decode payload
|
|
106
|
+
const payloadJson = (0, base64url_1.base64urlDecodeString)(payloadB64);
|
|
107
|
+
const payload = JSON.parse(payloadJson);
|
|
108
|
+
// Decode signature
|
|
109
|
+
const signatureBytes = (0, base64url_1.base64urlDecode)(signatureB64);
|
|
110
|
+
// Verify signature
|
|
111
|
+
const signingInput = `${headerB64}.${payloadB64}`;
|
|
112
|
+
const signingInputBytes = new TextEncoder().encode(signingInput);
|
|
113
|
+
const valid = await ed25519.verifyAsync(signatureBytes, signingInputBytes, publicKey);
|
|
114
|
+
return {
|
|
115
|
+
header,
|
|
116
|
+
payload,
|
|
117
|
+
valid,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Decode JWS without verifying signature (use with caution!)
|
|
122
|
+
*
|
|
123
|
+
* @param jws - JWS compact serialization
|
|
124
|
+
* @returns Decoded header and payload (unverified)
|
|
125
|
+
*/
|
|
126
|
+
function decode(jws) {
|
|
127
|
+
const parts = jws.split('.');
|
|
128
|
+
if (parts.length !== 3) {
|
|
129
|
+
throw new Error('Invalid JWS: must have three dot-separated parts');
|
|
130
|
+
}
|
|
131
|
+
const [headerB64, payloadB64] = parts;
|
|
132
|
+
const headerJson = (0, base64url_1.base64urlDecodeString)(headerB64);
|
|
133
|
+
const header = JSON.parse(headerJson);
|
|
134
|
+
const payloadJson = (0, base64url_1.base64urlDecodeString)(payloadB64);
|
|
135
|
+
const payload = JSON.parse(payloadJson);
|
|
136
|
+
return { header, payload };
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Generate a random Ed25519 keypair
|
|
140
|
+
*
|
|
141
|
+
* @returns Private key (32 bytes) and public key (32 bytes)
|
|
142
|
+
*/
|
|
143
|
+
async function generateKeypair() {
|
|
144
|
+
const privateKey = ed25519.utils.randomPrivateKey();
|
|
145
|
+
const publicKey = await ed25519.getPublicKeyAsync(privateKey);
|
|
146
|
+
return { privateKey, publicKey };
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=jws.js.map
|
package/dist/jws.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jws.js","sourceRoot":"","sources":["../src/jws.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@peac/crypto",
|
|
3
|
+
"version": "0.9.18",
|
|
4
|
+
"description": "Ed25519 JWS signing and verification for PEAC protocol",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/peacprotocol/peac.git",
|
|
10
|
+
"directory": "packages/crypto"
|
|
11
|
+
},
|
|
12
|
+
"author": "jithinraj <7850727+jithinraj@users.noreply.github.com>",
|
|
13
|
+
"license": "Apache-2.0",
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/peacprotocol/peac/issues"
|
|
16
|
+
},
|
|
17
|
+
"homepage": "https://github.com/peacprotocol/peac#readme",
|
|
18
|
+
"files": [
|
|
19
|
+
"dist",
|
|
20
|
+
"README.md"
|
|
21
|
+
],
|
|
22
|
+
"publishConfig": {
|
|
23
|
+
"access": "public"
|
|
24
|
+
},
|
|
25
|
+
"scripts": {
|
|
26
|
+
"build": "tsc",
|
|
27
|
+
"test": "vitest run",
|
|
28
|
+
"test:watch": "vitest",
|
|
29
|
+
"clean": "rm -rf dist"
|
|
30
|
+
},
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"@noble/ed25519": "^2.0.0",
|
|
33
|
+
"@peac/schema": "workspace:*"
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"@types/node": "^20.10.0",
|
|
37
|
+
"typescript": "^5.3.3",
|
|
38
|
+
"vitest": "^1.1.0"
|
|
39
|
+
}
|
|
40
|
+
}
|