@passportsign/core 0.1.0 → 0.2.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/badge.d.ts +5 -0
- package/dist/badge.d.ts.map +1 -1
- package/dist/badge.js +8 -2
- package/dist/badge.js.map +1 -1
- package/dist/bind.d.ts.map +1 -1
- package/dist/bind.js +2 -8
- package/dist/bind.js.map +1 -1
- package/dist/bundle-fs.d.ts +16 -0
- package/dist/bundle-fs.d.ts.map +1 -0
- package/dist/bundle-fs.js +31 -0
- package/dist/bundle-fs.js.map +1 -0
- package/dist/bundle.d.ts +13 -5
- package/dist/bundle.d.ts.map +1 -1
- package/dist/bundle.js +18 -20
- package/dist/bundle.js.map +1 -1
- package/dist/canonical.d.ts.map +1 -1
- package/dist/canonical.js +3 -4
- package/dist/canonical.js.map +1 -1
- package/dist/classify.d.ts +68 -0
- package/dist/classify.d.ts.map +1 -0
- package/dist/classify.js +117 -0
- package/dist/classify.js.map +1 -0
- package/dist/dsse-common.d.ts +32 -0
- package/dist/dsse-common.d.ts.map +1 -0
- package/dist/dsse-common.js +26 -0
- package/dist/dsse-common.js.map +1 -0
- package/dist/dsse-web.d.ts +28 -0
- package/dist/dsse-web.d.ts.map +1 -0
- package/dist/dsse-web.js +81 -0
- package/dist/dsse-web.js.map +1 -0
- package/dist/dsse.d.ts +2 -26
- package/dist/dsse.d.ts.map +1 -1
- package/dist/dsse.js +2 -19
- package/dist/dsse.js.map +1 -1
- package/dist/encoding.d.ts +20 -0
- package/dist/encoding.d.ts.map +1 -0
- package/dist/encoding.js +88 -0
- package/dist/encoding.js.map +1 -0
- package/dist/github.js +2 -2
- package/dist/github.js.map +1 -1
- package/dist/index.d.ts +9 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -2
- package/dist/index.js.map +1 -1
- package/dist/log/rekor.d.ts +1 -1
- package/dist/log/rekor.d.ts.map +1 -1
- package/dist/log/rekor.js +7 -10
- package/dist/log/rekor.js.map +1 -1
- package/dist/lookup.d.ts +46 -0
- package/dist/lookup.d.ts.map +1 -0
- package/dist/lookup.js +101 -0
- package/dist/lookup.js.map +1 -0
- package/dist/merkle.js +3 -3
- package/dist/merkle.js.map +1 -1
- package/dist/nonce.js +1 -1
- package/dist/nonce.js.map +1 -1
- package/dist/profile-index.d.ts +64 -0
- package/dist/profile-index.d.ts.map +1 -0
- package/dist/profile-index.js +161 -0
- package/dist/profile-index.js.map +1 -0
- package/dist/revoke.d.ts +30 -0
- package/dist/revoke.d.ts.map +1 -0
- package/dist/revoke.js +42 -0
- package/dist/revoke.js.map +1 -0
- package/dist/sdk-payload.d.ts.map +1 -1
- package/dist/sdk-payload.js +4 -6
- package/dist/sdk-payload.js.map +1 -1
- package/dist/statement.d.ts +41 -0
- package/dist/statement.d.ts.map +1 -1
- package/dist/statement.js +43 -0
- package/dist/statement.js.map +1 -1
- package/dist/submit.d.ts +3 -3
- package/dist/submit.d.ts.map +1 -1
- package/dist/submit.js +3 -14
- package/dist/submit.js.map +1 -1
- package/dist/verifier.d.ts.map +1 -1
- package/dist/verifier.js +4 -14
- package/dist/verifier.js.map +1 -1
- package/dist/web.d.ts +35 -0
- package/dist/web.d.ts.map +1 -0
- package/dist/web.js +35 -0
- package/dist/web.js.map +1 -0
- package/package.json +6 -2
- package/src/badge.ts +124 -113
- package/src/bind.ts +128 -137
- package/src/bundle-fs.ts +40 -0
- package/src/bundle.ts +138 -127
- package/src/canonical.ts +33 -33
- package/src/classify.ts +165 -0
- package/src/dsse-common.ts +45 -0
- package/src/dsse-web.ts +97 -0
- package/src/dsse.ts +63 -91
- package/src/encoding.ts +96 -0
- package/src/github.ts +196 -196
- package/src/index.ts +59 -2
- package/src/log/rekor.ts +330 -334
- package/src/lookup.ts +175 -0
- package/src/merkle.ts +187 -187
- package/src/nonce.ts +53 -53
- package/src/profile-index.ts +222 -0
- package/src/revoke.ts +67 -0
- package/src/sdk-payload.ts +60 -62
- package/src/statement.ts +203 -119
- package/src/submit.ts +38 -54
- package/src/verifier.ts +304 -317
- package/src/web.ts +175 -0
package/dist/badge.d.ts
CHANGED
|
@@ -17,6 +17,11 @@ export interface BadgeInput {
|
|
|
17
17
|
bound_at: string;
|
|
18
18
|
/** Rekor entry UUID for the `<title>` tooltip. */
|
|
19
19
|
log_entry_hash?: string;
|
|
20
|
+
/**
|
|
21
|
+
* Binding state (spec §4 color logic). Defaults to `'active'` so
|
|
22
|
+
* v0-era callers (static badges) are unchanged.
|
|
23
|
+
*/
|
|
24
|
+
state?: 'active' | 'stale' | 'revoked';
|
|
20
25
|
}
|
|
21
26
|
/**
|
|
22
27
|
* Render the badge SVG. The output is intentionally a string (not a
|
package/dist/badge.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"badge.d.ts","sourceRoot":"","sources":["../src/badge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,MAAM,WAAW,UAAU;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,kDAAkD;IAClD,cAAc,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"badge.d.ts","sourceRoot":"","sources":["../src/badge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,MAAM,WAAW,UAAU;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,kDAAkD;IAClD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,KAAK,CAAC,EAAE,QAAQ,GAAG,OAAO,GAAG,SAAS,CAAC;CACxC;AAkCD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CA2CxD;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE;IACzC,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,GAAG,MAAM,CAKT"}
|
package/dist/badge.js
CHANGED
|
@@ -12,6 +12,11 @@
|
|
|
12
12
|
* trick used by shields.io for crisper text rendering.
|
|
13
13
|
*/
|
|
14
14
|
const LABEL = 'passportsign';
|
|
15
|
+
const STATE_COLORS = {
|
|
16
|
+
active: '#4c1',
|
|
17
|
+
stale: '#dfb317',
|
|
18
|
+
revoked: '#e05d44',
|
|
19
|
+
};
|
|
15
20
|
const CHAR_WIDTH_PX = 7; // Approx Verdana 11pt character width
|
|
16
21
|
const SIDE_PADDING_PX = 8;
|
|
17
22
|
function escapeXml(s) {
|
|
@@ -42,8 +47,9 @@ function dateStringFor(isoTimestamp) {
|
|
|
42
47
|
* `writeFileSync`.
|
|
43
48
|
*/
|
|
44
49
|
export function renderBadgeSvg(input) {
|
|
50
|
+
const state = input.state ?? 'active';
|
|
45
51
|
const date = dateStringFor(input.bound_at);
|
|
46
|
-
const valueParts = ['verified human'];
|
|
52
|
+
const valueParts = [state === 'revoked' ? 'revoked' : 'verified human'];
|
|
47
53
|
if (input.issuing_country)
|
|
48
54
|
valueParts.push(input.issuing_country);
|
|
49
55
|
valueParts.push(date);
|
|
@@ -69,7 +75,7 @@ export function renderBadgeSvg(input) {
|
|
|
69
75
|
`<clipPath id="r"><rect width="${totalW}" height="20" rx="3" fill="#fff"/></clipPath>`,
|
|
70
76
|
`<g clip-path="url(#r)">`,
|
|
71
77
|
`<rect width="${labelW}" height="20" fill="#555"/>`,
|
|
72
|
-
`<rect x="${labelW}" width="${valueW}" height="20" fill="
|
|
78
|
+
`<rect x="${labelW}" width="${valueW}" height="20" fill="${STATE_COLORS[state]}"/>`,
|
|
73
79
|
`<rect width="${totalW}" height="20" fill="url(#s)"/>`,
|
|
74
80
|
`</g>`,
|
|
75
81
|
`<g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110">`,
|
package/dist/badge.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"badge.js","sourceRoot":"","sources":["../src/badge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;
|
|
1
|
+
{"version":3,"file":"badge.js","sourceRoot":"","sources":["../src/badge.ts"],"names":[],"mappings":"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"}
|
package/dist/bind.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bind.d.ts","sourceRoot":"","sources":["../src/bind.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;
|
|
1
|
+
{"version":3,"file":"bind.d.ts","sourceRoot":"","sources":["../src/bind.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAKH,OAAO,EAAE,gBAAgB,EAAE,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,EAAkB,KAAK,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAE5E,MAAM,WAAW,mBAAmB;IAClC,eAAe,EAAE,MAAM,CAAC;IACxB,mFAAmF;IACnF,cAAc,EAAE,MAAM,CAAC;IACvB,mFAAmF;IACnF,iBAAiB,EAAE,MAAM,CAAC;IAC1B,mFAAmF;IACnF,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,kFAAkF;IAClF,KAAK,EAAE,MAAM,CAAC;IACd,0EAA0E;IAC1E,KAAK,EAAE,MAAM,CAAC;IACd,sEAAsE;IACtE,sBAAsB,EAAE,MAAM,CAAC;IAC/B,uFAAuF;IACvF,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,kBAAkB;IACjC,mEAAmE;IACnE,QAAQ,EAAE,IAAI,CAAC;IACf,gFAAgF;IAChF,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,kBAAkB;IACjC,8DAA8D;IAC9D,MAAM,CAAC,EAAE,OAAO,gBAAgB,CAAC;IACjC,4CAA4C;IAC5C,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;CACtB;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,qBAAqB,CAAC;IACjC,mBAAmB,EAAE,UAAU,CAAC;IAChC,oBAAoB,EAAE,MAAM,CAAC;IAC7B,cAAc,EAAE,MAAM,CAAC;IACvB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,IAAI,EAAE,YAAY,CAAC;CACpB;AAID;;;;;;GAMG;AACH,wBAAsB,cAAc,CAClC,KAAK,EAAE,mBAAmB,EAC1B,IAAI,EAAE,kBAAkB,EACxB,IAAI,GAAE,kBAAuB,GAC5B,OAAO,CAAC,eAAe,CAAC,CAqD1B"}
|
package/dist/bind.js
CHANGED
|
@@ -11,18 +11,12 @@
|
|
|
11
11
|
* command is the producer of that data (it drives the SDK + UI),
|
|
12
12
|
* keeping this module pure and unit-testable without the SDK.
|
|
13
13
|
*/
|
|
14
|
-
import { createHash } from 'node:crypto';
|
|
15
14
|
import { canonicalize, canonicalSha256Hex } from './canonical.js';
|
|
15
|
+
import { base64ToBytes, sha256Hex } from './encoding.js';
|
|
16
16
|
import { PassportsignError } from './errors.js';
|
|
17
17
|
import { checkGistControl } from './github.js';
|
|
18
18
|
import { buildStatement } from './statement.js';
|
|
19
19
|
const DEFAULT_GIST_FILENAME = 'passportsign.txt';
|
|
20
|
-
function decodeBase64(b64) {
|
|
21
|
-
return new Uint8Array(Buffer.from(b64, 'base64'));
|
|
22
|
-
}
|
|
23
|
-
function sha256Hex(bytes) {
|
|
24
|
-
return createHash('sha256').update(bytes).digest('hex');
|
|
25
|
-
}
|
|
26
20
|
/**
|
|
27
21
|
* Run the GitHub gist control check, then build the in-toto statement and
|
|
28
22
|
* compute canonical bytes + hashes for the Rekor handoff.
|
|
@@ -44,7 +38,7 @@ export async function prepareBinding(input, init, deps = {}) {
|
|
|
44
38
|
// 2. Derive proof_blob sha256 from the base64 input.
|
|
45
39
|
let proofBytes;
|
|
46
40
|
try {
|
|
47
|
-
proofBytes =
|
|
41
|
+
proofBytes = base64ToBytes(input.proof_blob_b64);
|
|
48
42
|
}
|
|
49
43
|
catch (err) {
|
|
50
44
|
throw new PassportsignError('proof_invalid', `proof_blob_b64 is not valid base64`, err);
|
package/dist/bind.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bind.js","sourceRoot":"","sources":["../src/bind.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"bind.js","sourceRoot":"","sources":["../src/bind.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAClE,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAqB,MAAM,aAAa,CAAC;AAClE,OAAO,EAAE,cAAc,EAA8B,MAAM,gBAAgB,CAAC;AA2C5E,MAAM,qBAAqB,GAAG,kBAAkB,CAAC;AAEjD;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,KAA0B,EAC1B,IAAwB,EACxB,OAA2B,EAAE;IAE7B,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,IAAI,gBAAgB,CAAC;IAEnD,0EAA0E;IAC1E,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC;QAC5B,QAAQ,EAAE,KAAK,CAAC,eAAe;QAC/B,iBAAiB,EAAE,IAAI,CAAC,YAAY,IAAI,qBAAqB;QAC7D,gBAAgB,EAAE,KAAK,CAAC,KAAK;QAC7B,UAAU,EAAE,IAAI,CAAC,QAAQ;QACzB,GAAG,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5D,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC7C,CAAC,CAAC;IAEH,qDAAqD;IACrD,IAAI,UAAsB,CAAC;IAC3B,IAAI,CAAC;QACH,UAAU,GAAG,aAAa,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;IACnD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,iBAAiB,CACzB,eAAe,EACf,oCAAoC,EACpC,GAAG,CACJ,CAAC;IACJ,CAAC;IACD,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,iBAAiB,CAAC,eAAe,EAAE,sCAAsC,CAAC,CAAC;IACvF,CAAC;IACD,MAAM,qBAAqB,GAAG,SAAS,CAAC,UAAU,CAAC,CAAC;IAEpD,wEAAwE;IACxE,MAAM,SAAS,GAAG,cAAc,CAAC;QAC/B,eAAe,EAAE,KAAK,CAAC,eAAe;QACtC,iBAAiB,EAAE,KAAK,CAAC,iBAAiB;QAC1C,eAAe,EAAE,KAAK,CAAC,eAAe;QACtC,iBAAiB,EAAE,qBAAqB;QACxC,QAAQ,EAAE,IAAI,CAAC,GAAG;QAClB,mBAAmB,EAAE,IAAI,CAAC,cAAc;QACxC,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,sBAAsB,EAAE,KAAK,CAAC,sBAAsB;KACrD,CAAC,CAAC;IAEH,mDAAmD;IACnD,MAAM,mBAAmB,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC;IACpD,MAAM,oBAAoB,GAAG,kBAAkB,CAAC,SAAS,CAAC,CAAC;IAE3D,OAAO;QACL,SAAS;QACT,mBAAmB;QACnB,oBAAoB;QACpB,cAAc,EAAE,KAAK,CAAC,cAAc;QACpC,qBAAqB;QACrB,IAAI;KACL,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Node-only file I/O for `binding.passportsign.json` bundles. Kept out
|
|
3
|
+
* of `bundle.ts` so the validation logic stays runtime-neutral (the
|
|
4
|
+
* `./web` subpath exports validation but not these).
|
|
5
|
+
*/
|
|
6
|
+
import { type PassportsignBundle } from './bundle.js';
|
|
7
|
+
/**
|
|
8
|
+
* Read and validate a `binding.passportsign.json` file. Throws on
|
|
9
|
+
* invalid JSON or schema violations.
|
|
10
|
+
*/
|
|
11
|
+
export declare function readBundle(path: string): PassportsignBundle;
|
|
12
|
+
/**
|
|
13
|
+
* Validate and write a `binding.passportsign.json` file (pretty-printed).
|
|
14
|
+
*/
|
|
15
|
+
export declare function writeBundle(path: string, bundle: PassportsignBundle): void;
|
|
16
|
+
//# sourceMappingURL=bundle-fs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bundle-fs.d.ts","sourceRoot":"","sources":["../src/bundle-fs.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,EAGL,KAAK,kBAAkB,EACxB,MAAM,aAAa,CAAC;AAErB;;;GAGG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,kBAAkB,CAa3D;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,kBAAkB,GAAG,IAAI,CAG1E"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Node-only file I/O for `binding.passportsign.json` bundles. Kept out
|
|
3
|
+
* of `bundle.ts` so the validation logic stays runtime-neutral (the
|
|
4
|
+
* `./web` subpath exports validation but not these).
|
|
5
|
+
*/
|
|
6
|
+
import { readFileSync, writeFileSync } from 'node:fs';
|
|
7
|
+
import { BundleValidationError, validateBundle, } from './bundle.js';
|
|
8
|
+
/**
|
|
9
|
+
* Read and validate a `binding.passportsign.json` file. Throws on
|
|
10
|
+
* invalid JSON or schema violations.
|
|
11
|
+
*/
|
|
12
|
+
export function readBundle(path) {
|
|
13
|
+
const raw = readFileSync(path, 'utf8');
|
|
14
|
+
let parsed;
|
|
15
|
+
try {
|
|
16
|
+
parsed = JSON.parse(raw);
|
|
17
|
+
}
|
|
18
|
+
catch (err) {
|
|
19
|
+
throw new BundleValidationError('$', `invalid JSON: ${err instanceof Error ? err.message : String(err)}`);
|
|
20
|
+
}
|
|
21
|
+
validateBundle(parsed);
|
|
22
|
+
return parsed;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Validate and write a `binding.passportsign.json` file (pretty-printed).
|
|
26
|
+
*/
|
|
27
|
+
export function writeBundle(path, bundle) {
|
|
28
|
+
validateBundle(bundle);
|
|
29
|
+
writeFileSync(path, JSON.stringify(bundle, null, 2) + '\n', 'utf8');
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=bundle-fs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bundle-fs.js","sourceRoot":"","sources":["../src/bundle-fs.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAEtD,OAAO,EACL,qBAAqB,EACrB,cAAc,GAEf,MAAM,aAAa,CAAC;AAErB;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACvC,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,qBAAqB,CAC7B,GAAG,EACH,iBAAiB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CACpE,CAAC;IACJ,CAAC;IACD,cAAc,CAAC,MAAM,CAAC,CAAC;IACvB,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,IAAY,EAAE,MAA0B;IAClE,cAAc,CAAC,MAAM,CAAC,CAAC;IACvB,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC,CAAC;AACtE,CAAC"}
|
package/dist/bundle.d.ts
CHANGED
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
* shape gets pinned in Day 5 after we've smoke-tested the public Sigstore
|
|
13
13
|
* Rekor response format.
|
|
14
14
|
*/
|
|
15
|
+
import { type RekorEntryResponse } from './log/rekor.js';
|
|
15
16
|
export declare const BUNDLE_FORMAT_VERSION: 1;
|
|
16
17
|
export interface RekorBundleFields {
|
|
17
18
|
log_entry_hash: string;
|
|
@@ -36,12 +37,19 @@ export declare class BundleValidationError extends Error {
|
|
|
36
37
|
*/
|
|
37
38
|
export declare function validateBundle(value: unknown): asserts value is PassportsignBundle;
|
|
38
39
|
/**
|
|
39
|
-
*
|
|
40
|
-
*
|
|
40
|
+
* What bundle assembly needs from a prepared statement — satisfied by
|
|
41
|
+
* both `PreparedBinding` and `PreparedRevocation`. The statement kind
|
|
42
|
+
* doesn't matter; Rekor sees canonical bytes either way.
|
|
41
43
|
*/
|
|
42
|
-
export
|
|
44
|
+
export interface SubmittableStatement {
|
|
45
|
+
statement_canonical: Uint8Array;
|
|
46
|
+
proof_blob_b64: string;
|
|
47
|
+
}
|
|
43
48
|
/**
|
|
44
|
-
*
|
|
49
|
+
* Assemble (and validate) the portable bundle from a prepared
|
|
50
|
+
* statement and the Rekor entry it produced. Pure — used by the node
|
|
51
|
+
* `submitBinding` path and by runtimes that sign with
|
|
52
|
+
* `signEnvelopeWeb` and submit through the Rekor client themselves.
|
|
45
53
|
*/
|
|
46
|
-
export declare function
|
|
54
|
+
export declare function assembleBundle(prepared: SubmittableStatement, rekorEntry: RekorEntryResponse): PassportsignBundle;
|
|
47
55
|
//# sourceMappingURL=bundle.d.ts.map
|
package/dist/bundle.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bundle.d.ts","sourceRoot":"","sources":["../src/bundle.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;
|
|
1
|
+
{"version":3,"file":"bundle.d.ts","sourceRoot":"","sources":["../src/bundle.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,EAAE,KAAK,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAEzD,eAAO,MAAM,qBAAqB,EAAG,CAAU,CAAC;AAEhD,MAAM,WAAW,iBAAiB;IAChC,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,OAAO,CAAC;IACzB,sBAAsB,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,kBAAkB;IACjC,qBAAqB,EAAE,OAAO,qBAAqB,CAAC;IACpD,gEAAgE;IAChE,SAAS,EAAE,MAAM,CAAC;IAClB,4CAA4C;IAC5C,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,iBAAiB,CAAC;CAC1B;AAOD,qBAAa,qBAAsB,SAAQ,KAAK;IAE5C,QAAQ,CAAC,IAAI,EAAE,MAAM;gBAAZ,IAAI,EAAE,MAAM,EACrB,OAAO,EAAE,MAAM;CAKlB;AAUD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,KAAK,IAAI,kBAAkB,CAsClF;AAKD;;;;GAIG;AACH,MAAM,WAAW,oBAAoB;IACnC,mBAAmB,EAAE,UAAU,CAAC;IAChC,cAAc,EAAE,MAAM,CAAC;CACxB;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,oBAAoB,EAC9B,UAAU,EAAE,kBAAkB,GAC7B,kBAAkB,CAapB"}
|
package/dist/bundle.js
CHANGED
|
@@ -12,7 +12,8 @@
|
|
|
12
12
|
* shape gets pinned in Day 5 after we've smoke-tested the public Sigstore
|
|
13
13
|
* Rekor response format.
|
|
14
14
|
*/
|
|
15
|
-
import {
|
|
15
|
+
import { bytesToHex } from './encoding.js';
|
|
16
|
+
import {} from './log/rekor.js';
|
|
16
17
|
export const BUNDLE_FORMAT_VERSION = 1;
|
|
17
18
|
const HEX_EVEN = /^(?:[0-9a-f]{2})+$/;
|
|
18
19
|
// Standard base64: A-Z, a-z, 0-9, +, /, with 0-2 trailing '=' for padding.
|
|
@@ -70,26 +71,23 @@ export function validateBundle(value) {
|
|
|
70
71
|
}
|
|
71
72
|
}
|
|
72
73
|
/**
|
|
73
|
-
*
|
|
74
|
-
*
|
|
74
|
+
* Assemble (and validate) the portable bundle from a prepared
|
|
75
|
+
* statement and the Rekor entry it produced. Pure — used by the node
|
|
76
|
+
* `submitBinding` path and by runtimes that sign with
|
|
77
|
+
* `signEnvelopeWeb` and submit through the Rekor client themselves.
|
|
75
78
|
*/
|
|
76
|
-
export function
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
}
|
|
88
|
-
/**
|
|
89
|
-
* Validate and write a `binding.passportsign.json` file (pretty-printed).
|
|
90
|
-
*/
|
|
91
|
-
export function writeBundle(path, bundle) {
|
|
79
|
+
export function assembleBundle(prepared, rekorEntry) {
|
|
80
|
+
const bundle = {
|
|
81
|
+
bundle_format_version: BUNDLE_FORMAT_VERSION,
|
|
82
|
+
statement: bytesToHex(prepared.statement_canonical),
|
|
83
|
+
proof_blob: prepared.proof_blob_b64,
|
|
84
|
+
rekor: {
|
|
85
|
+
log_entry_hash: rekorEntry.uuid,
|
|
86
|
+
inclusion_proof: rekorEntry.verification.inclusionProof,
|
|
87
|
+
log_root_at_submission: rekorEntry.verification.inclusionProof.rootHash,
|
|
88
|
+
},
|
|
89
|
+
};
|
|
92
90
|
validateBundle(bundle);
|
|
93
|
-
|
|
91
|
+
return bundle;
|
|
94
92
|
}
|
|
95
93
|
//# sourceMappingURL=bundle.js.map
|
package/dist/bundle.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bundle.js","sourceRoot":"","sources":["../src/bundle.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"bundle.js","sourceRoot":"","sources":["../src/bundle.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAA2B,MAAM,gBAAgB,CAAC;AAEzD,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAU,CAAC;AAiBhD,MAAM,QAAQ,GAAG,oBAAoB,CAAC;AACtC,2EAA2E;AAC3E,gCAAgC;AAChC,MAAM,MAAM,GAAG,kEAAkE,CAAC;AAElF,MAAM,OAAO,qBAAsB,SAAQ,KAAK;IAEnC;IADX,YACW,IAAY,EACrB,OAAe;QAEf,KAAK,CAAC,GAAG,IAAI,KAAK,OAAO,EAAE,CAAC,CAAC;QAHpB,SAAI,GAAJ,IAAI,CAAQ;QAIrB,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;IACtC,CAAC;CACF;AAED,SAAS,IAAI,CAAC,IAAY,EAAE,OAAe;IACzC,MAAM,IAAI,qBAAqB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AACjD,CAAC;AAED,SAAS,QAAQ,CAAC,CAAU;IAC1B,OAAO,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AAClE,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,KAAc;IAC3C,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,IAAI,CAAC,GAAG,EAAE,8BAA8B,CAAC,CAAC;IAEhE,IAAI,KAAK,CAAC,uBAAuB,CAAC,KAAK,qBAAqB,EAAE,CAAC;QAC7D,IAAI,CACF,yBAAyB,EACzB,YAAY,qBAAqB,SAAS,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC,EAAE,CAC3F,CAAC;IACJ,CAAC;IAED,MAAM,SAAS,GAAG,KAAK,CAAC,WAAW,CAAC,CAAC;IACrC,IAAI,OAAO,SAAS,KAAK,QAAQ;QAAE,IAAI,CAAC,aAAa,EAAE,kBAAkB,CAAC,CAAC;IAC3E,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;QAC9B,IAAI,CAAC,aAAa,EAAE,yDAAyD,CAAC,CAAC;IACjF,CAAC;IAED,MAAM,SAAS,GAAG,KAAK,CAAC,YAAY,CAAC,CAAC;IACtC,IAAI,OAAO,SAAS,KAAK,QAAQ;QAAE,IAAI,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAC;IAC5E,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;QAC5B,IAAI,CAAC,cAAc,EAAE,0DAA0D,CAAC,CAAC;IACnF,CAAC;IAED,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC;IAC7B,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,IAAI,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;IAE3D,MAAM,YAAY,GAAG,KAAK,CAAC,gBAAgB,CAAC,CAAC;IAC7C,IAAI,OAAO,YAAY,KAAK,QAAQ,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClE,IAAI,CAAC,wBAAwB,EAAE,4BAA4B,CAAC,CAAC;IAC/D,CAAC;IAED,IAAI,CAAC,CAAC,iBAAiB,IAAI,KAAK,CAAC,EAAE,CAAC;QAClC,IAAI,CAAC,yBAAyB,EAAE,qCAAqC,CAAC,CAAC;IACzE,CAAC;IAED,MAAM,mBAAmB,GAAG,KAAK,CAAC,wBAAwB,CAAC,CAAC;IAC5D,IAAI,OAAO,mBAAmB,KAAK,QAAQ,IAAI,mBAAmB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAChF,IAAI,CAAC,gCAAgC,EAAE,4BAA4B,CAAC,CAAC;IACvE,CAAC;AACH,CAAC;AAeD;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAC5B,QAA8B,EAC9B,UAA8B;IAE9B,MAAM,MAAM,GAAuB;QACjC,qBAAqB,EAAE,qBAAqB;QAC5C,SAAS,EAAE,UAAU,CAAC,QAAQ,CAAC,mBAAmB,CAAC;QACnD,UAAU,EAAE,QAAQ,CAAC,cAAc;QACnC,KAAK,EAAE;YACL,cAAc,EAAE,UAAU,CAAC,IAAI;YAC/B,eAAe,EAAE,UAAU,CAAC,YAAY,CAAC,cAAc;YACvD,sBAAsB,EAAE,UAAU,CAAC,YAAY,CAAC,cAAc,CAAC,QAAQ;SACxE;KACF,CAAC;IACF,cAAc,CAAC,MAAM,CAAC,CAAC;IACvB,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
package/dist/canonical.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"canonical.d.ts","sourceRoot":"","sources":["../src/canonical.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"canonical.d.ts","sourceRoot":"","sources":["../src/canonical.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,UAAU,CAQvD;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEzD"}
|
package/dist/canonical.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import canonify from '@truestamp/canonify';
|
|
2
|
-
import {
|
|
2
|
+
import { sha256Hex, utf8ToBytes } from './encoding.js';
|
|
3
3
|
/**
|
|
4
4
|
* RFC 8785 JCS-canonical UTF-8 bytes for a JSON-serializable value.
|
|
5
5
|
*
|
|
@@ -17,14 +17,13 @@ export function canonicalize(value) {
|
|
|
17
17
|
if (canonical === undefined) {
|
|
18
18
|
throw new TypeError('canonicalize: value cannot be JCS-canonicalized (undefined / cycle / non-JSON)');
|
|
19
19
|
}
|
|
20
|
-
return
|
|
20
|
+
return utf8ToBytes(canonical);
|
|
21
21
|
}
|
|
22
22
|
/**
|
|
23
23
|
* Lowercase-hex SHA-256 of `canonicalize(value)`. Used to derive the
|
|
24
24
|
* Rekor entry hash for the in-toto statement.
|
|
25
25
|
*/
|
|
26
26
|
export function canonicalSha256Hex(value) {
|
|
27
|
-
|
|
28
|
-
return createHash('sha256').update(bytes).digest('hex');
|
|
27
|
+
return sha256Hex(canonicalize(value));
|
|
29
28
|
}
|
|
30
29
|
//# sourceMappingURL=canonical.js.map
|
package/dist/canonical.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"canonical.js","sourceRoot":"","sources":["../src/canonical.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"canonical.js","sourceRoot":"","sources":["../src/canonical.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,qBAAqB,CAAC;AAE3C,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEvD;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,YAAY,CAAC,KAAc;IACzC,MAAM,SAAS,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAClC,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QAC5B,MAAM,IAAI,SAAS,CACjB,gFAAgF,CACjF,CAAC;IACJ,CAAC;IACD,OAAO,WAAW,CAAC,SAAS,CAAC,CAAC;AAChC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAAc;IAC/C,OAAO,SAAS,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC;AACxC,CAAC"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse Rekor in-toto entries back into statements and classify
|
|
3
|
+
* binding state (active / stale / revoked).
|
|
4
|
+
*
|
|
5
|
+
* This is the read-side counterpart of `statement.ts`/`submit.ts`:
|
|
6
|
+
* the `list` command and the badge service both consume entries the
|
|
7
|
+
* profile index points at, and neither may trust the index — every
|
|
8
|
+
* entry is integrity-checked against the hash Rekor recorded.
|
|
9
|
+
*
|
|
10
|
+
* Staleness (spec §10 row 1): a binding moves to `stale` 12 months
|
|
11
|
+
* after its Rekor inclusion time. `integratedTime` is authoritative;
|
|
12
|
+
* user-supplied dates in the index are display-only.
|
|
13
|
+
*/
|
|
14
|
+
import { type RekorEntryResponse } from './log/rekor.js';
|
|
15
|
+
import { IN_TOTO_STATEMENT_TYPE } from './statement.js';
|
|
16
|
+
/** Spec §10 row 1: bindings move to `stale` after 12 months. */
|
|
17
|
+
export declare const STALENESS_WINDOW_MS: number;
|
|
18
|
+
export declare class EntryParseError extends Error {
|
|
19
|
+
constructor(message: string);
|
|
20
|
+
}
|
|
21
|
+
/** Generic in-toto Statement v1 shape (predicate left untyped — callers narrow). */
|
|
22
|
+
export interface InTotoStatement {
|
|
23
|
+
_type: typeof IN_TOTO_STATEMENT_TYPE;
|
|
24
|
+
subject: Array<{
|
|
25
|
+
name: string;
|
|
26
|
+
digest: Record<string, string>;
|
|
27
|
+
}>;
|
|
28
|
+
predicateType: string;
|
|
29
|
+
predicate: unknown;
|
|
30
|
+
}
|
|
31
|
+
export interface ParsedIntotoEntry {
|
|
32
|
+
uuid: string;
|
|
33
|
+
/** Unix seconds — Rekor's authoritative inclusion time. */
|
|
34
|
+
integratedTime: number;
|
|
35
|
+
predicateType: string;
|
|
36
|
+
statement: InTotoStatement;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Decode a Rekor in-toto entry's stored attestation back into its
|
|
40
|
+
* statement, verifying the attestation bytes hash to the
|
|
41
|
+
* `payloadHash` Rekor recorded in the entry body. The hash check is
|
|
42
|
+
* what lets consumers trust an entry fetched via an untrusted index.
|
|
43
|
+
*/
|
|
44
|
+
export declare function parseIntotoEntry(entry: RekorEntryResponse): ParsedIntotoEntry;
|
|
45
|
+
export type BindingState = 'active' | 'stale' | 'revoked';
|
|
46
|
+
export interface ClassifiedBinding {
|
|
47
|
+
entry: ParsedIntotoEntry;
|
|
48
|
+
state: BindingState;
|
|
49
|
+
/** UUID of the revocation entry that caused `revoked`, when applicable. */
|
|
50
|
+
revokedBy?: string;
|
|
51
|
+
}
|
|
52
|
+
export interface ClassifyBindingsInput {
|
|
53
|
+
bindings: ParsedIntotoEntry[];
|
|
54
|
+
revocations: ParsedIntotoEntry[];
|
|
55
|
+
/** Epoch milliseconds; defaults to the current time. */
|
|
56
|
+
now?: number;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Classify each binding:
|
|
60
|
+
* - `revoked` if a revocation entry (predicateType `…#revocation`)
|
|
61
|
+
* carries the same `unique_identifier` and either targets this
|
|
62
|
+
* binding's UUID via `revokes_rekor_entry_hash` or has no target
|
|
63
|
+
* (revokes all bindings under that identifier);
|
|
64
|
+
* - else `stale` if older than {@link STALENESS_WINDOW_MS};
|
|
65
|
+
* - else `active`.
|
|
66
|
+
*/
|
|
67
|
+
export declare function classifyBindings(input: ClassifyBindingsInput): ClassifiedBinding[];
|
|
68
|
+
//# sourceMappingURL=classify.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"classify.d.ts","sourceRoot":"","sources":["../src/classify.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,EAAE,KAAK,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,EACL,sBAAsB,EAEvB,MAAM,gBAAgB,CAAC;AAExB,gEAAgE;AAChE,eAAO,MAAM,mBAAmB,QAA4B,CAAC;AAE7D,qBAAa,eAAgB,SAAQ,KAAK;gBAC5B,OAAO,EAAE,MAAM;CAI5B;AAED,oFAAoF;AACpF,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,OAAO,sBAAsB,CAAC;IACrC,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE,CAAC,CAAC;IACjE,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,2DAA2D;IAC3D,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,eAAe,CAAC;CAC5B;AAMD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,kBAAkB,GAAG,iBAAiB,CAkD7E;AAED,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,OAAO,GAAG,SAAS,CAAC;AAE1D,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,iBAAiB,CAAC;IACzB,KAAK,EAAE,YAAY,CAAC;IACpB,2EAA2E;IAC3E,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,iBAAiB,EAAE,CAAC;IAC9B,WAAW,EAAE,iBAAiB,EAAE,CAAC;IACjC,wDAAwD;IACxD,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AASD;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,qBAAqB,GAAG,iBAAiB,EAAE,CAuBlF"}
|
package/dist/classify.js
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse Rekor in-toto entries back into statements and classify
|
|
3
|
+
* binding state (active / stale / revoked).
|
|
4
|
+
*
|
|
5
|
+
* This is the read-side counterpart of `statement.ts`/`submit.ts`:
|
|
6
|
+
* the `list` command and the badge service both consume entries the
|
|
7
|
+
* profile index points at, and neither may trust the index — every
|
|
8
|
+
* entry is integrity-checked against the hash Rekor recorded.
|
|
9
|
+
*
|
|
10
|
+
* Staleness (spec §10 row 1): a binding moves to `stale` 12 months
|
|
11
|
+
* after its Rekor inclusion time. `integratedTime` is authoritative;
|
|
12
|
+
* user-supplied dates in the index are display-only.
|
|
13
|
+
*/
|
|
14
|
+
import { base64ToBytes, bytesToUtf8, sha256Hex } from './encoding.js';
|
|
15
|
+
import {} from './log/rekor.js';
|
|
16
|
+
import { IN_TOTO_STATEMENT_TYPE, PASSPORTSIGN_REVOCATION_PREDICATE_TYPE, } from './statement.js';
|
|
17
|
+
/** Spec §10 row 1: bindings move to `stale` after 12 months. */
|
|
18
|
+
export const STALENESS_WINDOW_MS = 365 * 24 * 60 * 60 * 1000;
|
|
19
|
+
export class EntryParseError extends Error {
|
|
20
|
+
constructor(message) {
|
|
21
|
+
super(message);
|
|
22
|
+
this.name = 'EntryParseError';
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
function fail(message) {
|
|
26
|
+
throw new EntryParseError(message);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Decode a Rekor in-toto entry's stored attestation back into its
|
|
30
|
+
* statement, verifying the attestation bytes hash to the
|
|
31
|
+
* `payloadHash` Rekor recorded in the entry body. The hash check is
|
|
32
|
+
* what lets consumers trust an entry fetched via an untrusted index.
|
|
33
|
+
*/
|
|
34
|
+
export function parseIntotoEntry(entry) {
|
|
35
|
+
const data = entry.attestation?.data;
|
|
36
|
+
if (typeof data !== 'string' || data.length === 0) {
|
|
37
|
+
fail(`entry ${entry.uuid}: no stored attestation`);
|
|
38
|
+
}
|
|
39
|
+
const decoded = (() => {
|
|
40
|
+
try {
|
|
41
|
+
return {
|
|
42
|
+
attestationBytes: base64ToBytes(data),
|
|
43
|
+
bodyObj: JSON.parse(bytesToUtf8(base64ToBytes(entry.body))),
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
fail(`entry ${entry.uuid}: attestation/body is not base64 JSON`);
|
|
48
|
+
}
|
|
49
|
+
})();
|
|
50
|
+
const { attestationBytes, bodyObj } = decoded;
|
|
51
|
+
const payloadHash = bodyObj?.spec?.content?.payloadHash;
|
|
52
|
+
if (payloadHash?.algorithm !== 'sha256' || typeof payloadHash.value !== 'string') {
|
|
53
|
+
fail(`entry ${entry.uuid}: body has no sha256 payloadHash`);
|
|
54
|
+
}
|
|
55
|
+
const computed = sha256Hex(attestationBytes);
|
|
56
|
+
if (computed !== payloadHash.value) {
|
|
57
|
+
fail(`entry ${entry.uuid}: attestation hash mismatch (computed ${computed}, recorded ${payloadHash.value})`);
|
|
58
|
+
}
|
|
59
|
+
let statement;
|
|
60
|
+
try {
|
|
61
|
+
statement = JSON.parse(bytesToUtf8(attestationBytes));
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
fail(`entry ${entry.uuid}: attestation is not JSON`);
|
|
65
|
+
}
|
|
66
|
+
const s = statement;
|
|
67
|
+
if (s?._type !== IN_TOTO_STATEMENT_TYPE ||
|
|
68
|
+
!Array.isArray(s.subject) ||
|
|
69
|
+
typeof s.predicateType !== 'string') {
|
|
70
|
+
fail(`entry ${entry.uuid}: attestation is not an in-toto Statement v1`);
|
|
71
|
+
}
|
|
72
|
+
return {
|
|
73
|
+
uuid: entry.uuid,
|
|
74
|
+
integratedTime: entry.integratedTime,
|
|
75
|
+
predicateType: s.predicateType,
|
|
76
|
+
statement: s,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
function predicateField(entry, field) {
|
|
80
|
+
const predicate = entry.statement.predicate;
|
|
81
|
+
if (typeof predicate !== 'object' || predicate === null)
|
|
82
|
+
return undefined;
|
|
83
|
+
const value = predicate[field];
|
|
84
|
+
return typeof value === 'string' ? value : undefined;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Classify each binding:
|
|
88
|
+
* - `revoked` if a revocation entry (predicateType `…#revocation`)
|
|
89
|
+
* carries the same `unique_identifier` and either targets this
|
|
90
|
+
* binding's UUID via `revokes_rekor_entry_hash` or has no target
|
|
91
|
+
* (revokes all bindings under that identifier);
|
|
92
|
+
* - else `stale` if older than {@link STALENESS_WINDOW_MS};
|
|
93
|
+
* - else `active`.
|
|
94
|
+
*/
|
|
95
|
+
export function classifyBindings(input) {
|
|
96
|
+
const now = input.now ?? Date.now();
|
|
97
|
+
// Exact match, not endsWith — a foreign predicateType that happens to
|
|
98
|
+
// end in #revocation must never revoke a binding.
|
|
99
|
+
const revocations = input.revocations.filter((r) => r.predicateType === PASSPORTSIGN_REVOCATION_PREDICATE_TYPE);
|
|
100
|
+
return input.bindings.map((entry) => {
|
|
101
|
+
const uid = predicateField(entry, 'unique_identifier');
|
|
102
|
+
const revokedBy = revocations.find((r) => {
|
|
103
|
+
if (predicateField(r, 'unique_identifier') !== uid || uid === undefined)
|
|
104
|
+
return false;
|
|
105
|
+
const target = predicateField(r, 'revokes_rekor_entry_hash');
|
|
106
|
+
return target === undefined || target === entry.uuid;
|
|
107
|
+
});
|
|
108
|
+
if (revokedBy) {
|
|
109
|
+
return { entry, state: 'revoked', revokedBy: revokedBy.uuid };
|
|
110
|
+
}
|
|
111
|
+
if (now - entry.integratedTime * 1000 > STALENESS_WINDOW_MS) {
|
|
112
|
+
return { entry, state: 'stale' };
|
|
113
|
+
}
|
|
114
|
+
return { entry, state: 'active' };
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=classify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"classify.js","sourceRoot":"","sources":["../src/classify.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime-neutral DSSE pieces shared by the node signer (`dsse.ts`)
|
|
3
|
+
* and the WebCrypto signer (`dsse-web.ts`): the envelope shape and the
|
|
4
|
+
* Pre-Authentication Encoding.
|
|
5
|
+
*/
|
|
6
|
+
export declare const DSSE_VERSION = "DSSEv1";
|
|
7
|
+
export declare const IN_TOTO_PAYLOAD_TYPE = "application/vnd.in-toto+json";
|
|
8
|
+
export interface DsseSignature {
|
|
9
|
+
/** Single-base64 of the raw signature bytes. */
|
|
10
|
+
sig: string;
|
|
11
|
+
/** PEM-encoded SubjectPublicKeyInfo. */
|
|
12
|
+
publicKey: string;
|
|
13
|
+
/** Optional key identifier. Omit (don't pass empty string) when not set. */
|
|
14
|
+
keyid?: string;
|
|
15
|
+
}
|
|
16
|
+
export interface DsseEnvelope {
|
|
17
|
+
/** Media type of the payload (e.g. `application/vnd.in-toto+json`). */
|
|
18
|
+
payloadType: string;
|
|
19
|
+
/** Single-base64 of the raw payload bytes. */
|
|
20
|
+
payload: string;
|
|
21
|
+
signatures: DsseSignature[];
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* DSSE Pre-Authentication Encoding (PAE):
|
|
25
|
+
*
|
|
26
|
+
* "DSSEv1" SP LEN(type) SP type SP LEN(body) SP body
|
|
27
|
+
*
|
|
28
|
+
* Where SP is a single 0x20 space, LEN is the ASCII-decimal length of
|
|
29
|
+
* the following byte string.
|
|
30
|
+
*/
|
|
31
|
+
export declare function pae(type: string, body: Uint8Array): Uint8Array;
|
|
32
|
+
//# sourceMappingURL=dsse-common.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dsse-common.d.ts","sourceRoot":"","sources":["../src/dsse-common.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,eAAO,MAAM,YAAY,WAAW,CAAC;AACrC,eAAO,MAAM,oBAAoB,iCAAiC,CAAC;AAEnE,MAAM,WAAW,aAAa;IAC5B,gDAAgD;IAChD,GAAG,EAAE,MAAM,CAAC;IACZ,wCAAwC;IACxC,SAAS,EAAE,MAAM,CAAC;IAClB,4EAA4E;IAC5E,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,uEAAuE;IACvE,WAAW,EAAE,MAAM,CAAC;IACpB,8CAA8C;IAC9C,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,aAAa,EAAE,CAAC;CAC7B;AAED;;;;;;;GAOG;AACH,wBAAgB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,UAAU,CAQ9D"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime-neutral DSSE pieces shared by the node signer (`dsse.ts`)
|
|
3
|
+
* and the WebCrypto signer (`dsse-web.ts`): the envelope shape and the
|
|
4
|
+
* Pre-Authentication Encoding.
|
|
5
|
+
*/
|
|
6
|
+
import { utf8ToBytes } from './encoding.js';
|
|
7
|
+
export const DSSE_VERSION = 'DSSEv1';
|
|
8
|
+
export const IN_TOTO_PAYLOAD_TYPE = 'application/vnd.in-toto+json';
|
|
9
|
+
/**
|
|
10
|
+
* DSSE Pre-Authentication Encoding (PAE):
|
|
11
|
+
*
|
|
12
|
+
* "DSSEv1" SP LEN(type) SP type SP LEN(body) SP body
|
|
13
|
+
*
|
|
14
|
+
* Where SP is a single 0x20 space, LEN is the ASCII-decimal length of
|
|
15
|
+
* the following byte string.
|
|
16
|
+
*/
|
|
17
|
+
export function pae(type, body) {
|
|
18
|
+
const typeBytes = utf8ToBytes(type);
|
|
19
|
+
const prefix = `${DSSE_VERSION} ${typeBytes.length} ${type} ${body.length} `;
|
|
20
|
+
const prefixBytes = utf8ToBytes(prefix);
|
|
21
|
+
const out = new Uint8Array(prefixBytes.length + body.length);
|
|
22
|
+
out.set(prefixBytes);
|
|
23
|
+
out.set(body, prefixBytes.length);
|
|
24
|
+
return out;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=dsse-common.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dsse-common.js","sourceRoot":"","sources":["../src/dsse-common.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,MAAM,CAAC,MAAM,YAAY,GAAG,QAAQ,CAAC;AACrC,MAAM,CAAC,MAAM,oBAAoB,GAAG,8BAA8B,CAAC;AAmBnE;;;;;;;GAOG;AACH,MAAM,UAAU,GAAG,CAAC,IAAY,EAAE,IAAgB;IAChD,MAAM,SAAS,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IACpC,MAAM,MAAM,GAAG,GAAG,YAAY,IAAI,SAAS,CAAC,MAAM,IAAI,IAAI,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;IAC7E,MAAM,WAAW,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;IACxC,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,WAAW,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;IAC7D,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IACrB,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAClC,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WebCrypto variant of the DSSE envelope signer for runtimes without
|
|
3
|
+
* `node:crypto` sign APIs (browsers, edge workers). Same semantics as
|
|
4
|
+
* `dsse.ts`'s `signEnvelope`: ephemeral ECDSA P-256 key, discarded
|
|
5
|
+
* after signing; the signature is a Rekor schema requirement, not a
|
|
6
|
+
* trust mechanism.
|
|
7
|
+
*
|
|
8
|
+
* Two impedance mismatches with what Rekor expects, both handled here:
|
|
9
|
+
* - WebCrypto emits raw P1363 (`r || s`) signatures; Rekor needs DER.
|
|
10
|
+
* - WebCrypto exports SPKI as raw bytes; Rekor needs PEM text.
|
|
11
|
+
*
|
|
12
|
+
* The drift test in `test/dsse-web.test.ts` verifies output with
|
|
13
|
+
* `node:crypto.createVerify` so the two signers cannot diverge silently.
|
|
14
|
+
*/
|
|
15
|
+
import { type DsseEnvelope } from './dsse-common.js';
|
|
16
|
+
export interface SignEnvelopeWebResult {
|
|
17
|
+
envelope: DsseEnvelope;
|
|
18
|
+
publicKeyPem: string;
|
|
19
|
+
}
|
|
20
|
+
/** Convert a P1363 (r||s) ECDSA signature to DER SEQUENCE(INTEGER r, INTEGER s). */
|
|
21
|
+
export declare function p1363ToDer(sig: Uint8Array): Uint8Array;
|
|
22
|
+
/**
|
|
23
|
+
* Generate an ephemeral ECDSA P-256 keypair via WebCrypto, sign
|
|
24
|
+
* PAE(payloadType, payload), and return a DSSE envelope. Async because
|
|
25
|
+
* WebCrypto is; otherwise interchangeable with `signEnvelope`.
|
|
26
|
+
*/
|
|
27
|
+
export declare function signEnvelopeWeb(payload: Uint8Array, payloadType: string): Promise<SignEnvelopeWebResult>;
|
|
28
|
+
//# sourceMappingURL=dsse-web.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dsse-web.d.ts","sourceRoot":"","sources":["../src/dsse-web.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAE1D,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,YAAY,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;CACtB;AAeD,oFAAoF;AACpF,wBAAgB,UAAU,CAAC,GAAG,EAAE,UAAU,GAAG,UAAU,CAoBtD;AAQD;;;;GAIG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,UAAU,EACnB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,qBAAqB,CAAC,CAuBhC"}
|