@continuonai/rcan-ts 1.2.0 → 1.2.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/browser.d.mts +19 -44
- package/dist/browser.mjs +40 -66
- package/dist/browser.mjs.map +1 -1
- package/dist/index.d.mts +19 -44
- package/dist/index.d.ts +19 -44
- package/dist/index.js +42 -66
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +40 -66
- package/dist/index.mjs.map +1 -1
- package/dist/rcan-validate.js +0 -1
- package/dist/rcan.iife.js +2 -2
- package/package.json +5 -2
package/dist/browser.d.mts
CHANGED
|
@@ -109,8 +109,9 @@ interface DelegationHop {
|
|
|
109
109
|
scope: string;
|
|
110
110
|
signature: string;
|
|
111
111
|
}
|
|
112
|
+
/** RCAN v2.2: ML-DSA-65 is the only valid alg ("ml-dsa-65"). Ed25519 is deprecated. */
|
|
112
113
|
interface SignatureBlock {
|
|
113
|
-
alg:
|
|
114
|
+
alg: "ml-dsa-65";
|
|
114
115
|
kid: string;
|
|
115
116
|
sig: string;
|
|
116
117
|
}
|
|
@@ -767,7 +768,7 @@ declare function makeTransparencyMessage(ruri: string, disclosure: string, deleg
|
|
|
767
768
|
/** The RCAN spec version this SDK implements. */
|
|
768
769
|
declare const SPEC_VERSION = "2.2.0";
|
|
769
770
|
/** The SDK release version. */
|
|
770
|
-
declare const SDK_VERSION = "1.2.
|
|
771
|
+
declare const SDK_VERSION = "1.2.1";
|
|
771
772
|
/**
|
|
772
773
|
* Validate version compatibility.
|
|
773
774
|
*
|
|
@@ -1863,81 +1864,55 @@ declare function verifyM2mTrustedToken(token: string, targetRrn: string, options
|
|
|
1863
1864
|
}): Promise<M2MTrustedClaims>;
|
|
1864
1865
|
|
|
1865
1866
|
/**
|
|
1866
|
-
* RCAN v2.2
|
|
1867
|
-
*
|
|
1868
|
-
* Provides MLDSAKeyPair for post-quantum signing alongside the existing
|
|
1869
|
-
* Ed25519 SignatureBlock. In hybrid mode a message carries both:
|
|
1870
|
-
* - `signature` — Ed25519 SignatureBlock (backward-compat with v2.1)
|
|
1871
|
-
* - `pqSig` — MLDSASignatureBlock (new in v2.2)
|
|
1867
|
+
* RCAN v2.2 ML-DSA-65 Signing (NIST FIPS 204)
|
|
1872
1868
|
*
|
|
1873
|
-
*
|
|
1874
|
-
*
|
|
1875
|
-
* Private key: 4032 bytes
|
|
1876
|
-
* Signature: 3309 bytes
|
|
1869
|
+
* Ed25519 is deprecated. ML-DSA-65 is the ONLY signing algorithm.
|
|
1870
|
+
* All signed messages carry a ``signature`` block with ``alg: "ml-dsa-65"``.
|
|
1877
1871
|
*
|
|
1878
1872
|
* Requires: @noble/post-quantum (npm install @noble/post-quantum)
|
|
1879
1873
|
*
|
|
1880
|
-
* Spec: https://rcan.dev/spec#section-7-2
|
|
1874
|
+
* Spec: https://rcan.dev/spec/v2.2#section-7-2
|
|
1881
1875
|
*/
|
|
1882
1876
|
|
|
1883
|
-
/** @deprecated use PQSignatureBlock */
|
|
1884
|
-
type MLDSASignatureBlock = PQSignatureBlock;
|
|
1885
1877
|
interface MLDSAKeyPairData {
|
|
1886
|
-
/** Public key bytes (1952 bytes) */
|
|
1887
1878
|
publicKey: Uint8Array;
|
|
1888
|
-
/** Private key bytes (4032 bytes). Absent for verify-only key pairs. */
|
|
1889
1879
|
secretKey?: Uint8Array;
|
|
1890
|
-
/** 8-char hex key ID */
|
|
1891
1880
|
keyId: string;
|
|
1892
1881
|
}
|
|
1893
1882
|
/**
|
|
1894
1883
|
* An ML-DSA-65 (CRYSTALS-Dilithium, NIST FIPS 204) key pair.
|
|
1895
1884
|
*
|
|
1896
|
-
*
|
|
1897
|
-
* {@link MLDSAKeyPair.fromPublicKey}.
|
|
1885
|
+
* This is the ONLY signing key type in RCAN v2.2+. Ed25519 is deprecated.
|
|
1898
1886
|
*/
|
|
1899
1887
|
declare class MLDSAKeyPair {
|
|
1900
1888
|
readonly keyId: string;
|
|
1901
1889
|
readonly publicKey: Uint8Array;
|
|
1902
1890
|
readonly secretKey: Uint8Array | undefined;
|
|
1903
1891
|
private constructor();
|
|
1904
|
-
/** Generate a new ML-DSA-65 key pair. */
|
|
1905
1892
|
static generate(): Promise<MLDSAKeyPair>;
|
|
1906
|
-
/** Build a verify-only key pair from raw public key bytes. */
|
|
1907
1893
|
static fromPublicKey(publicKey: Uint8Array): Promise<MLDSAKeyPair>;
|
|
1908
|
-
/** Build a full key pair from saved bytes (public + secret). */
|
|
1909
1894
|
static fromKeyMaterial(publicKey: Uint8Array, secretKey: Uint8Array): Promise<MLDSAKeyPair>;
|
|
1910
1895
|
get hasPrivateKey(): boolean;
|
|
1911
|
-
/** Sign raw bytes; returns ML-DSA-65 signature (3309 bytes). */
|
|
1912
1896
|
signBytes(data: Uint8Array): Promise<Uint8Array>;
|
|
1913
|
-
/**
|
|
1914
|
-
* Verify an ML-DSA-65 signature.
|
|
1915
|
-
* @returns true if valid
|
|
1916
|
-
* @throws {Error} on invalid signature
|
|
1917
|
-
*/
|
|
1918
1897
|
verifyBytes(data: Uint8Array, signature: Uint8Array): Promise<void>;
|
|
1919
1898
|
toString(): string;
|
|
1920
1899
|
}
|
|
1921
1900
|
/**
|
|
1922
|
-
*
|
|
1923
|
-
*
|
|
1924
|
-
* This is the v2.2 hybrid complement to the existing Ed25519 signature.
|
|
1925
|
-
* Call {@link signMessageEd25519} (or the existing signing path) first to set
|
|
1926
|
-
* `signature`, then call this to append `pqSig`.
|
|
1901
|
+
* Sign an RCANMessage with ML-DSA-65 (the only signing algorithm in RCAN v2.2).
|
|
1927
1902
|
*
|
|
1928
|
-
*
|
|
1929
|
-
* @param keypair ML-DSA-65 key pair with private key
|
|
1930
|
-
* @returns The same message cast to include `pqSig`
|
|
1903
|
+
* Sets msg.signature = { alg: "ml-dsa-65", kid, sig }.
|
|
1931
1904
|
*/
|
|
1932
|
-
declare function
|
|
1905
|
+
declare function signMessage(msg: RCANMessage, keypair: MLDSAKeyPair): Promise<RCANMessage>;
|
|
1933
1906
|
/**
|
|
1934
|
-
* Verify the ML-DSA-65 signature
|
|
1907
|
+
* Verify the ML-DSA-65 signature on an RCANMessage.
|
|
1935
1908
|
*
|
|
1936
|
-
* @
|
|
1937
|
-
* @param trustedKeys Trusted ML-DSA public key pairs
|
|
1938
|
-
* @param requirePQ If true, raise when `pqSig` is absent (for post-2028 hard mode)
|
|
1909
|
+
* @throws {Error} if signature is missing, alg is not ml-dsa-65, key not found, or invalid.
|
|
1939
1910
|
*/
|
|
1940
|
-
declare function
|
|
1911
|
+
declare function verifyMessage(msg: RCANMessage, trustedKeys: MLDSAKeyPair[]): Promise<void>;
|
|
1912
|
+
/** @deprecated Use signMessage() — Ed25519 is removed in RCAN v2.2 */
|
|
1913
|
+
declare const addPQSignature: typeof signMessage;
|
|
1914
|
+
/** @deprecated Use verifyMessage() — Ed25519 is removed in RCAN v2.2 */
|
|
1915
|
+
declare function verifyPQSignature(msg: RCANMessage, trustedKeys: MLDSAKeyPair[], _requirePQ?: boolean): Promise<void>;
|
|
1941
1916
|
|
|
1942
1917
|
/**
|
|
1943
1918
|
* rcan-ts — Official TypeScript SDK for RCAN v1.6
|
|
@@ -1951,4 +1926,4 @@ declare const VERSION = "0.6.0";
|
|
|
1951
1926
|
/** @deprecated Use SPEC_VERSION from ./version instead */
|
|
1952
1927
|
declare const RCAN_VERSION = "1.6";
|
|
1953
1928
|
|
|
1954
|
-
export { AUTHORITY_ERROR_CODES, type ApprovalStatus, AuditChain, AuditError, type AuditExportRequest, type AuthorityAccessPayload, type AuthorityAccessPayloadWire, type AuthorityDataCategory, type AuthorityResponseData, type AuthorityResponsePayload, COMPETITION_SCOPE_LEVEL, CONTRIBUTE_SCOPE_LEVEL, type CachedKey, type ChainVerifyResult, ClockDriftError, type ClockSyncStatus, CommitmentRecord, type CommitmentRecordData, type CommitmentRecordJSON, type CompetitionBadge, type CompetitionEnter, type CompetitionFormat, type CompetitionScore, type ComputeResource, ConfidenceGate, type ConsentRequestParams, type ConsentResponseParams, type ConsentType, type ContributeCancel, type ContributeRequest, type ContributeResult, DEFAULT_LOA_POLICY, DataCategory, type DelegationHop, FIRMWARE_MANIFEST_PATH, FaultCode, type FaultReportParams, type FaultSeverity, type FederationSyncPayload, FederationSyncType, type FirmwareComponent, FirmwareIntegrityError, type FirmwareManifest, type FirmwareManifestWire, GateError, HiTLGate, type IdentityRecord, type JWKEntry, type JWKSDocument, KeyStore, LevelOfAssurance, type ListResult, type LoaPolicy, M2MAuthError, type M2MPeerClaims, type M2MTrustedClaims, M2M_TRUSTED_ISSUER, MLDSAKeyPair, type MLDSAKeyPairData, type
|
|
1929
|
+
export { AUTHORITY_ERROR_CODES, type ApprovalStatus, AuditChain, AuditError, type AuditExportRequest, type AuthorityAccessPayload, type AuthorityAccessPayloadWire, type AuthorityDataCategory, type AuthorityResponseData, type AuthorityResponsePayload, COMPETITION_SCOPE_LEVEL, CONTRIBUTE_SCOPE_LEVEL, type CachedKey, type ChainVerifyResult, ClockDriftError, type ClockSyncStatus, CommitmentRecord, type CommitmentRecordData, type CommitmentRecordJSON, type CompetitionBadge, type CompetitionEnter, type CompetitionFormat, type CompetitionScore, type ComputeResource, ConfidenceGate, type ConsentRequestParams, type ConsentResponseParams, type ConsentType, type ContributeCancel, type ContributeRequest, type ContributeResult, DEFAULT_LOA_POLICY, DataCategory, type DelegationHop, FIRMWARE_MANIFEST_PATH, FaultCode, type FaultReportParams, type FaultSeverity, type FederationSyncPayload, FederationSyncType, type FirmwareComponent, FirmwareIntegrityError, type FirmwareManifest, type FirmwareManifestWire, GateError, HiTLGate, type IdentityRecord, type JWKEntry, type JWKSDocument, KeyStore, LevelOfAssurance, type ListResult, type LoaPolicy, M2MAuthError, type M2MPeerClaims, type M2MTrustedClaims, M2M_TRUSTED_ISSUER, MLDSAKeyPair, type MLDSAKeyPairData, type MediaChunk, MediaEncoding, MessageType, NodeClient, type OfflineCommandResult, OfflineModeManager, type OfflineState, PRODUCTION_LOA_POLICY, type PendingApproval, type PersonalResearchResult, QoSAckTimeoutError, QoSLevel, QoSManager, type QoSResult, type QoSSendOptions, RCANAddressError, type RCANAgentConfig, type RCANConfig, RCANConfigAuthorizationError, RCANDelegationChainError, RCANError, RCANGateError, RCANMessage, type RCANMessageData, type RCANMessageEnvelope, RCANMessageError, type RCANMetadata, RCANNodeError, RCANNodeNotFoundError, RCANNodeSyncError, RCANNodeTrustError, RCANRegistryError, type RCANRegistryNode, RCANReplayAttackError, type RCANResolveResult, RCANSignatureError, RCANValidationError, RCANVersionIncompatibleError, RCAN_VERSION, ROLE_JWT_LEVEL, RRF_REVOCATION_CACHE_TTL_MS, RRF_REVOCATION_URL, type RegistrationResult, RegistryClient, type RegistryIdentity, RegistryTier, ReplayCache, type ReplayCheckResult, type ReplayableMessage, type ResearchMetrics, RevocationCache$1 as RevocationCache, type RevocationStatus, type RevocationStatusValue, type Robot, type RobotRegistration, RobotURI, RobotURIError, type RobotURIOptions, Role, type RunType, SAFETY_MESSAGE_TYPE, SCOPE_MIN_ROLE, SDK_VERSION, SPEC_VERSION, type SafetyEvent, type SafetyMessage, type ScopeValidationResult, type SeasonStanding, type SenderType, type SignatureBlock, type StandingEntry, type StreamChunk, type TrainingConsentRequestParams, type TransparencyMessage, TransportEncoding, TransportError, TrustAnchorCache, VERSION, type ValidationResult, type WorkUnitStatus, addDelegationHop, addMediaInline, addMediaRef, addPQSignature, assertClockSynced, authorityAccessFromWire, authorityAccessToWire, canonicalManifestJson, checkClockSync, checkRevocation, decodeBleFrames, decodeCompact, decodeMinimal, encodeBleFrames, encodeCompact, encodeMinimal, extractIdentityFromJwt, extractLoaFromJwt, extractRoleFromJwt, fetchCanonicalSchema, fetchRRFRevocations, isAuthorityRequestValid, isM2mTrustedRevoked, isPreemptedBy, isSafetyMessage, makeCloudRelayMessage, makeCompetitionEnter, makeCompetitionScore, makeConfigUpdate, makeConsentDeny, makeConsentGrant, makeConsentRequest, makeContributeCancel, makeContributeRequest, makeContributeResult, makeEstopMessage, makeEstopWithQoS, makeFaultReport, makeFederationSync, makeKeyRotationMessage, makePersonalResearchResult, makeResumeMessage, makeRevocationBroadcast, makeSeasonStanding, makeStopMessage, makeStreamChunk, makeTrainingConsentDeny, makeTrainingConsentGrant, makeTrainingConsentRequest, makeTrainingDataMessage, makeTransparencyMessage, manifestFromWire, manifestToWire, parseM2mPeerToken, parseM2mTrustedToken, roleFromJwtLevel, selectTransport, signMessage, validateAuthorityAccess, validateCompetitionScope, validateConfig, validateConfigAgainstSchema, validateConfigUpdate, validateConsentMessage, validateContributeScope, validateCrossRegistryCommand, validateDelegationChain, validateLoaForScope, validateManifest, validateMediaChunks, validateMessage, validateNodeAgainstSchema, validateReplay, validateRoleForScope, validateSafetyMessage, validateTrainingDataMessage, validateURI, validateVersionCompat, verifyM2mTrustedToken, verifyM2mTrustedTokenClaims, verifyMessage, verifyPQSignature };
|
package/dist/browser.mjs
CHANGED
|
@@ -100,7 +100,7 @@ var RobotURI = class _RobotURI {
|
|
|
100
100
|
|
|
101
101
|
// src/version.ts
|
|
102
102
|
var SPEC_VERSION = "2.2.0";
|
|
103
|
-
var SDK_VERSION = "1.2.
|
|
103
|
+
var SDK_VERSION = "1.2.1";
|
|
104
104
|
function validateVersionCompat(incomingVersion, localVersion = SPEC_VERSION) {
|
|
105
105
|
const parseParts = (v) => {
|
|
106
106
|
const parts = v.split(".");
|
|
@@ -279,7 +279,6 @@ var RCANMessage = class _RCANMessage {
|
|
|
279
279
|
if (this.mediaChunks !== void 0) obj.mediaChunks = this.mediaChunks;
|
|
280
280
|
if (this.firmwareHash !== void 0) obj.firmwareHash = this.firmwareHash;
|
|
281
281
|
if (this.attestationRef !== void 0) obj.attestationRef = this.attestationRef;
|
|
282
|
-
if (this.pqSig !== void 0) obj.pqSig = this.pqSig;
|
|
283
282
|
return obj;
|
|
284
283
|
}
|
|
285
284
|
/** Serialize to JSON string */
|
|
@@ -3114,21 +3113,15 @@ function fromBase64url(b64) {
|
|
|
3114
3113
|
return bytes;
|
|
3115
3114
|
}
|
|
3116
3115
|
async function sha256hex(data) {
|
|
3117
|
-
|
|
3118
|
-
|
|
3119
|
-
const subtle = webcrypto?.subtle;
|
|
3120
|
-
if (subtle) {
|
|
3121
|
-
const buf = await subtle.digest("SHA-256", data);
|
|
3116
|
+
if (typeof crypto !== "undefined" && crypto.subtle) {
|
|
3117
|
+
const buf = await crypto.subtle.digest("SHA-256", data.buffer);
|
|
3122
3118
|
return Array.from(new Uint8Array(buf)).map((b) => b.toString(16).padStart(2, "0")).join("").slice(0, 8);
|
|
3123
3119
|
}
|
|
3124
|
-
const
|
|
3125
|
-
|
|
3126
|
-
return nodeCrypto.createHash("sha256").update(data).digest("hex").slice(0, 8);
|
|
3127
|
-
}
|
|
3128
|
-
throw new Error("No SHA-256 implementation available");
|
|
3120
|
+
const { createHash } = __require("crypto");
|
|
3121
|
+
return createHash("sha256").update(data).digest("hex").slice(0, 8);
|
|
3129
3122
|
}
|
|
3130
3123
|
var _mlDsaModule;
|
|
3131
|
-
async function
|
|
3124
|
+
async function requireMlDsa() {
|
|
3132
3125
|
if (_mlDsaModule) return _mlDsaModule;
|
|
3133
3126
|
if (typeof __require !== "undefined") {
|
|
3134
3127
|
try {
|
|
@@ -3142,7 +3135,7 @@ async function requireNoblePostQuantum() {
|
|
|
3142
3135
|
return _mlDsaModule;
|
|
3143
3136
|
} catch {
|
|
3144
3137
|
throw new Error(
|
|
3145
|
-
"ML-DSA signing requires @noble/post-quantum. Install with: npm install @noble/post-quantum"
|
|
3138
|
+
"ML-DSA-65 signing requires @noble/post-quantum. Install with: npm install @noble/post-quantum"
|
|
3146
3139
|
);
|
|
3147
3140
|
}
|
|
3148
3141
|
}
|
|
@@ -3155,23 +3148,16 @@ var MLDSAKeyPair = class _MLDSAKeyPair {
|
|
|
3155
3148
|
this.publicKey = data.publicKey;
|
|
3156
3149
|
this.secretKey = data.secretKey;
|
|
3157
3150
|
}
|
|
3158
|
-
/** Generate a new ML-DSA-65 key pair. */
|
|
3159
3151
|
static async generate() {
|
|
3160
|
-
const
|
|
3161
|
-
const kp = ml_dsa65.keygen();
|
|
3152
|
+
const m = await requireMlDsa();
|
|
3153
|
+
const kp = m.ml_dsa65.keygen();
|
|
3162
3154
|
const keyId = await sha256hex(kp.publicKey);
|
|
3163
|
-
return new _MLDSAKeyPair({
|
|
3164
|
-
publicKey: kp.publicKey,
|
|
3165
|
-
secretKey: kp.secretKey,
|
|
3166
|
-
keyId
|
|
3167
|
-
});
|
|
3155
|
+
return new _MLDSAKeyPair({ publicKey: kp.publicKey, secretKey: kp.secretKey, keyId });
|
|
3168
3156
|
}
|
|
3169
|
-
/** Build a verify-only key pair from raw public key bytes. */
|
|
3170
3157
|
static async fromPublicKey(publicKey) {
|
|
3171
3158
|
const keyId = await sha256hex(publicKey);
|
|
3172
3159
|
return new _MLDSAKeyPair({ publicKey, keyId });
|
|
3173
3160
|
}
|
|
3174
|
-
/** Build a full key pair from saved bytes (public + secret). */
|
|
3175
3161
|
static async fromKeyMaterial(publicKey, secretKey) {
|
|
3176
3162
|
const keyId = await sha256hex(publicKey);
|
|
3177
3163
|
return new _MLDSAKeyPair({ publicKey, secretKey, keyId });
|
|
@@ -3179,82 +3165,68 @@ var MLDSAKeyPair = class _MLDSAKeyPair {
|
|
|
3179
3165
|
get hasPrivateKey() {
|
|
3180
3166
|
return this.secretKey !== void 0;
|
|
3181
3167
|
}
|
|
3182
|
-
/** Sign raw bytes; returns ML-DSA-65 signature (3309 bytes). */
|
|
3183
3168
|
async signBytes(data) {
|
|
3184
|
-
if (!this.secretKey)
|
|
3185
|
-
|
|
3186
|
-
|
|
3187
|
-
const { ml_dsa65 } = await requireNoblePostQuantum();
|
|
3188
|
-
return ml_dsa65.sign(data, this.secretKey);
|
|
3169
|
+
if (!this.secretKey) throw new Error("Cannot sign: MLDSAKeyPair has no private key (verify-only)");
|
|
3170
|
+
const m = await requireMlDsa();
|
|
3171
|
+
return m.ml_dsa65.sign(data, this.secretKey);
|
|
3189
3172
|
}
|
|
3190
|
-
/**
|
|
3191
|
-
* Verify an ML-DSA-65 signature.
|
|
3192
|
-
* @returns true if valid
|
|
3193
|
-
* @throws {Error} on invalid signature
|
|
3194
|
-
*/
|
|
3195
3173
|
async verifyBytes(data, signature) {
|
|
3196
|
-
const
|
|
3197
|
-
const ok = ml_dsa65.verify(signature, data, this.publicKey);
|
|
3198
|
-
if (!ok) throw new Error("ML-DSA signature verification failed");
|
|
3174
|
+
const m = await requireMlDsa();
|
|
3175
|
+
const ok = m.ml_dsa65.verify(signature, data, this.publicKey);
|
|
3176
|
+
if (!ok) throw new Error("ML-DSA-65 signature verification failed");
|
|
3199
3177
|
}
|
|
3200
3178
|
toString() {
|
|
3201
|
-
|
|
3202
|
-
return `MLDSAKeyPair(keyId=${this.keyId}, alg=ML-DSA-65, ${mode})`;
|
|
3179
|
+
return `MLDSAKeyPair(keyId=${this.keyId}, alg=ML-DSA-65, ${this.hasPrivateKey ? "private+public" : "public-only"})`;
|
|
3203
3180
|
}
|
|
3204
3181
|
};
|
|
3205
3182
|
function canonicalMessageBytes(msg) {
|
|
3206
|
-
const m = msg;
|
|
3207
3183
|
const payload = {
|
|
3208
3184
|
rcan: msg.rcan,
|
|
3209
|
-
msg_id:
|
|
3185
|
+
msg_id: msg["msgId"] ?? "",
|
|
3210
3186
|
timestamp: msg.timestamp,
|
|
3211
3187
|
cmd: msg.cmd,
|
|
3212
3188
|
target: msg.target,
|
|
3213
3189
|
params: msg.params
|
|
3214
3190
|
};
|
|
3215
|
-
|
|
3216
|
-
Object.fromEntries(Object.entries(payload).sort())
|
|
3217
|
-
null,
|
|
3218
|
-
void 0
|
|
3191
|
+
return new TextEncoder().encode(
|
|
3192
|
+
JSON.stringify(Object.fromEntries(Object.entries(payload).sort()))
|
|
3219
3193
|
);
|
|
3220
|
-
return new TextEncoder().encode(sorted);
|
|
3221
3194
|
}
|
|
3222
|
-
async function
|
|
3195
|
+
async function signMessage(msg, keypair) {
|
|
3223
3196
|
const payload = canonicalMessageBytes(msg);
|
|
3224
3197
|
const rawSig = await keypair.signBytes(payload);
|
|
3225
|
-
|
|
3198
|
+
msg["signature"] = {
|
|
3226
3199
|
alg: "ml-dsa-65",
|
|
3227
3200
|
kid: keypair.keyId,
|
|
3228
3201
|
sig: toBase64url(rawSig)
|
|
3229
3202
|
};
|
|
3230
|
-
msg["pqSig"] = block;
|
|
3231
3203
|
return msg;
|
|
3232
3204
|
}
|
|
3233
|
-
async function
|
|
3234
|
-
const
|
|
3235
|
-
if (!
|
|
3236
|
-
|
|
3237
|
-
|
|
3238
|
-
|
|
3239
|
-
|
|
3240
|
-
}
|
|
3241
|
-
if (pqSig.alg !== "ml-dsa-65") {
|
|
3242
|
-
throw new Error(`Unsupported PQ signature algorithm: ${pqSig.alg}`);
|
|
3205
|
+
async function verifyMessage(msg, trustedKeys) {
|
|
3206
|
+
const sig = msg.signature;
|
|
3207
|
+
if (!sig) throw new Error("Message is unsigned \u2014 signature field missing");
|
|
3208
|
+
if (sig.alg !== "ml-dsa-65") {
|
|
3209
|
+
throw new Error(
|
|
3210
|
+
`Unsupported signature algorithm: ${sig.alg}. RCAN v2.2 requires ml-dsa-65 (Ed25519 is deprecated).`
|
|
3211
|
+
);
|
|
3243
3212
|
}
|
|
3244
|
-
const matched = trustedKeys.find((k) => k.keyId ===
|
|
3213
|
+
const matched = trustedKeys.find((k) => k.keyId === sig.kid);
|
|
3245
3214
|
if (!matched) {
|
|
3246
3215
|
throw new Error(
|
|
3247
|
-
`No trusted ML-DSA key with kid=${
|
|
3216
|
+
`No trusted ML-DSA-65 key with kid=${sig.kid}. Known kids: [${trustedKeys.map((k) => k.keyId).join(", ")}]`
|
|
3248
3217
|
);
|
|
3249
3218
|
}
|
|
3250
3219
|
let rawSig;
|
|
3251
3220
|
try {
|
|
3252
|
-
rawSig = fromBase64url(
|
|
3221
|
+
rawSig = fromBase64url(sig.sig);
|
|
3253
3222
|
} catch (e) {
|
|
3254
|
-
throw new Error(`Invalid base64url
|
|
3223
|
+
throw new Error(`Invalid base64url sig: ${e}`);
|
|
3255
3224
|
}
|
|
3256
|
-
|
|
3257
|
-
|
|
3225
|
+
await matched.verifyBytes(canonicalMessageBytes(msg), rawSig);
|
|
3226
|
+
}
|
|
3227
|
+
var addPQSignature = signMessage;
|
|
3228
|
+
async function verifyPQSignature(msg, trustedKeys, _requirePQ = true) {
|
|
3229
|
+
return verifyMessage(msg, trustedKeys);
|
|
3258
3230
|
}
|
|
3259
3231
|
|
|
3260
3232
|
// src/index.ts
|
|
@@ -3382,6 +3354,7 @@ export {
|
|
|
3382
3354
|
parseM2mTrustedToken,
|
|
3383
3355
|
roleFromJwtLevel,
|
|
3384
3356
|
selectTransport,
|
|
3357
|
+
signMessage,
|
|
3385
3358
|
validateAuthorityAccess,
|
|
3386
3359
|
validateCompetitionScope,
|
|
3387
3360
|
validateConfig,
|
|
@@ -3404,6 +3377,7 @@ export {
|
|
|
3404
3377
|
validateVersionCompat,
|
|
3405
3378
|
verifyM2mTrustedToken,
|
|
3406
3379
|
verifyM2mTrustedTokenClaims,
|
|
3380
|
+
verifyMessage,
|
|
3407
3381
|
verifyPQSignature
|
|
3408
3382
|
};
|
|
3409
3383
|
//# sourceMappingURL=browser.mjs.map
|