@peac/protocol 0.15.3 → 0.16.1
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/index.cjs +86 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +86 -3
- package/dist/index.mjs.map +1 -1
- package/dist/replay-guard.d.ts +55 -0
- package/dist/replay-guard.d.ts.map +1 -0
- package/dist/verify-local-wire01.d.ts.map +1 -1
- package/dist/verify-local.cjs +11 -2
- package/dist/verify-local.cjs.map +1 -1
- package/dist/verify-local.d.ts +1 -1
- package/dist/verify-local.d.ts.map +1 -1
- package/dist/verify-local.mjs +11 -2
- package/dist/verify-local.mjs.map +1 -1
- package/package.json +4 -4
package/dist/index.d.ts
CHANGED
|
@@ -17,5 +17,6 @@ export * from './verification-report';
|
|
|
17
17
|
export * from './ssrf-safe-fetch';
|
|
18
18
|
export * from './transport-profiles';
|
|
19
19
|
export * from './pointer-fetch';
|
|
20
|
+
export * from './replay-guard';
|
|
20
21
|
export { base64urlDecode, base64urlEncode, computeJwkThumbprint, generateKeypair, jwkToPublicKeyBytes, sha256Bytes, sha256Hex, verify, } from '@peac/crypto';
|
|
21
22
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,YAAY,EACV,GAAG,EACH,IAAI,EACJ,cAAc,EACd,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,mBAAmB,EACnB,oBAAoB,EACpB,cAAc,EACd,gBAAgB,EAChB,WAAW,GACZ,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAK9E,OAAO,EACL,4BAA4B,EAC5B,6BAA6B,EAC7B,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,oBAAoB,CAAC;AAG5B,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC;AAChC,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,cAAc,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,YAAY,EACV,GAAG,EACH,IAAI,EACJ,cAAc,EACd,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,mBAAmB,EACnB,oBAAoB,EACpB,cAAc,EACd,gBAAgB,EAChB,WAAW,GACZ,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAK9E,OAAO,EACL,4BAA4B,EAC5B,6BAA6B,EAC7B,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,oBAAoB,CAAC;AAG5B,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC;AAChC,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,cAAc,iBAAiB,CAAC;AAIhC,cAAc,gBAAgB,CAAC;AAG/B,OAAO,EACL,eAAe,EACf,eAAe,EACf,oBAAoB,EACpB,eAAe,EACf,mBAAmB,EACnB,WAAW,EACX,SAAS,EACT,MAAM,GACP,MAAM,cAAc,CAAC"}
|
package/dist/index.mjs
CHANGED
|
@@ -2405,7 +2405,14 @@ var JOSE_CODE_MAP = {
|
|
|
2405
2405
|
CRYPTO_JWS_CRIT_REJECTED: "E_JWS_CRIT_REJECTED",
|
|
2406
2406
|
CRYPTO_JWS_MISSING_KID: "E_JWS_MISSING_KID",
|
|
2407
2407
|
CRYPTO_JWS_B64_REJECTED: "E_JWS_B64_REJECTED",
|
|
2408
|
-
CRYPTO_JWS_ZIP_REJECTED: "E_JWS_ZIP_REJECTED"
|
|
2408
|
+
CRYPTO_JWS_ZIP_REJECTED: "E_JWS_ZIP_REJECTED",
|
|
2409
|
+
// Raw-input I-JSON gate (RFC 7493): specific E_IJSON_* codes so callers can
|
|
2410
|
+
// distinguish duplicate member names, out-of-range numbers, and invalid
|
|
2411
|
+
// strings from ordinary format errors. (Generic JSON syntax errors from the
|
|
2412
|
+
// gate use CRYPTO_INVALID_JWS_FORMAT -> E_INVALID_FORMAT via FORMAT_ERROR_CODES.)
|
|
2413
|
+
CRYPTO_IJSON_DUPLICATE_MEMBER_NAME: "E_IJSON_DUPLICATE_MEMBER_NAME",
|
|
2414
|
+
CRYPTO_IJSON_NUMBER_OUT_OF_RANGE: "E_IJSON_NUMBER_OUT_OF_RANGE",
|
|
2415
|
+
CRYPTO_IJSON_INVALID_STRING: "E_IJSON_INVALID_STRING"
|
|
2409
2416
|
};
|
|
2410
2417
|
var MAX_PARSE_ISSUES = 25;
|
|
2411
2418
|
function sanitizeParseIssues(issues) {
|
|
@@ -2429,10 +2436,12 @@ async function verifyLocal(jws, publicKey, options = {}) {
|
|
|
2429
2436
|
try {
|
|
2430
2437
|
const result = await defaultCodec.decode(jws, publicKey);
|
|
2431
2438
|
if (!result.valid) {
|
|
2439
|
+
const signatureBytes = ed25519SignatureByteLength(jws);
|
|
2440
|
+
const invalidLength = signatureBytes !== null && signatureBytes !== ED25519_SIGNATURE_BYTES;
|
|
2432
2441
|
return {
|
|
2433
2442
|
valid: false,
|
|
2434
2443
|
code: "E_INVALID_SIGNATURE",
|
|
2435
|
-
message: "Ed25519 signature verification failed"
|
|
2444
|
+
message: invalidLength ? "Ed25519 signature has invalid length" : "Ed25519 signature verification failed"
|
|
2436
2445
|
};
|
|
2437
2446
|
}
|
|
2438
2447
|
const accumulatedWarnings = [];
|
|
@@ -4071,6 +4080,80 @@ async function verifyAndFetchPointer(pointerHeader, fetchOptions) {
|
|
|
4071
4080
|
});
|
|
4072
4081
|
}
|
|
4073
4082
|
|
|
4074
|
-
|
|
4083
|
+
// src/replay-guard.ts
|
|
4084
|
+
var DEFAULT_MAX_CLOCK_SKEW_SECONDS = 300;
|
|
4085
|
+
var DEFAULT_MAX_ENTRIES = 1e5;
|
|
4086
|
+
function safeInteger(value, name) {
|
|
4087
|
+
if (!Number.isSafeInteger(value)) {
|
|
4088
|
+
throw new Error(`createReplayGuard: ${name} must be a safe integer`);
|
|
4089
|
+
}
|
|
4090
|
+
return value;
|
|
4091
|
+
}
|
|
4092
|
+
function positiveInt(value, name) {
|
|
4093
|
+
safeInteger(value, name);
|
|
4094
|
+
if (value <= 0) {
|
|
4095
|
+
throw new Error(`createReplayGuard: ${name} must be a positive integer`);
|
|
4096
|
+
}
|
|
4097
|
+
return value;
|
|
4098
|
+
}
|
|
4099
|
+
function nonNegativeInt(value, name) {
|
|
4100
|
+
safeInteger(value, name);
|
|
4101
|
+
if (value < 0) {
|
|
4102
|
+
throw new Error(`createReplayGuard: ${name} must be a non-negative integer`);
|
|
4103
|
+
}
|
|
4104
|
+
return value;
|
|
4105
|
+
}
|
|
4106
|
+
function nonEmptyString(value, name) {
|
|
4107
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
4108
|
+
throw new Error(`createReplayGuard: ${name} must be a non-empty string`);
|
|
4109
|
+
}
|
|
4110
|
+
return value;
|
|
4111
|
+
}
|
|
4112
|
+
function createReplayGuard(options) {
|
|
4113
|
+
const windowSeconds = positiveInt(options.windowSeconds, "windowSeconds");
|
|
4114
|
+
const maxClockSkewSeconds = options.maxClockSkewSeconds === void 0 ? DEFAULT_MAX_CLOCK_SKEW_SECONDS : nonNegativeInt(options.maxClockSkewSeconds, "maxClockSkewSeconds");
|
|
4115
|
+
const maxEntries = options.maxEntries === void 0 ? DEFAULT_MAX_ENTRIES : positiveInt(options.maxEntries, "maxEntries");
|
|
4116
|
+
const now = options.now ?? (() => Math.floor(Date.now() / 1e3));
|
|
4117
|
+
let lastNow = Number.NEGATIVE_INFINITY;
|
|
4118
|
+
const currentNow = () => {
|
|
4119
|
+
const raw = safeInteger(now(), "now()");
|
|
4120
|
+
if (raw < lastNow) return lastNow;
|
|
4121
|
+
lastNow = raw;
|
|
4122
|
+
return raw;
|
|
4123
|
+
};
|
|
4124
|
+
const seen = /* @__PURE__ */ new Map();
|
|
4125
|
+
const keyOf = (iss, jti) => `${iss.length}:${iss}${jti.length}:${jti}`;
|
|
4126
|
+
const purgeExpired = (nowSeconds) => {
|
|
4127
|
+
for (const [key, entry] of seen) {
|
|
4128
|
+
if (entry.expiresAt > nowSeconds) break;
|
|
4129
|
+
seen.delete(key);
|
|
4130
|
+
}
|
|
4131
|
+
};
|
|
4132
|
+
return {
|
|
4133
|
+
check(record) {
|
|
4134
|
+
const iat = safeInteger(record.iat, "record.iat");
|
|
4135
|
+
const iss = nonEmptyString(record.iss, "record.iss");
|
|
4136
|
+
const jti = nonEmptyString(record.jti, "record.jti");
|
|
4137
|
+
const t = currentNow();
|
|
4138
|
+
purgeExpired(t);
|
|
4139
|
+
if (iat < t - windowSeconds || iat > t + maxClockSkewSeconds) {
|
|
4140
|
+
return "outside-window";
|
|
4141
|
+
}
|
|
4142
|
+
const key = keyOf(iss, jti);
|
|
4143
|
+
if (seen.has(key)) {
|
|
4144
|
+
return "replayed";
|
|
4145
|
+
}
|
|
4146
|
+
const expiresAt = safeInteger(t + windowSeconds + maxClockSkewSeconds, "entry expiry");
|
|
4147
|
+
if (seen.size >= maxEntries) {
|
|
4148
|
+
const oldest = seen.keys().next().value;
|
|
4149
|
+
if (oldest !== void 0) seen.delete(oldest);
|
|
4150
|
+
}
|
|
4151
|
+
seen.set(key, { expiresAt });
|
|
4152
|
+
return "fresh";
|
|
4153
|
+
}
|
|
4154
|
+
};
|
|
4155
|
+
}
|
|
4156
|
+
|
|
4157
|
+
export { CHECK_IDS, DEFAULT_NETWORK_SECURITY, DEFAULT_VERIFIER_LIMITS, IssueError, NON_DETERMINISTIC_ARTIFACT_KEYS, VerificationReportBuilder, buildFailureReport, buildSuccessReport, checkDocumentBinding, checkPolicyBinding, clearJWKSCache, clearKidThumbprints, computeDocumentDigest, computeJsonDocumentDigestJcs, computePolicyDigestJcs, computeReceiptDigest, computeTextDocumentDigestUtf8, createDefaultPolicy, createDigest, createEmptyReport, createReplayGuard, createReportBuilder, fetchDiscovery, fetchIssuerConfig, fetchJWKSSafe, fetchPointerSafe, fetchPointerWithDigest, fetchPolicyManifest, getJWKSCacheSize, getKidThumbprintSize, getPurposeHeader, getReceiptHeader, getSSRFCapabilities, isAttestationResult, isBlockedIP, isCommerceResult, isWire02Result, issue, issueJws, issueWire01, issueWire02, parseBodyProfile, parseDiscovery, parseHeaderProfile, parseIssuerConfig, parsePointerProfile, parsePolicyManifest, parseTransportProfile, reasonCodeToErrorCode, reasonCodeToSeverity, resetSSRFCapabilitiesCache, resolveJWKS, setPurposeAppliedHeader, setPurposeReasonHeader, setReceiptHeader, setVaryHeader, setVaryPurposeHeader, ssrfErrorToReasonCode, ssrfSafeFetch, verifyAndFetchPointer, verifyLocal, verifyReceipt, verifyReceiptCore };
|
|
4075
4158
|
//# sourceMappingURL=index.mjs.map
|
|
4076
4159
|
//# sourceMappingURL=index.mjs.map
|