agentic-payments 0.1.15 → 0.1.16
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 +26 -5
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/visa-tap/index.d.ts +1 -1
- package/dist/visa-tap/index.d.ts.map +1 -1
- package/dist/visa-tap/index.js.map +1 -1
- package/dist/visa-tap/rfc9421-fields.d.ts +29 -0
- package/dist/visa-tap/rfc9421-fields.d.ts.map +1 -0
- package/dist/visa-tap/rfc9421-fields.js +207 -0
- package/dist/visa-tap/rfc9421-fields.js.map +1 -0
- package/dist/visa-tap/rfc9421.d.ts +26 -8
- package/dist/visa-tap/rfc9421.d.ts.map +1 -1
- package/dist/visa-tap/rfc9421.js +188 -81
- package/dist/visa-tap/rfc9421.js.map +1 -1
- package/dist/visa-tap/types.d.ts +52 -2
- package/dist/visa-tap/types.d.ts.map +1 -1
- package/package.json +3 -24
package/README.md
CHANGED
|
@@ -653,10 +653,18 @@ const signed = await signHttpMessage(
|
|
|
653
653
|
'did:agent:shopping-bot'
|
|
654
654
|
);
|
|
655
655
|
|
|
656
|
-
// Send with your HTTPS client, carrying
|
|
657
|
-
//
|
|
656
|
+
// Send with your HTTPS client, carrying the Content-Digest header plus
|
|
657
|
+
// Signature: signed.signature and Signature-Input: signed.signatureInput, and
|
|
658
|
+
// treat the payment as submitted only when the merchant confirms it.
|
|
658
659
|
```
|
|
659
660
|
|
|
661
|
+
`Signature-Input` lists every signed component in signing order (`@method`,
|
|
662
|
+
`@authority`, `@path`, then `content-digest` and any `headers`) with
|
|
663
|
+
`created`, `expires` (default 5 minutes), `nonce`, `keyid` and `alg="ed25519"`,
|
|
664
|
+
so any RFC 9421 verifier can check it. The package is tested against the
|
|
665
|
+
independent `http-message-signatures` implementation and the RFC 9421
|
|
666
|
+
Appendix B.2.6 Ed25519 test vector.
|
|
667
|
+
|
|
660
668
|
There is no working QUIC transport: see [Visa TAP transport](#visa-tap-quic-transport).
|
|
661
669
|
|
|
662
670
|
### Agent Fleet Management
|
|
@@ -1022,12 +1030,25 @@ Production deployment guidelines for secure payment authorization:
|
|
|
1022
1030
|
|
|
1023
1031
|
### Signature Validation
|
|
1024
1032
|
|
|
1025
|
-
**RFC 9421
|
|
1033
|
+
**RFC 9421 Verification**:
|
|
1026
1034
|
```typescript
|
|
1027
|
-
//
|
|
1028
|
-
|
|
1035
|
+
// components: your view of the received request. Every component you pass,
|
|
1036
|
+
// including contentDigest and each entry of headers, must be covered by the
|
|
1037
|
+
// received Signature-Input or verification fails.
|
|
1038
|
+
const isValid = await verifyHttpSignature(
|
|
1039
|
+
components,
|
|
1040
|
+
{ signatureInput: req.headers['signature-input'], signature: req.headers['signature'] },
|
|
1041
|
+
publicKeyHex,
|
|
1042
|
+
300, // max age of created, in seconds
|
|
1043
|
+
{ expectedKeyId: 'did:agent:shopping-bot' }
|
|
1044
|
+
);
|
|
1029
1045
|
```
|
|
1030
1046
|
|
|
1047
|
+
The signature base is rebuilt from the received `Signature-Input`, in its
|
|
1048
|
+
order. Verification fails when `created` is missing, older than the max age or
|
|
1049
|
+
in the future (30 s skew), when `expires` has passed, when `alg` is not
|
|
1050
|
+
`ed25519`, or when a covered component is unsupported or unavailable.
|
|
1051
|
+
|
|
1031
1052
|
**Replay Protection**:
|
|
1032
1053
|
- Nonce-based replay prevention (16-byte cryptographic nonces)
|
|
1033
1054
|
- Timestamp validation (configurable max age, default 300 seconds)
|
package/dist/index.d.ts
CHANGED
|
@@ -51,6 +51,7 @@ export type { IntentMandateData, CartMandateData, PaymentMandateData, CartItem,
|
|
|
51
51
|
export { PaymentError, PaymentErrorCode, isRecoverable, getErrorCode, formatError, AgenticPaymentError, CryptoError, ValidationError, ConsensusError, SystemError, WasmInitError, ErrorCode, } from './errors.js';
|
|
52
52
|
export { VisaTapQuicTransport, createQuicTransport, getQuicTransportStatus, QuicTransportUnavailableError, PaymentNotDeliveredError, } from './visa-tap/index.js';
|
|
53
53
|
export { signHttpMessage, verifyHttpSignature, computeContentDigest } from './visa-tap/index.js';
|
|
54
|
+
export type { SignatureComponents, SignedHttpMessage, VerifiableHttpSignature, SignHttpMessageOptions, VerifyHttpSignatureOptions, } from './visa-tap/index.js';
|
|
54
55
|
export { TAP_VERSION, DEFAULT_QUIC_PORT, MAX_MANDATE_LIFETIME_SECS } from './visa-tap/index.js';
|
|
55
56
|
export declare const VERSION = "1.0.0";
|
|
56
57
|
/**
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAGH,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,YAAY,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAEvD,OAAO,EACL,kBAAkB,EAClB,yBAAyB,GAC1B,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACV,SAAS,EACT,kBAAkB,EAClB,kBAAkB,EAClB,aAAa,GACd,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC1E,YAAY,EACV,iBAAiB,EACjB,eAAe,EACf,kBAAkB,EAClB,QAAQ,EACR,gBAAgB,GACjB,MAAM,cAAc,CAAC;AAGtB,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,aAAa,EACb,YAAY,EACZ,WAAW,EAEX,mBAAmB,EACnB,WAAW,EACX,eAAe,EACf,cAAc,EACd,WAAW,EACX,aAAa,EACb,SAAS,GACV,MAAM,aAAa,CAAC;AAIrB,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,sBAAsB,EACtB,6BAA6B,EAC7B,wBAAwB,GACzB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AACjG,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,yBAAyB,EAAE,MAAM,qBAAqB,CAAC;AAGhG,eAAO,MAAM,OAAO,UAAU,CAAC;AAE/B;;;;GAIG;AACH,wBAAgB,OAAO,IAAI;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB,CAeA;;;;;AAGD,wBAGE"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAGH,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,YAAY,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAEvD,OAAO,EACL,kBAAkB,EAClB,yBAAyB,GAC1B,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACV,SAAS,EACT,kBAAkB,EAClB,kBAAkB,EAClB,aAAa,GACd,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC1E,YAAY,EACV,iBAAiB,EACjB,eAAe,EACf,kBAAkB,EAClB,QAAQ,EACR,gBAAgB,GACjB,MAAM,cAAc,CAAC;AAGtB,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,aAAa,EACb,YAAY,EACZ,WAAW,EAEX,mBAAmB,EACnB,WAAW,EACX,eAAe,EACf,cAAc,EACd,WAAW,EACX,aAAa,EACb,SAAS,GACV,MAAM,aAAa,CAAC;AAIrB,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,sBAAsB,EACtB,6BAA6B,EAC7B,wBAAwB,GACzB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AACjG,YAAY,EACV,mBAAmB,EACnB,iBAAiB,EACjB,uBAAuB,EACvB,sBAAsB,EACtB,0BAA0B,GAC3B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,yBAAyB,EAAE,MAAM,qBAAqB,CAAC;AAGhG,eAAO,MAAM,OAAO,UAAU,CAAC;AAE/B;;;;GAIG;AACH,wBAAgB,OAAO,IAAI;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB,CAeA;;;;;AAGD,wBAGE"}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAEH,eAAe;AACf,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAG9C,OAAO,EACL,kBAAkB,EAClB,yBAAyB,GAC1B,MAAM,mBAAmB,CAAC;AAQ3B,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAS1E,gBAAgB;AAChB,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,aAAa,EACb,YAAY,EACZ,WAAW;AACX,iBAAiB;AACjB,mBAAmB,EACnB,WAAW,EACX,eAAe,EACf,cAAc,EACd,WAAW,EACX,aAAa,EACb,SAAS,GACV,MAAM,aAAa,CAAC;AAErB,mFAAmF;AACnF,kFAAkF;AAClF,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,sBAAsB,EACtB,6BAA6B,EAC7B,wBAAwB,GACzB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAEH,eAAe;AACf,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAG9C,OAAO,EACL,kBAAkB,EAClB,yBAAyB,GAC1B,MAAM,mBAAmB,CAAC;AAQ3B,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAS1E,gBAAgB;AAChB,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,aAAa,EACb,YAAY,EACZ,WAAW;AACX,iBAAiB;AACjB,mBAAmB,EACnB,WAAW,EACX,eAAe,EACf,cAAc,EACd,WAAW,EACX,aAAa,EACb,SAAS,GACV,MAAM,aAAa,CAAC;AAErB,mFAAmF;AACnF,kFAAkF;AAClF,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,sBAAsB,EACtB,6BAA6B,EAC7B,wBAAwB,GACzB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAQjG,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,yBAAyB,EAAE,MAAM,qBAAqB,CAAC;AAEhG,sBAAsB;AACtB,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC;AAE/B;;;;GAIG;AACH,MAAM,UAAU,OAAO;IAKrB,OAAO;QACL,OAAO,EAAE,OAAO;QAChB,cAAc,EAAE,mBAAmB;QACnC,QAAQ,EAAE;YACR,oBAAoB;YACpB,uBAAuB;YACvB,2BAA2B;YAC3B,iBAAiB;YACjB,eAAe;YACf,kBAAkB;YAClB,yBAAyB;YACzB,iBAAiB;SAClB;KACF,CAAC;AACJ,CAAC;AAED,iBAAiB;AACjB,eAAe;IACb,OAAO;IACP,OAAO;CACR,CAAC"}
|
package/dist/visa-tap/index.d.ts
CHANGED
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
export { validateAndVerify, guardExecution, revoke, isRevoked, getAllRevocations, type SignedMandate, type VerificationResult, type ExecutionGuard, type RevocationRecord, } from '../active-mandate/index.js';
|
|
24
24
|
export { VisaTapQuicTransport, createQuicTransport, loadQuicTransport, getQuicTransportStatus, QuicTransportUnavailableError, PaymentNotDeliveredError, QUIC_UNAVAILABLE, PAYMENT_NOT_DELIVERED, AGENTIC_FLOW_PEER_RANGE, type QuicTransportStatus, } from './quic-transport.js';
|
|
25
25
|
export { signHttpMessage, verifyHttpSignature, computeContentDigest, } from './rfc9421.js';
|
|
26
|
-
export type { Period, MandateKind, ActiveMandatePayload, SignedActiveMandate, SignatureComponents, SignedHttpMessage, QuicConfig, QuicStats, PaymentResponse, } from './types.js';
|
|
26
|
+
export type { Period, MandateKind, ActiveMandatePayload, SignedActiveMandate, SignatureComponents, SignedHttpMessage, VerifiableHttpSignature, SignHttpMessageOptions, VerifyHttpSignatureOptions, QuicConfig, QuicStats, PaymentResponse, } from './types.js';
|
|
27
27
|
/**
|
|
28
28
|
* Visa TAP protocol version
|
|
29
29
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/visa-tap/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAGH,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,MAAM,EACN,SAAS,EACT,iBAAiB,EACjB,KAAK,aAAa,EAClB,KAAK,kBAAkB,EACvB,KAAK,cAAc,EACnB,KAAK,gBAAgB,GACtB,MAAM,4BAA4B,CAAC;AAGpC,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,iBAAiB,EACjB,sBAAsB,EACtB,6BAA6B,EAC7B,wBAAwB,EACxB,gBAAgB,EAChB,qBAAqB,EACrB,uBAAuB,EACvB,KAAK,mBAAmB,GACzB,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,oBAAoB,GACrB,MAAM,cAAc,CAAC;AAGtB,YAAY,EACV,MAAM,EACN,WAAW,EACX,oBAAoB,EACpB,mBAAmB,EACnB,mBAAmB,EACnB,iBAAiB,EACjB,UAAU,EACV,SAAS,EACT,eAAe,GAChB,MAAM,YAAY,CAAC;AAEpB;;GAEG;AACH,eAAO,MAAM,WAAW,QAAQ,CAAC;AAEjC;;GAEG;AACH,eAAO,MAAM,iBAAiB,OAAO,CAAC;AAEtC;;GAEG;AACH,eAAO,MAAM,yBAAyB,QAAmB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/visa-tap/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAGH,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,MAAM,EACN,SAAS,EACT,iBAAiB,EACjB,KAAK,aAAa,EAClB,KAAK,kBAAkB,EACvB,KAAK,cAAc,EACnB,KAAK,gBAAgB,GACtB,MAAM,4BAA4B,CAAC;AAGpC,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,iBAAiB,EACjB,sBAAsB,EACtB,6BAA6B,EAC7B,wBAAwB,EACxB,gBAAgB,EAChB,qBAAqB,EACrB,uBAAuB,EACvB,KAAK,mBAAmB,GACzB,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,oBAAoB,GACrB,MAAM,cAAc,CAAC;AAGtB,YAAY,EACV,MAAM,EACN,WAAW,EACX,oBAAoB,EACpB,mBAAmB,EACnB,mBAAmB,EACnB,iBAAiB,EACjB,uBAAuB,EACvB,sBAAsB,EACtB,0BAA0B,EAC1B,UAAU,EACV,SAAS,EACT,eAAe,GAChB,MAAM,YAAY,CAAC;AAEpB;;GAEG;AACH,eAAO,MAAM,WAAW,QAAQ,CAAC;AAEjC;;GAEG;AACH,eAAO,MAAM,iBAAiB,OAAO,CAAC;AAEtC;;GAEG;AACH,eAAO,MAAM,yBAAyB,QAAmB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/visa-tap/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,kDAAkD;AAClD,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,MAAM,EACN,SAAS,EACT,iBAAiB,GAKlB,MAAM,4BAA4B,CAAC;AAEpC,wBAAwB;AACxB,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,iBAAiB,EACjB,sBAAsB,EACtB,6BAA6B,EAC7B,wBAAwB,EACxB,gBAAgB,EAChB,qBAAqB,EACrB,uBAAuB,GAExB,MAAM,qBAAqB,CAAC;AAE7B,kBAAkB;AAClB,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,oBAAoB,GACrB,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/visa-tap/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,kDAAkD;AAClD,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,MAAM,EACN,SAAS,EACT,iBAAiB,GAKlB,MAAM,4BAA4B,CAAC;AAEpC,wBAAwB;AACxB,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,iBAAiB,EACjB,sBAAsB,EACtB,6BAA6B,EAC7B,wBAAwB,EACxB,gBAAgB,EAChB,qBAAqB,EACrB,uBAAuB,GAExB,MAAM,qBAAqB,CAAC;AAE7B,kBAAkB;AAClB,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,oBAAoB,GACrB,MAAM,cAAc,CAAC;AAkBtB;;GAEG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,CAAC;AAEjC;;GAEG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,CAAC;AAEtC;;GAEG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Strict parsing and serialization of the RFC 9421 `Signature-Input` and
|
|
3
|
+
* `Signature` fields (RFC 8941 structured-field dictionaries).
|
|
4
|
+
*
|
|
5
|
+
* Only the subset RFC 9421 needs is accepted: dictionary members whose value
|
|
6
|
+
* is an inner list of component identifiers (Signature-Input) or a byte
|
|
7
|
+
* sequence (Signature). Anything else is rejected rather than guessed at.
|
|
8
|
+
*/
|
|
9
|
+
/** A signature parameter value (RFC 9421 §2.3). */
|
|
10
|
+
export type SignatureParamValue = number | string;
|
|
11
|
+
/** A parsed Signature-Input member. */
|
|
12
|
+
export interface ParsedSignatureInput {
|
|
13
|
+
label: string;
|
|
14
|
+
/** Covered component identifiers, in the order they were listed. */
|
|
15
|
+
components: string[];
|
|
16
|
+
/** Signature parameters, in the order they were listed. */
|
|
17
|
+
params: Array<[string, SignatureParamValue]>;
|
|
18
|
+
}
|
|
19
|
+
/** Parse every member of a Signature-Input field. Throws on malformed input. */
|
|
20
|
+
export declare function parseSignatureInputField(field: string): Map<string, ParsedSignatureInput>;
|
|
21
|
+
/** Parse every member of a Signature field. Throws on malformed input. */
|
|
22
|
+
export declare function parseSignatureField(field: string): Map<string, Uint8Array>;
|
|
23
|
+
/** Serialize a string as an RFC 8941 sf-string. */
|
|
24
|
+
export declare function serializeString(value: string): string;
|
|
25
|
+
/** Serialize the inner list + parameters, i.e. the `@signature-params` value. */
|
|
26
|
+
export declare function serializeSignatureParams(components: readonly string[], params: ReadonlyArray<readonly [string, SignatureParamValue]>): string;
|
|
27
|
+
/** Validate a dictionary key (signature label). */
|
|
28
|
+
export declare function assertLabel(label: string): void;
|
|
29
|
+
//# sourceMappingURL=rfc9421-fields.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rfc9421-fields.d.ts","sourceRoot":"","sources":["../../src/visa-tap/rfc9421-fields.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,mDAAmD;AACnD,MAAM,MAAM,mBAAmB,GAAG,MAAM,GAAG,MAAM,CAAC;AAElD,uCAAuC;AACvC,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,oEAAoE;IACpE,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,2DAA2D;IAC3D,MAAM,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC,CAAC;CAC9C;AAoJD,gFAAgF;AAChF,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAKzF;AAED,0EAA0E;AAC1E,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAE1E;AAED,mDAAmD;AACnD,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAKrD;AAED,iFAAiF;AACjF,wBAAgB,wBAAwB,CACtC,UAAU,EAAE,SAAS,MAAM,EAAE,EAC7B,MAAM,EAAE,aAAa,CAAC,SAAS,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC,GAC5D,MAAM,CAaR;AAED,mDAAmD;AACnD,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAE/C"}
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Strict parsing and serialization of the RFC 9421 `Signature-Input` and
|
|
3
|
+
* `Signature` fields (RFC 8941 structured-field dictionaries).
|
|
4
|
+
*
|
|
5
|
+
* Only the subset RFC 9421 needs is accepted: dictionary members whose value
|
|
6
|
+
* is an inner list of component identifiers (Signature-Input) or a byte
|
|
7
|
+
* sequence (Signature). Anything else is rejected rather than guessed at.
|
|
8
|
+
*/
|
|
9
|
+
/** Parameters RFC 9421 §2.3 defines, and the type each must have. */
|
|
10
|
+
const PARAM_TYPES = {
|
|
11
|
+
created: 'integer',
|
|
12
|
+
expires: 'integer',
|
|
13
|
+
nonce: 'string',
|
|
14
|
+
alg: 'string',
|
|
15
|
+
keyid: 'string',
|
|
16
|
+
tag: 'string',
|
|
17
|
+
};
|
|
18
|
+
const KEY_RE = /^[a-z*][a-z0-9_\-.*]*$/;
|
|
19
|
+
const MAX_INTEGER = 999_999_999_999_999;
|
|
20
|
+
class Cursor {
|
|
21
|
+
src;
|
|
22
|
+
pos = 0;
|
|
23
|
+
constructor(src) {
|
|
24
|
+
this.src = src;
|
|
25
|
+
}
|
|
26
|
+
peek() {
|
|
27
|
+
return this.src[this.pos];
|
|
28
|
+
}
|
|
29
|
+
eof() {
|
|
30
|
+
return this.pos >= this.src.length;
|
|
31
|
+
}
|
|
32
|
+
skipSP() {
|
|
33
|
+
while (this.src[this.pos] === ' ')
|
|
34
|
+
this.pos++;
|
|
35
|
+
}
|
|
36
|
+
skipOWS() {
|
|
37
|
+
while (this.src[this.pos] === ' ' || this.src[this.pos] === '\t')
|
|
38
|
+
this.pos++;
|
|
39
|
+
}
|
|
40
|
+
expect(ch) {
|
|
41
|
+
if (this.src[this.pos] !== ch) {
|
|
42
|
+
throw new Error(`expected "${ch}" at offset ${this.pos}`);
|
|
43
|
+
}
|
|
44
|
+
this.pos++;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function parseKey(c) {
|
|
48
|
+
const start = c.pos;
|
|
49
|
+
while (!c.eof() && /[a-z0-9_\-.*]/.test(c.peek()))
|
|
50
|
+
c.pos++;
|
|
51
|
+
const key = c.src.slice(start, c.pos);
|
|
52
|
+
if (!KEY_RE.test(key))
|
|
53
|
+
throw new Error(`invalid key at offset ${start}`);
|
|
54
|
+
return key;
|
|
55
|
+
}
|
|
56
|
+
function parseString(c) {
|
|
57
|
+
c.expect('"');
|
|
58
|
+
let out = '';
|
|
59
|
+
for (;;) {
|
|
60
|
+
const ch = c.peek();
|
|
61
|
+
if (ch === undefined)
|
|
62
|
+
throw new Error('unterminated string');
|
|
63
|
+
c.pos++;
|
|
64
|
+
if (ch === '"')
|
|
65
|
+
return out;
|
|
66
|
+
if (ch === '\\') {
|
|
67
|
+
const next = c.peek();
|
|
68
|
+
if (next !== '"' && next !== '\\')
|
|
69
|
+
throw new Error('invalid string escape');
|
|
70
|
+
out += next;
|
|
71
|
+
c.pos++;
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
const code = ch.charCodeAt(0);
|
|
75
|
+
if (code < 0x20 || code > 0x7e)
|
|
76
|
+
throw new Error('invalid character in string');
|
|
77
|
+
out += ch;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
function parseInteger(c) {
|
|
81
|
+
const start = c.pos;
|
|
82
|
+
if (c.peek() === '-')
|
|
83
|
+
c.pos++;
|
|
84
|
+
const digitsStart = c.pos;
|
|
85
|
+
while (!c.eof() && /[0-9]/.test(c.peek()))
|
|
86
|
+
c.pos++;
|
|
87
|
+
const digits = c.pos - digitsStart;
|
|
88
|
+
if (digits === 0 || digits > 15)
|
|
89
|
+
throw new Error(`invalid integer at offset ${start}`);
|
|
90
|
+
if (c.peek() === '.')
|
|
91
|
+
throw new Error('decimals are not allowed here');
|
|
92
|
+
return Number(c.src.slice(start, c.pos));
|
|
93
|
+
}
|
|
94
|
+
function parseParams(c) {
|
|
95
|
+
const params = [];
|
|
96
|
+
const seen = new Set();
|
|
97
|
+
while (c.peek() === ';') {
|
|
98
|
+
c.pos++;
|
|
99
|
+
c.skipSP();
|
|
100
|
+
const key = parseKey(c);
|
|
101
|
+
if (seen.has(key))
|
|
102
|
+
throw new Error(`duplicate parameter "${key}"`);
|
|
103
|
+
seen.add(key);
|
|
104
|
+
const type = PARAM_TYPES[key];
|
|
105
|
+
if (!type)
|
|
106
|
+
throw new Error(`unsupported signature parameter "${key}"`);
|
|
107
|
+
c.expect('=');
|
|
108
|
+
const value = type === 'integer' ? parseInteger(c) : parseString(c);
|
|
109
|
+
params.push([key, value]);
|
|
110
|
+
}
|
|
111
|
+
return params;
|
|
112
|
+
}
|
|
113
|
+
/** Split a structured-field dictionary into raw `[key, valueText]` members. */
|
|
114
|
+
function parseDictionary(field, parseValue) {
|
|
115
|
+
const c = new Cursor(field.trim());
|
|
116
|
+
const out = new Map();
|
|
117
|
+
if (c.eof())
|
|
118
|
+
throw new Error('empty dictionary');
|
|
119
|
+
for (;;) {
|
|
120
|
+
const key = parseKey(c);
|
|
121
|
+
if (out.has(key))
|
|
122
|
+
throw new Error(`duplicate dictionary member "${key}"`);
|
|
123
|
+
c.expect('=');
|
|
124
|
+
out.set(key, parseValue(c));
|
|
125
|
+
c.skipOWS();
|
|
126
|
+
if (c.eof())
|
|
127
|
+
return out;
|
|
128
|
+
c.expect(',');
|
|
129
|
+
c.skipOWS();
|
|
130
|
+
if (c.eof())
|
|
131
|
+
throw new Error('trailing comma in dictionary');
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
function parseInnerList(c) {
|
|
135
|
+
c.expect('(');
|
|
136
|
+
const components = [];
|
|
137
|
+
c.skipSP();
|
|
138
|
+
while (c.peek() !== ')') {
|
|
139
|
+
if (c.eof())
|
|
140
|
+
throw new Error('unterminated inner list');
|
|
141
|
+
components.push(parseString(c));
|
|
142
|
+
if (c.peek() === ';')
|
|
143
|
+
throw new Error('component parameters are not supported');
|
|
144
|
+
const before = c.pos;
|
|
145
|
+
c.skipSP();
|
|
146
|
+
if (c.peek() !== ')' && c.pos === before) {
|
|
147
|
+
throw new Error('inner list items must be separated by a space');
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
c.pos++;
|
|
151
|
+
return { components, params: parseParams(c) };
|
|
152
|
+
}
|
|
153
|
+
function parseByteSequence(c) {
|
|
154
|
+
c.expect(':');
|
|
155
|
+
const start = c.pos;
|
|
156
|
+
while (!c.eof() && c.peek() !== ':')
|
|
157
|
+
c.pos++;
|
|
158
|
+
const b64 = c.src.slice(start, c.pos);
|
|
159
|
+
c.expect(':');
|
|
160
|
+
if (c.peek() === ';')
|
|
161
|
+
throw new Error('signature parameters are not supported');
|
|
162
|
+
if (!/^[A-Za-z0-9+/]*={0,2}$/.test(b64) || b64.length % 4 !== 0) {
|
|
163
|
+
throw new Error('invalid base64 in byte sequence');
|
|
164
|
+
}
|
|
165
|
+
return new Uint8Array(Buffer.from(b64, 'base64'));
|
|
166
|
+
}
|
|
167
|
+
/** Parse every member of a Signature-Input field. Throws on malformed input. */
|
|
168
|
+
export function parseSignatureInputField(field) {
|
|
169
|
+
const raw = parseDictionary(field, parseInnerList);
|
|
170
|
+
const out = new Map();
|
|
171
|
+
for (const [label, value] of raw)
|
|
172
|
+
out.set(label, { label, ...value });
|
|
173
|
+
return out;
|
|
174
|
+
}
|
|
175
|
+
/** Parse every member of a Signature field. Throws on malformed input. */
|
|
176
|
+
export function parseSignatureField(field) {
|
|
177
|
+
return parseDictionary(field, parseByteSequence);
|
|
178
|
+
}
|
|
179
|
+
/** Serialize a string as an RFC 8941 sf-string. */
|
|
180
|
+
export function serializeString(value) {
|
|
181
|
+
if (!/^[\x20-\x7e]*$/.test(value)) {
|
|
182
|
+
throw new Error('structured-field strings must be printable ASCII');
|
|
183
|
+
}
|
|
184
|
+
return `"${value.replace(/[\\"]/g, (m) => `\\${m}`)}"`;
|
|
185
|
+
}
|
|
186
|
+
/** Serialize the inner list + parameters, i.e. the `@signature-params` value. */
|
|
187
|
+
export function serializeSignatureParams(components, params) {
|
|
188
|
+
const list = `(${components.map(serializeString).join(' ')})`;
|
|
189
|
+
const rendered = params.map(([key, value]) => {
|
|
190
|
+
if (!KEY_RE.test(key))
|
|
191
|
+
throw new Error(`invalid parameter name "${key}"`);
|
|
192
|
+
if (typeof value === 'number') {
|
|
193
|
+
if (!Number.isInteger(value) || Math.abs(value) > MAX_INTEGER) {
|
|
194
|
+
throw new Error(`parameter "${key}" must be an integer`);
|
|
195
|
+
}
|
|
196
|
+
return `;${key}=${value}`;
|
|
197
|
+
}
|
|
198
|
+
return `;${key}=${serializeString(value)}`;
|
|
199
|
+
});
|
|
200
|
+
return list + rendered.join('');
|
|
201
|
+
}
|
|
202
|
+
/** Validate a dictionary key (signature label). */
|
|
203
|
+
export function assertLabel(label) {
|
|
204
|
+
if (!KEY_RE.test(label))
|
|
205
|
+
throw new Error(`invalid signature label "${label}"`);
|
|
206
|
+
}
|
|
207
|
+
//# sourceMappingURL=rfc9421-fields.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rfc9421-fields.js","sourceRoot":"","sources":["../../src/visa-tap/rfc9421-fields.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,19 +1,37 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* RFC 9421 HTTP Message Signatures
|
|
2
|
+
* RFC 9421 HTTP Message Signatures (Ed25519)
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* The signer lists every component it signs, in signing order, in the
|
|
5
|
+
* `Signature-Input` field, and the `@signature-params` line of the signature
|
|
6
|
+
* base is byte-identical to that field's value, so any RFC 9421 verifier can
|
|
7
|
+
* rebuild the same base. The verifier is driven by the received
|
|
8
|
+
* `Signature-Input`: it rebuilds the base in the listed order, refuses
|
|
9
|
+
* components the caller relies on but the signer did not cover, and checks
|
|
10
|
+
* `created`, `expires` and `alg`.
|
|
5
11
|
*/
|
|
6
|
-
import type { SignatureComponents, SignedHttpMessage } from './types.js';
|
|
12
|
+
import type { SignatureComponents, SignedHttpMessage, SignHttpMessageOptions, VerifiableHttpSignature, VerifyHttpSignatureOptions } from './types.js';
|
|
7
13
|
/**
|
|
8
|
-
* Sign HTTP
|
|
14
|
+
* Sign an HTTP request per RFC 9421 with Ed25519.
|
|
15
|
+
*
|
|
16
|
+
* Covers `@method`, `@authority`, `@path`, then `content-digest` when
|
|
17
|
+
* `contentDigest` is given, then every entry of `headers` in insertion order.
|
|
18
|
+
* All of them are listed, in that order, in `Signature-Input`.
|
|
9
19
|
*/
|
|
10
|
-
export declare function signHttpMessage(components: SignatureComponents, privateKeyHex: string, keyId: string): Promise<SignedHttpMessage>;
|
|
20
|
+
export declare function signHttpMessage(components: SignatureComponents, privateKeyHex: string, keyId: string, options?: SignHttpMessageOptions): Promise<SignedHttpMessage>;
|
|
11
21
|
/**
|
|
12
|
-
* Verify RFC 9421 HTTP
|
|
22
|
+
* Verify an RFC 9421 Ed25519 signature on an HTTP request.
|
|
23
|
+
*
|
|
24
|
+
* `components` is the verifier's view of the received request. The signature
|
|
25
|
+
* base is rebuilt from the received `Signature-Input` (its order, its
|
|
26
|
+
* parameters). Verification fails unless every supplied component, including
|
|
27
|
+
* `contentDigest` and every entry of `headers`, is covered, `created` is
|
|
28
|
+
* present and no older than `maxAgeSeconds` (and not in the future beyond the
|
|
29
|
+
* clock skew), `expires` (if present) has not passed, and `alg` (if present)
|
|
30
|
+
* is `ed25519`. Never throws; returns false on any failure.
|
|
13
31
|
*
|
|
14
|
-
* @param maxAgeSeconds - Maximum age of signature in seconds (default
|
|
32
|
+
* @param maxAgeSeconds - Maximum age of the signature in seconds (default 300)
|
|
15
33
|
*/
|
|
16
|
-
export declare function verifyHttpSignature(components: SignatureComponents, signed:
|
|
34
|
+
export declare function verifyHttpSignature(components: SignatureComponents, signed: VerifiableHttpSignature, publicKeyHex: string, maxAgeSeconds?: number, options?: VerifyHttpSignatureOptions): Promise<boolean>;
|
|
17
35
|
/**
|
|
18
36
|
* Compute content digest (SHA-256)
|
|
19
37
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rfc9421.d.ts","sourceRoot":"","sources":["../../src/visa-tap/rfc9421.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"rfc9421.d.ts","sourceRoot":"","sources":["../../src/visa-tap/rfc9421.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAMH,OAAO,KAAK,EACV,mBAAmB,EACnB,iBAAiB,EACjB,sBAAsB,EACtB,uBAAuB,EACvB,0BAA0B,EAC3B,MAAM,YAAY,CAAC;AA4EpB;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,UAAU,EAAE,mBAAmB,EAC/B,aAAa,EAAE,MAAM,EACrB,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,iBAAiB,CAAC,CAkC5B;AAqED;;;;;;;;;;;;GAYG;AACH,wBAAsB,mBAAmB,CACvC,UAAU,EAAE,mBAAmB,EAC/B,MAAM,EAAE,uBAAuB,EAC/B,YAAY,EAAE,MAAM,EACpB,aAAa,GAAE,MAAY,EAC3B,OAAO,GAAE,0BAA+B,GACvC,OAAO,CAAC,OAAO,CAAC,CAwBlB;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAI7D"}
|
package/dist/visa-tap/rfc9421.js
CHANGED
|
@@ -1,95 +1,212 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* RFC 9421 HTTP Message Signatures
|
|
2
|
+
* RFC 9421 HTTP Message Signatures (Ed25519)
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* The signer lists every component it signs, in signing order, in the
|
|
5
|
+
* `Signature-Input` field, and the `@signature-params` line of the signature
|
|
6
|
+
* base is byte-identical to that field's value, so any RFC 9421 verifier can
|
|
7
|
+
* rebuild the same base. The verifier is driven by the received
|
|
8
|
+
* `Signature-Input`: it rebuilds the base in the listed order, refuses
|
|
9
|
+
* components the caller relies on but the signer did not cover, and checks
|
|
10
|
+
* `created`, `expires` and `alg`.
|
|
5
11
|
*/
|
|
6
12
|
import { sha256 } from '@noble/hashes/sha256';
|
|
13
|
+
import { sha512 } from '@noble/hashes/sha512';
|
|
7
14
|
import { bytesToHex, hexToBytes } from '@noble/hashes/utils';
|
|
8
15
|
import * as ed25519 from '@noble/ed25519';
|
|
16
|
+
import { assertLabel, parseSignatureField, parseSignatureInputField, serializeSignatureParams, serializeString, } from './rfc9421-fields.js';
|
|
17
|
+
ed25519.etc.sha512Sync = (...m) => sha512(ed25519.etc.concatBytes(...m));
|
|
18
|
+
const ALG = 'ed25519';
|
|
19
|
+
const DEFAULT_LABEL = 'sig1';
|
|
20
|
+
const DEFAULT_EXPIRES_IN = 300;
|
|
21
|
+
const DEFAULT_CLOCK_SKEW = 30;
|
|
22
|
+
/** Derived components this implementation can resolve, in signing order. */
|
|
23
|
+
const DERIVED = ['@method', '@authority', '@path'];
|
|
24
|
+
const FIELD_NAME_RE = /^[a-z0-9!#$%&'*+.^_`|~-]+$/;
|
|
25
|
+
function assertFieldValue(name, value) {
|
|
26
|
+
if (/[\r\n\0]/.test(value)) {
|
|
27
|
+
throw new Error(`component "${name}" contains CR, LF or NUL`);
|
|
28
|
+
}
|
|
29
|
+
return value.trim();
|
|
30
|
+
}
|
|
9
31
|
/**
|
|
10
|
-
*
|
|
32
|
+
* Resolve the caller's view of the message into canonical component values.
|
|
33
|
+
* Field names are lowercased; a name supplied twice (in any case) is an error.
|
|
11
34
|
*/
|
|
12
|
-
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
if (
|
|
22
|
-
|
|
35
|
+
function resolveComponents(components) {
|
|
36
|
+
const values = new Map();
|
|
37
|
+
const method = assertFieldValue('@method', components.method);
|
|
38
|
+
const authority = assertFieldValue('@authority', components.authority).toLowerCase();
|
|
39
|
+
let path = assertFieldValue('@path', components.path);
|
|
40
|
+
if (path === '')
|
|
41
|
+
path = '/';
|
|
42
|
+
if (!method || !authority)
|
|
43
|
+
throw new Error('@method and @authority must be non-empty');
|
|
44
|
+
if (!path.startsWith('/') || path.includes('?')) {
|
|
45
|
+
throw new Error('@path must be an absolute path without a query');
|
|
23
46
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
47
|
+
values.set('@method', method);
|
|
48
|
+
values.set('@authority', authority);
|
|
49
|
+
values.set('@path', path);
|
|
50
|
+
if (components.contentDigest !== undefined) {
|
|
51
|
+
values.set('content-digest', assertFieldValue('content-digest', components.contentDigest));
|
|
52
|
+
}
|
|
53
|
+
for (const [rawName, rawValue] of Object.entries(components.headers ?? {})) {
|
|
54
|
+
const name = rawName.toLowerCase();
|
|
55
|
+
if (!FIELD_NAME_RE.test(name))
|
|
56
|
+
throw new Error(`invalid header name "${rawName}"`);
|
|
57
|
+
if (values.has(name))
|
|
58
|
+
throw new Error(`header "${name}" is supplied more than once`);
|
|
59
|
+
values.set(name, assertFieldValue(name, rawValue));
|
|
60
|
+
}
|
|
61
|
+
return values;
|
|
62
|
+
}
|
|
63
|
+
function buildSignatureBase(covered, values, signatureParams) {
|
|
64
|
+
const lines = covered.map((name) => {
|
|
65
|
+
const value = values.get(name);
|
|
66
|
+
if (value === undefined)
|
|
67
|
+
throw new Error(`covered component "${name}" is not available`);
|
|
68
|
+
return `${serializeString(name)}: ${value}`;
|
|
69
|
+
});
|
|
70
|
+
lines.push(`"@signature-params": ${signatureParams}`);
|
|
71
|
+
return lines.join('\n');
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Sign an HTTP request per RFC 9421 with Ed25519.
|
|
75
|
+
*
|
|
76
|
+
* Covers `@method`, `@authority`, `@path`, then `content-digest` when
|
|
77
|
+
* `contentDigest` is given, then every entry of `headers` in insertion order.
|
|
78
|
+
* All of them are listed, in that order, in `Signature-Input`.
|
|
79
|
+
*/
|
|
80
|
+
export async function signHttpMessage(components, privateKeyHex, keyId, options = {}) {
|
|
81
|
+
const label = options.label ?? DEFAULT_LABEL;
|
|
82
|
+
assertLabel(label);
|
|
83
|
+
const values = resolveComponents(components);
|
|
84
|
+
const covered = [...values.keys()];
|
|
85
|
+
const created = options.created ?? Math.floor(Date.now() / 1000);
|
|
86
|
+
const expiresIn = options.expiresInSeconds ?? DEFAULT_EXPIRES_IN;
|
|
87
|
+
if (!Number.isInteger(created) || created < 0)
|
|
88
|
+
throw new Error('created must be a non-negative integer');
|
|
89
|
+
if (!Number.isInteger(expiresIn) || expiresIn < 0) {
|
|
90
|
+
throw new Error('expiresInSeconds must be a non-negative integer');
|
|
28
91
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
92
|
+
const expires = expiresIn > 0 ? created + expiresIn : undefined;
|
|
93
|
+
const nonce = options.nonce ?? generateNonce();
|
|
94
|
+
const params = [['created', created]];
|
|
95
|
+
if (expires !== undefined)
|
|
96
|
+
params.push(['expires', expires]);
|
|
97
|
+
params.push(['nonce', nonce], ['keyid', keyId], ['alg', ALG]);
|
|
98
|
+
if (options.tag !== undefined)
|
|
99
|
+
params.push(['tag', options.tag]);
|
|
100
|
+
const signatureParams = serializeSignatureParams(covered, params);
|
|
101
|
+
const signatureBase = buildSignatureBase(covered, values, signatureParams);
|
|
102
|
+
const signatureBytes = ed25519.sign(new TextEncoder().encode(signatureBase), hexToBytes(privateKeyHex));
|
|
36
103
|
const signatureB64 = Buffer.from(signatureBytes).toString('base64');
|
|
37
|
-
// Build Signature-Input header
|
|
38
|
-
const signatureInput = `sig1=("@method" "@authority" "@path");created=${created};nonce="${nonce}";keyid="${keyId}";alg="ed25519"`;
|
|
39
104
|
return {
|
|
40
|
-
signatureInput
|
|
41
|
-
signature:
|
|
105
|
+
signatureInput: `${label}=${signatureParams}`,
|
|
106
|
+
signature: `${label}=:${signatureB64}:`,
|
|
42
107
|
nonce,
|
|
43
108
|
created,
|
|
109
|
+
...(expires !== undefined ? { expires } : {}),
|
|
110
|
+
coveredComponents: covered,
|
|
44
111
|
};
|
|
45
112
|
}
|
|
113
|
+
function selectMember(members, label, field) {
|
|
114
|
+
if (label !== undefined) {
|
|
115
|
+
const value = members.get(label);
|
|
116
|
+
if (value === undefined)
|
|
117
|
+
throw new Error(`${field} has no member "${label}"`);
|
|
118
|
+
return [label, value];
|
|
119
|
+
}
|
|
120
|
+
if (members.size !== 1)
|
|
121
|
+
throw new Error(`${field} has ${members.size} members; pass options.label`);
|
|
122
|
+
return [...members.entries()][0];
|
|
123
|
+
}
|
|
124
|
+
function checkParams(input, signed, maxAgeSeconds, options) {
|
|
125
|
+
const params = new Map(input.params);
|
|
126
|
+
const created = params.get('created');
|
|
127
|
+
const expires = params.get('expires');
|
|
128
|
+
const alg = params.get('alg');
|
|
129
|
+
const now = options.now ?? Math.floor(Date.now() / 1000);
|
|
130
|
+
const skew = options.clockSkewSeconds ?? DEFAULT_CLOCK_SKEW;
|
|
131
|
+
if (typeof created !== 'number')
|
|
132
|
+
throw new Error('signature has no created parameter');
|
|
133
|
+
if (created > now + skew)
|
|
134
|
+
throw new Error('signature created in the future');
|
|
135
|
+
if (now - created > maxAgeSeconds)
|
|
136
|
+
throw new Error('signature is older than maxAgeSeconds');
|
|
137
|
+
if (expires !== undefined) {
|
|
138
|
+
if (typeof expires !== 'number' || expires < created)
|
|
139
|
+
throw new Error('invalid expires parameter');
|
|
140
|
+
if (now > expires + skew)
|
|
141
|
+
throw new Error('signature has expired');
|
|
142
|
+
}
|
|
143
|
+
else if (options.requireExpires) {
|
|
144
|
+
throw new Error('signature has no expires parameter');
|
|
145
|
+
}
|
|
146
|
+
if (alg !== undefined && alg !== ALG)
|
|
147
|
+
throw new Error(`unsupported alg "${String(alg)}"`);
|
|
148
|
+
if (options.expectedKeyId !== undefined && params.get('keyid') !== options.expectedKeyId) {
|
|
149
|
+
throw new Error('keyid does not match the expected key');
|
|
150
|
+
}
|
|
151
|
+
if (signed.created !== undefined && signed.created !== created) {
|
|
152
|
+
throw new Error('created does not match Signature-Input');
|
|
153
|
+
}
|
|
154
|
+
if (signed.nonce !== undefined && signed.nonce !== params.get('nonce')) {
|
|
155
|
+
throw new Error('nonce does not match Signature-Input');
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
function checkCoverage(covered, values, options) {
|
|
159
|
+
const seen = new Set();
|
|
160
|
+
for (const name of covered) {
|
|
161
|
+
if (seen.has(name))
|
|
162
|
+
throw new Error(`component "${name}" is listed twice`);
|
|
163
|
+
seen.add(name);
|
|
164
|
+
if (name.startsWith('@') && !DERIVED.includes(name)) {
|
|
165
|
+
throw new Error(`unsupported derived component "${name}"`);
|
|
166
|
+
}
|
|
167
|
+
if (!name.startsWith('@') && !FIELD_NAME_RE.test(name)) {
|
|
168
|
+
throw new Error(`invalid component name "${name}"`);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
// Everything the caller relies on must be covered; nothing unlisted is trusted.
|
|
172
|
+
const required = [...values.keys(), ...(options.requiredComponents ?? []).map((n) => n.toLowerCase())];
|
|
173
|
+
for (const name of required) {
|
|
174
|
+
if (!seen.has(name))
|
|
175
|
+
throw new Error(`component "${name}" is not covered by the signature`);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
46
178
|
/**
|
|
47
|
-
* Verify RFC 9421 HTTP
|
|
179
|
+
* Verify an RFC 9421 Ed25519 signature on an HTTP request.
|
|
180
|
+
*
|
|
181
|
+
* `components` is the verifier's view of the received request. The signature
|
|
182
|
+
* base is rebuilt from the received `Signature-Input` (its order, its
|
|
183
|
+
* parameters). Verification fails unless every supplied component, including
|
|
184
|
+
* `contentDigest` and every entry of `headers`, is covered, `created` is
|
|
185
|
+
* present and no older than `maxAgeSeconds` (and not in the future beyond the
|
|
186
|
+
* clock skew), `expires` (if present) has not passed, and `alg` (if present)
|
|
187
|
+
* is `ed25519`. Never throws; returns false on any failure.
|
|
48
188
|
*
|
|
49
|
-
* @param maxAgeSeconds - Maximum age of signature in seconds (default
|
|
189
|
+
* @param maxAgeSeconds - Maximum age of the signature in seconds (default 300)
|
|
50
190
|
*/
|
|
51
|
-
export async function verifyHttpSignature(components, signed, publicKeyHex, maxAgeSeconds = 300) {
|
|
191
|
+
export async function verifyHttpSignature(components, signed, publicKeyHex, maxAgeSeconds = 300, options = {}) {
|
|
52
192
|
try {
|
|
53
|
-
|
|
54
|
-
const
|
|
55
|
-
const
|
|
56
|
-
if (
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
}
|
|
69
|
-
if (components.headers) {
|
|
70
|
-
for (const [name, value] of Object.entries(components.headers)) {
|
|
71
|
-
baseParts.push(`"${name.toLowerCase()}": ${value}`);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
// Extract keyid from signature input
|
|
75
|
-
const keyId = extractKeyId(signed.signatureInput);
|
|
76
|
-
// Add signature parameters
|
|
77
|
-
baseParts.push(`"@signature-params": ("@method" "@authority" "@path");created=${signed.created};nonce="${signed.nonce}";keyid="${keyId}"`);
|
|
78
|
-
const signatureBase = baseParts.join('\n');
|
|
79
|
-
// Extract signature bytes
|
|
80
|
-
const sigMatch = signed.signature.match(/^sig1=:(.+):$/);
|
|
81
|
-
if (!sigMatch || !sigMatch[1]) {
|
|
82
|
-
throw new Error('Invalid signature format');
|
|
83
|
-
}
|
|
84
|
-
const signatureB64 = sigMatch[1];
|
|
85
|
-
const signatureBytes = Buffer.from(signatureB64, 'base64');
|
|
86
|
-
// Verify with Ed25519
|
|
87
|
-
const publicKey = hexToBytes(publicKeyHex);
|
|
88
|
-
const messageBytes = new TextEncoder().encode(signatureBase);
|
|
89
|
-
return await ed25519.verify(signatureBytes, messageBytes, publicKey);
|
|
193
|
+
const [label, input] = selectMember(parseSignatureInputField(signed.signatureInput), options.label, 'Signature-Input');
|
|
194
|
+
const signatures = parseSignatureField(signed.signature);
|
|
195
|
+
const signatureBytes = signatures.get(label);
|
|
196
|
+
if (!signatureBytes)
|
|
197
|
+
throw new Error(`Signature has no member "${label}"`);
|
|
198
|
+
if (signatureBytes.length !== 64)
|
|
199
|
+
throw new Error('Ed25519 signatures are 64 bytes');
|
|
200
|
+
const values = resolveComponents(components);
|
|
201
|
+
checkCoverage(input.components, values, options);
|
|
202
|
+
checkParams(input, signed, maxAgeSeconds, options);
|
|
203
|
+
const signatureParams = serializeSignatureParams(input.components, input.params);
|
|
204
|
+
const signatureBase = buildSignatureBase(input.components, values, signatureParams);
|
|
205
|
+
return ed25519.verify(signatureBytes, new TextEncoder().encode(signatureBase), hexToBytes(publicKeyHex), {
|
|
206
|
+
zip215: false,
|
|
207
|
+
});
|
|
90
208
|
}
|
|
91
|
-
catch
|
|
92
|
-
console.error('Signature verification failed:', error);
|
|
209
|
+
catch {
|
|
93
210
|
return false;
|
|
94
211
|
}
|
|
95
212
|
}
|
|
@@ -109,14 +226,4 @@ function generateNonce() {
|
|
|
109
226
|
crypto.getRandomValues(bytes);
|
|
110
227
|
return bytesToHex(bytes);
|
|
111
228
|
}
|
|
112
|
-
/**
|
|
113
|
-
* Extract keyid from Signature-Input header
|
|
114
|
-
*/
|
|
115
|
-
function extractKeyId(signatureInput) {
|
|
116
|
-
const match = signatureInput.match(/keyid="([^"]+)"/);
|
|
117
|
-
if (!match || !match[1]) {
|
|
118
|
-
throw new Error('Missing keyid in signature-input');
|
|
119
|
-
}
|
|
120
|
-
return match[1];
|
|
121
|
-
}
|
|
122
229
|
//# sourceMappingURL=rfc9421.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rfc9421.js","sourceRoot":"","sources":["../../src/visa-tap/rfc9421.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"rfc9421.js","sourceRoot":"","sources":["../../src/visa-tap/rfc9421.ts"],"names":[],"mappings":"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"}
|
package/dist/visa-tap/types.d.ts
CHANGED
|
@@ -61,10 +61,10 @@ export interface SignatureComponents {
|
|
|
61
61
|
headers?: Record<string, string>;
|
|
62
62
|
}
|
|
63
63
|
/**
|
|
64
|
-
* RFC 9421 Signed HTTP Message
|
|
64
|
+
* RFC 9421 Signed HTTP Message, as returned by signHttpMessage
|
|
65
65
|
*/
|
|
66
66
|
export interface SignedHttpMessage {
|
|
67
|
-
/** Signature-Input header value */
|
|
67
|
+
/** Signature-Input header value; lists every covered component, in order */
|
|
68
68
|
signatureInput: string;
|
|
69
69
|
/** Signature header value */
|
|
70
70
|
signature: string;
|
|
@@ -72,6 +72,56 @@ export interface SignedHttpMessage {
|
|
|
72
72
|
nonce: string;
|
|
73
73
|
/** Creation timestamp (Unix seconds) */
|
|
74
74
|
created: number;
|
|
75
|
+
/** Expiry timestamp (Unix seconds), when one was set */
|
|
76
|
+
expires?: number;
|
|
77
|
+
/** Covered component identifiers, in signing order */
|
|
78
|
+
coveredComponents: string[];
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* A received RFC 9421 signature to verify. Only the two header values are
|
|
82
|
+
* required; `created` and `nonce`, when given, must match Signature-Input.
|
|
83
|
+
*/
|
|
84
|
+
export interface VerifiableHttpSignature {
|
|
85
|
+
/** Signature-Input header value */
|
|
86
|
+
signatureInput: string;
|
|
87
|
+
/** Signature header value */
|
|
88
|
+
signature: string;
|
|
89
|
+
/** Expected nonce (must equal the signed nonce parameter) */
|
|
90
|
+
nonce?: string;
|
|
91
|
+
/** Expected created time (must equal the signed created parameter) */
|
|
92
|
+
created?: number;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Options for signHttpMessage
|
|
96
|
+
*/
|
|
97
|
+
export interface SignHttpMessageOptions {
|
|
98
|
+
/** Signature label (default "sig1") */
|
|
99
|
+
label?: string;
|
|
100
|
+
/** Creation time in Unix seconds (default: now) */
|
|
101
|
+
created?: number;
|
|
102
|
+
/** Lifetime written to the expires parameter (default 300; 0 omits expires) */
|
|
103
|
+
expiresInSeconds?: number;
|
|
104
|
+
/** Nonce (default: 16 random bytes, hex) */
|
|
105
|
+
nonce?: string;
|
|
106
|
+
/** Optional tag parameter */
|
|
107
|
+
tag?: string;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Options for verifyHttpSignature
|
|
111
|
+
*/
|
|
112
|
+
export interface VerifyHttpSignatureOptions {
|
|
113
|
+
/** Label to verify; required when Signature-Input has several members */
|
|
114
|
+
label?: string;
|
|
115
|
+
/** Current time in Unix seconds (default: now) */
|
|
116
|
+
now?: number;
|
|
117
|
+
/** Allowed clock skew for created/expires in seconds (default 30) */
|
|
118
|
+
clockSkewSeconds?: number;
|
|
119
|
+
/** Reject unless the keyid parameter equals this value */
|
|
120
|
+
expectedKeyId?: string;
|
|
121
|
+
/** Extra component identifiers that must be covered */
|
|
122
|
+
requiredComponents?: string[];
|
|
123
|
+
/** Reject signatures that carry no expires parameter */
|
|
124
|
+
requireExpires?: boolean;
|
|
75
125
|
}
|
|
76
126
|
/**
|
|
77
127
|
* QUIC Transport Configuration
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/visa-tap/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;GAEG;AACH,MAAM,MAAM,MAAM,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,GAAG,SAAS,CAAC;AAE/D;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,MAAM,CAAC;AAE5C;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,2BAA2B;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,iCAAiC;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,oDAAoD;IACpD,MAAM,EAAE,MAAM,CAAC;IACf,+BAA+B;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,mBAAmB;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,mBAAmB;IACnB,IAAI,EAAE,WAAW,CAAC;IAClB,sCAAsC;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,iCAAiC;IACjC,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,iCAAiC;IACjC,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,cAAc;IACd,OAAO,EAAE,oBAAoB,CAAC;IAC9B,sCAAsC;IACtC,SAAS,EAAE,MAAM,CAAC;IAClB,+BAA+B;IAC/B,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,kBAAkB;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,uBAAuB;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,mBAAmB;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,+BAA+B;IAC/B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iCAAiC;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/visa-tap/types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agentic-payments",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.16",
|
|
4
4
|
"description": "Dual-protocol payment infrastructure for autonomous AI commerce (AP2 + ACP)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -12,20 +12,6 @@
|
|
|
12
12
|
"import": "./dist/index.js",
|
|
13
13
|
"default": "./dist/index.js"
|
|
14
14
|
},
|
|
15
|
-
"./wasm": {
|
|
16
|
-
"types": "./dist/wasm/index.d.ts",
|
|
17
|
-
"import": "./dist/wasm/index.js",
|
|
18
|
-
"browser": "./dist/wasm/browser.js",
|
|
19
|
-
"node": "./dist/wasm/node.js"
|
|
20
|
-
},
|
|
21
|
-
"./ap2": {
|
|
22
|
-
"types": "./dist/ap2/index.d.ts",
|
|
23
|
-
"import": "./dist/ap2/index.js"
|
|
24
|
-
},
|
|
25
|
-
"./acp": {
|
|
26
|
-
"types": "./dist/acp/index.d.ts",
|
|
27
|
-
"import": "./dist/acp/index.js"
|
|
28
|
-
},
|
|
29
15
|
"./visa-tap": {
|
|
30
16
|
"types": "./dist/visa-tap/index.d.ts",
|
|
31
17
|
"import": "./dist/visa-tap/index.js"
|
|
@@ -96,15 +82,7 @@
|
|
|
96
82
|
],
|
|
97
83
|
"author": "rUv <ruv@ruv.io>",
|
|
98
84
|
"license": "(MIT OR Apache-2.0)",
|
|
99
|
-
"
|
|
100
|
-
"type": "git",
|
|
101
|
-
"url": "https://github.com/agentic-catalog/agentic-payments.git",
|
|
102
|
-
"directory": "crates/agentic-payments"
|
|
103
|
-
},
|
|
104
|
-
"bugs": {
|
|
105
|
-
"url": "https://github.com/agentic-catalog/agentic-payments/issues"
|
|
106
|
-
},
|
|
107
|
-
"homepage": "https://github.com/agentic-catalog/agentic-payments#readme",
|
|
85
|
+
"homepage": "https://www.npmjs.com/package/agentic-payments",
|
|
108
86
|
"engines": {
|
|
109
87
|
"node": ">=18.0.0",
|
|
110
88
|
"npm": ">=8.0.0"
|
|
@@ -140,6 +118,7 @@
|
|
|
140
118
|
"eslint-config-prettier": "^9.1.0",
|
|
141
119
|
"eslint-plugin-import": "^2.29.1",
|
|
142
120
|
"eventsource": "^4.0.0",
|
|
121
|
+
"http-message-signatures": "^1.0.6",
|
|
143
122
|
"node-fetch": "^3.3.2",
|
|
144
123
|
"prettier": "^3.2.4",
|
|
145
124
|
"size-limit": "^11.0.1",
|