@dfinity/agent
Advanced tools
Comparing version 0.19.2 to 0.19.3
@@ -123,2 +123,4 @@ "use strict"; | ||
constructor(config) { | ||
if (!config.canisterId) | ||
throw new errors_1.AgentError(`Canister ID is required, but recieved ${typeof config.canisterId} instead. If you are using automatically generated declarations, this may be because your application is not setting the canister ID in process.env correctly.`); | ||
const canisterId = typeof config.canisterId === 'string' | ||
@@ -142,2 +144,5 @@ ? principal_1.Principal.fromText(config.canisterId) | ||
static createActor(interfaceFactory, configuration) { | ||
if (!configuration.canisterId) { | ||
throw new errors_1.AgentError(`Canister ID is required, but recieved ${typeof configuration.canisterId} instead. If you are using automatically generated declarations, this may be because your application is not setting the canister ID in process.env correctly.`); | ||
} | ||
return new (this.createActorClass(interfaceFactory))(configuration); | ||
@@ -144,0 +149,0 @@ } |
@@ -28,3 +28,2 @@ "use strict"; | ||
exports.encodePath = exports.request = void 0; | ||
const candid_1 = require("@dfinity/candid"); | ||
const principal_1 = require("@dfinity/principal"); | ||
@@ -35,2 +34,3 @@ const errors_1 = require("../errors"); | ||
const Cbor = __importStar(require("../cbor")); | ||
const leb_1 = require("../utils/leb"); | ||
/** | ||
@@ -85,3 +85,3 @@ * | ||
case 'time': { | ||
status.set(path, decodeTime(data)); | ||
status.set(path, (0, leb_1.decodeTime)(data)); | ||
break; | ||
@@ -109,3 +109,3 @@ } | ||
case 'leb128': { | ||
status.set(path.key, decodeLeb128(data)); | ||
status.set(path.key, (0, leb_1.decodeLeb128)(data)); | ||
break; | ||
@@ -192,5 +192,2 @@ } | ||
}; | ||
const decodeLeb128 = (buf) => { | ||
return (0, candid_1.lebDecode)(new candid_1.PipeArrayBuffer(buf)); | ||
}; | ||
const decodeCbor = (buf) => { | ||
@@ -202,7 +199,2 @@ return Cbor.decode(buf); | ||
}; | ||
// time is a LEB128-encoded Nat | ||
const decodeTime = (buf) => { | ||
const decoded = decodeLeb128(buf); | ||
return new Date(Number(decoded / BigInt(1000000))); | ||
}; | ||
// Controllers are CBOR-encoded buffers, starting with a Tag we don't need | ||
@@ -209,0 +201,0 @@ const decodeControllers = (buf) => { |
@@ -42,2 +42,9 @@ import { AgentError } from './errors'; | ||
blsVerify?: VerifyFunc; | ||
/** | ||
* The maximum age of the certificate in minutes. Default is 5 minutes. | ||
* @default 5 | ||
* This is used to verify the time the certificate was signed, particularly for validating Delegation certificates, which can live for longer than the default window of +/- 5 minutes. If the certificate is | ||
* older than the specified age, it will fail verification. | ||
*/ | ||
maxAgeInMinutes?: number; | ||
} | ||
@@ -48,2 +55,3 @@ export declare class Certificate { | ||
private _blsVerify; | ||
private _maxAgeInMinutes; | ||
private readonly cert; | ||
@@ -53,8 +61,8 @@ /** | ||
* CertificateVerificationError if the certificate cannot be verified. | ||
* @constructs {@link AuthClient} | ||
* @param {CreateCertificateOptions} options | ||
* @see {@link CreateCertificateOptions} | ||
* @constructs Certificate | ||
* @param {CreateCertificateOptions} options {@link CreateCertificateOptions} | ||
* @param {ArrayBuffer} options.certificate The bytes of the certificate | ||
* @param {ArrayBuffer} options.rootKey The root key to verify against | ||
* @param {Principal} options.canisterId The effective or signing canister ID | ||
* @param {number} options.maxAgeInMinutes The maximum age of the certificate in minutes. Default is 5 minutes. | ||
* @throws {CertificateVerificationError} | ||
@@ -61,0 +69,0 @@ */ |
@@ -33,2 +33,3 @@ "use strict"; | ||
const bls = __importStar(require("./utils/bls")); | ||
const leb_1 = require("./utils/leb"); | ||
/** | ||
@@ -100,6 +101,9 @@ * A certificate may fail verification with respect to the provided public key | ||
class Certificate { | ||
constructor(certificate, _rootKey, _canisterId, _blsVerify) { | ||
constructor(certificate, _rootKey, _canisterId, _blsVerify, | ||
// Default to 5 minutes | ||
_maxAgeInMinutes = 5) { | ||
this._rootKey = _rootKey; | ||
this._canisterId = _canisterId; | ||
this._blsVerify = _blsVerify; | ||
this._maxAgeInMinutes = _maxAgeInMinutes; | ||
this.cert = cbor.decode(new Uint8Array(certificate)); | ||
@@ -110,8 +114,8 @@ } | ||
* CertificateVerificationError if the certificate cannot be verified. | ||
* @constructs {@link AuthClient} | ||
* @param {CreateCertificateOptions} options | ||
* @see {@link CreateCertificateOptions} | ||
* @constructs Certificate | ||
* @param {CreateCertificateOptions} options {@link CreateCertificateOptions} | ||
* @param {ArrayBuffer} options.certificate The bytes of the certificate | ||
* @param {ArrayBuffer} options.rootKey The root key to verify against | ||
* @param {Principal} options.canisterId The effective or signing canister ID | ||
* @param {number} options.maxAgeInMinutes The maximum age of the certificate in minutes. Default is 5 minutes. | ||
* @throws {CertificateVerificationError} | ||
@@ -124,3 +128,3 @@ */ | ||
} | ||
const cert = new Certificate(options.certificate, options.rootKey, options.canisterId, blsVerify); | ||
const cert = new Certificate(options.certificate, options.rootKey, options.canisterId, blsVerify, options.maxAgeInMinutes); | ||
await cert.verify(); | ||
@@ -139,2 +143,25 @@ return cert; | ||
let sigVer = false; | ||
const lookupTime = this.lookup(['time']); | ||
if (!lookupTime) { | ||
// Should never happen - time is always present in IC certificates | ||
throw new CertificateVerificationError('Certificate does not contain a time'); | ||
} | ||
const FIVE_MINUTES_IN_MSEC = 5 * 60 * 1000; | ||
const MAX_AGE_IN_MSEC = this._maxAgeInMinutes * 60 * 1000; | ||
const now = Date.now(); | ||
const earliestCertificateTime = now - MAX_AGE_IN_MSEC; | ||
const fiveMinutesFromNow = now + FIVE_MINUTES_IN_MSEC; | ||
const certTime = (0, leb_1.decodeTime)(lookupTime); | ||
if (certTime.getTime() < earliestCertificateTime) { | ||
throw new CertificateVerificationError(`Certificate is signed more than ${this._maxAgeInMinutes} minutes in the past. Certificate time: ` + | ||
certTime.toISOString() + | ||
' Current time: ' + | ||
new Date(now).toISOString()); | ||
} | ||
else if (certTime.getTime() > fiveMinutesFromNow) { | ||
throw new CertificateVerificationError('Certificate is signed more than 5 minutes in the future. Certificate time: ' + | ||
certTime.toISOString() + | ||
' Current time: ' + | ||
new Date(now).toISOString()); | ||
} | ||
try { | ||
@@ -158,2 +185,5 @@ sigVer = await this._blsVerify(new Uint8Array(key), new Uint8Array(sig), new Uint8Array(msg)); | ||
canisterId: this._canisterId, | ||
blsVerify: this._blsVerify, | ||
// Maximum age of 30 days for delegation certificates | ||
maxAgeInMinutes: 60 * 24 * 30, | ||
}); | ||
@@ -160,0 +190,0 @@ const rangeLookup = cert.lookup(['subnet', d.subnet_id, 'canister_ranges']); |
@@ -114,2 +114,4 @@ import { Buffer } from 'buffer/'; | ||
constructor(config) { | ||
if (!config.canisterId) | ||
throw new AgentError(`Canister ID is required, but recieved ${typeof config.canisterId} instead. If you are using automatically generated declarations, this may be because your application is not setting the canister ID in process.env correctly.`); | ||
const canisterId = typeof config.canisterId === 'string' | ||
@@ -133,2 +135,5 @@ ? Principal.fromText(config.canisterId) | ||
static createActor(interfaceFactory, configuration) { | ||
if (!configuration.canisterId) { | ||
throw new AgentError(`Canister ID is required, but recieved ${typeof configuration.canisterId} instead. If you are using automatically generated declarations, this may be because your application is not setting the canister ID in process.env correctly.`); | ||
} | ||
return new (this.createActorClass(interfaceFactory))(configuration); | ||
@@ -135,0 +140,0 @@ } |
/** @module CanisterStatus */ | ||
import { lebDecode, PipeArrayBuffer } from '@dfinity/candid'; | ||
import { Principal } from '@dfinity/principal'; | ||
@@ -8,2 +7,3 @@ import { AgentError } from '../errors'; | ||
import * as Cbor from '../cbor'; | ||
import { decodeLeb128, decodeTime } from '../utils/leb'; | ||
/** | ||
@@ -161,5 +161,2 @@ * | ||
}; | ||
const decodeLeb128 = (buf) => { | ||
return lebDecode(new PipeArrayBuffer(buf)); | ||
}; | ||
const decodeCbor = (buf) => { | ||
@@ -171,7 +168,2 @@ return Cbor.decode(buf); | ||
}; | ||
// time is a LEB128-encoded Nat | ||
const decodeTime = (buf) => { | ||
const decoded = decodeLeb128(buf); | ||
return new Date(Number(decoded / BigInt(1000000))); | ||
}; | ||
// Controllers are CBOR-encoded buffers, starting with a Tag we don't need | ||
@@ -178,0 +170,0 @@ const decodeControllers = (buf) => { |
@@ -42,2 +42,9 @@ import { AgentError } from './errors'; | ||
blsVerify?: VerifyFunc; | ||
/** | ||
* The maximum age of the certificate in minutes. Default is 5 minutes. | ||
* @default 5 | ||
* This is used to verify the time the certificate was signed, particularly for validating Delegation certificates, which can live for longer than the default window of +/- 5 minutes. If the certificate is | ||
* older than the specified age, it will fail verification. | ||
*/ | ||
maxAgeInMinutes?: number; | ||
} | ||
@@ -48,2 +55,3 @@ export declare class Certificate { | ||
private _blsVerify; | ||
private _maxAgeInMinutes; | ||
private readonly cert; | ||
@@ -53,8 +61,8 @@ /** | ||
* CertificateVerificationError if the certificate cannot be verified. | ||
* @constructs {@link AuthClient} | ||
* @param {CreateCertificateOptions} options | ||
* @see {@link CreateCertificateOptions} | ||
* @constructs Certificate | ||
* @param {CreateCertificateOptions} options {@link CreateCertificateOptions} | ||
* @param {ArrayBuffer} options.certificate The bytes of the certificate | ||
* @param {ArrayBuffer} options.rootKey The root key to verify against | ||
* @param {Principal} options.canisterId The effective or signing canister ID | ||
* @param {number} options.maxAgeInMinutes The maximum age of the certificate in minutes. Default is 5 minutes. | ||
* @throws {CertificateVerificationError} | ||
@@ -61,0 +69,0 @@ */ |
@@ -7,2 +7,3 @@ import * as cbor from './cbor'; | ||
import * as bls from './utils/bls'; | ||
import { decodeTime } from './utils/leb'; | ||
/** | ||
@@ -72,6 +73,9 @@ * A certificate may fail verification with respect to the provided public key | ||
export class Certificate { | ||
constructor(certificate, _rootKey, _canisterId, _blsVerify) { | ||
constructor(certificate, _rootKey, _canisterId, _blsVerify, | ||
// Default to 5 minutes | ||
_maxAgeInMinutes = 5) { | ||
this._rootKey = _rootKey; | ||
this._canisterId = _canisterId; | ||
this._blsVerify = _blsVerify; | ||
this._maxAgeInMinutes = _maxAgeInMinutes; | ||
this.cert = cbor.decode(new Uint8Array(certificate)); | ||
@@ -82,8 +86,8 @@ } | ||
* CertificateVerificationError if the certificate cannot be verified. | ||
* @constructs {@link AuthClient} | ||
* @param {CreateCertificateOptions} options | ||
* @see {@link CreateCertificateOptions} | ||
* @constructs Certificate | ||
* @param {CreateCertificateOptions} options {@link CreateCertificateOptions} | ||
* @param {ArrayBuffer} options.certificate The bytes of the certificate | ||
* @param {ArrayBuffer} options.rootKey The root key to verify against | ||
* @param {Principal} options.canisterId The effective or signing canister ID | ||
* @param {number} options.maxAgeInMinutes The maximum age of the certificate in minutes. Default is 5 minutes. | ||
* @throws {CertificateVerificationError} | ||
@@ -96,3 +100,3 @@ */ | ||
} | ||
const cert = new Certificate(options.certificate, options.rootKey, options.canisterId, blsVerify); | ||
const cert = new Certificate(options.certificate, options.rootKey, options.canisterId, blsVerify, options.maxAgeInMinutes); | ||
await cert.verify(); | ||
@@ -111,2 +115,25 @@ return cert; | ||
let sigVer = false; | ||
const lookupTime = this.lookup(['time']); | ||
if (!lookupTime) { | ||
// Should never happen - time is always present in IC certificates | ||
throw new CertificateVerificationError('Certificate does not contain a time'); | ||
} | ||
const FIVE_MINUTES_IN_MSEC = 5 * 60 * 1000; | ||
const MAX_AGE_IN_MSEC = this._maxAgeInMinutes * 60 * 1000; | ||
const now = Date.now(); | ||
const earliestCertificateTime = now - MAX_AGE_IN_MSEC; | ||
const fiveMinutesFromNow = now + FIVE_MINUTES_IN_MSEC; | ||
const certTime = decodeTime(lookupTime); | ||
if (certTime.getTime() < earliestCertificateTime) { | ||
throw new CertificateVerificationError(`Certificate is signed more than ${this._maxAgeInMinutes} minutes in the past. Certificate time: ` + | ||
certTime.toISOString() + | ||
' Current time: ' + | ||
new Date(now).toISOString()); | ||
} | ||
else if (certTime.getTime() > fiveMinutesFromNow) { | ||
throw new CertificateVerificationError('Certificate is signed more than 5 minutes in the future. Certificate time: ' + | ||
certTime.toISOString() + | ||
' Current time: ' + | ||
new Date(now).toISOString()); | ||
} | ||
try { | ||
@@ -130,2 +157,5 @@ sigVer = await this._blsVerify(new Uint8Array(key), new Uint8Array(sig), new Uint8Array(msg)); | ||
canisterId: this._canisterId, | ||
blsVerify: this._blsVerify, | ||
// Maximum age of 30 days for delegation certificates | ||
maxAgeInMinutes: 60 * 24 * 30, | ||
}); | ||
@@ -132,0 +162,0 @@ const rangeLookup = cert.lookup(['subnet', d.subnet_id, 'canister_ranges']); |
{ | ||
"name": "@dfinity/agent", | ||
"version": "0.19.2", | ||
"version": "0.19.3", | ||
"author": "DFINITY Stiftung <sdk@dfinity.org>", | ||
@@ -53,4 +53,4 @@ "license": "Apache-2.0", | ||
"peerDependencies": { | ||
"@dfinity/candid": "^0.19.2", | ||
"@dfinity/principal": "^0.19.2" | ||
"@dfinity/candid": "^0.19.3", | ||
"@dfinity/principal": "^0.19.3" | ||
}, | ||
@@ -64,2 +64,3 @@ "dependencies": { | ||
"devDependencies": { | ||
"@dfinity/utils": "^0.0.22", | ||
"@peculiar/webcrypto": "^1.4.3", | ||
@@ -66,0 +67,0 @@ "@trust/webcrypto": "^0.9.2", |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
1097370
172
8117
19