@microsoft/ccf-app 3.0.0-dev6 → 3.0.0-rc1

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/consensus.d.ts CHANGED
@@ -1,13 +1,13 @@
1
1
  /**
2
- * @inheritDoc CCFConsensus.getLastCommittedTxId;
2
+ * @inheritDoc global!CCFConsensus.getLastCommittedTxId
3
3
  */
4
4
  export declare const getLastCommittedTxId: () => import("./global.js").TransactionId;
5
5
  /**
6
- * @inheritDoc CCFConsensus.getStatusForTxId;
6
+ * @inheritDoc global!CCFConsensus.getStatusForTxId
7
7
  */
8
8
  export declare const getStatusForTxId: (view: number, seqno: number) => import("./global.js").TransactionStatus;
9
9
  /**
10
- * @inheritDoc CCFConsensus.getViewForSeqno;
10
+ * @inheritDoc global!CCFConsensus.getViewForSeqno
11
11
  */
12
12
  export declare const getViewForSeqno: (seqno: number) => number | null;
13
13
  export { TransactionStatus } from "./global";
package/consensus.js CHANGED
@@ -8,14 +8,14 @@
8
8
  */
9
9
  import { ccf } from "./global.js";
10
10
  /**
11
- * @inheritDoc CCFConsensus.getLastCommittedTxId;
11
+ * @inheritDoc global!CCFConsensus.getLastCommittedTxId
12
12
  */
13
13
  export const getLastCommittedTxId = ccf.consensus.getLastCommittedTxId.bind(ccf.consensus);
14
14
  /**
15
- * @inheritDoc CCFConsensus.getStatusForTxId;
15
+ * @inheritDoc global!CCFConsensus.getStatusForTxId
16
16
  */
17
17
  export const getStatusForTxId = ccf.consensus.getStatusForTxId.bind(ccf.consensus);
18
18
  /**
19
- * @inheritDoc CCFConsensus.getViewForSeqno;
19
+ * @inheritDoc global!CCFConsensus.getViewForSeqno
20
20
  */
21
21
  export const getViewForSeqno = ccf.consensus.getViewForSeqno.bind(ccf.consensus);
package/crypto.d.ts CHANGED
@@ -1,33 +1,57 @@
1
1
  /**
2
- * @inheritDoc CCF.generateAesKey
2
+ * @inheritDoc global!CCF.generateAesKey
3
3
  */
4
4
  export declare const generateAesKey: (size: number) => ArrayBuffer;
5
5
  /**
6
- * @inheritDoc CCF.generateRsaKeyPair
6
+ * @inheritDoc global!CCF.generateRsaKeyPair
7
7
  */
8
8
  export declare const generateRsaKeyPair: (size: number, exponent?: number | undefined) => import("./global.js").CryptoKeyPair;
9
9
  /**
10
- * @inheritDoc CCF.generateEcdsaKeyPair
10
+ * @inheritDoc global!CCF.generateEcdsaKeyPair
11
11
  */
12
12
  export declare const generateEcdsaKeyPair: (curve: string) => import("./global.js").CryptoKeyPair;
13
13
  /**
14
- * @inheritDoc CCF.wrapKey
14
+ * @inheritDoc global!CCF.generateEcdsaKeyPair
15
+ */
16
+ export declare const generateEddsaKeyPair: (curve: string) => import("./global.js").CryptoKeyPair;
17
+ /**
18
+ * @inheritDoc global!CCF.wrapKey
15
19
  */
16
20
  export declare const wrapKey: (key: ArrayBuffer, wrappingKey: ArrayBuffer, wrapAlgo: import("./global.js").WrapAlgoParams) => ArrayBuffer;
17
21
  /**
18
- * @inheritDoc CCFCrypto.verifySignature
22
+ * @inheritDoc global!CCFCrypto.verifySignature
23
+ */
24
+ export declare const sign: (algorithm: import("./global.js").SigningAlgorithm, key: string, plaintext: ArrayBuffer) => ArrayBuffer;
25
+ /**
26
+ * @inheritDoc global!CCFCrypto.verifySignature
19
27
  */
20
- export declare const verifySignature: (algorithm: import("./global.js").SigningAlgorithm, key: string, signature: ArrayBuffer, data: ArrayBuffer) => boolean;
28
+ export declare const verifySignature: (algorithm: import("./global.js").SigningAlgorithm, key: string, signature: ArrayBuffer, plaintext: ArrayBuffer) => boolean;
21
29
  /**
22
- * @inheritDoc CCF.digest
30
+ * @inheritDoc global!CCFCrypto.digest
23
31
  */
24
- export declare const digest: (algorithm: "SHA-256", data: ArrayBuffer) => ArrayBuffer;
32
+ export declare const digest: (algorithm: "SHA-256", plaintext: ArrayBuffer) => ArrayBuffer;
25
33
  /**
26
- * @inheritDoc CCF.isValidX509CertBundle
34
+ * @inheritDoc global!CCFCrypto.isValidX509CertBundle
27
35
  */
28
36
  export declare const isValidX509CertBundle: (pem: string) => boolean;
29
37
  /**
30
- * @inheritDoc CCF.isValidX509CertChain
38
+ * @inheritDoc global!CCFCrypto.isValidX509CertChain
31
39
  */
32
40
  export declare const isValidX509CertChain: (chain: string, trusted: string) => boolean;
33
- export { WrapAlgoParams, AesKwpParams, RsaOaepParams, RsaOaepAesKwpParams, CryptoKeyPair, DigestAlgorithm, SigningAlgorithm, RsaPkcsParams, EcdsaParams, } from "./global";
41
+ /**
42
+ * @inheritDoc global!CCFCrypto.pubPemToJwk
43
+ */
44
+ export declare const pubPemToJwk: (pem: string, kid?: string | undefined) => import("./global.js").JsonWebKeyECPublic;
45
+ /**
46
+ * @inheritDoc global!CCFCrypto.pemToJwk
47
+ */
48
+ export declare const pemToJwk: (pem: string, kid?: string | undefined) => import("./global.js").JsonWebKeyECPrivate;
49
+ /**
50
+ * @inheritDoc global!CCFCrypto.pubRsaPemToJwk
51
+ */
52
+ export declare const pubRsaPemToJwk: (pem: string, kid?: string | undefined) => import("./global.js").JsonWebKeyRSAPublic;
53
+ /**
54
+ * @inheritDoc global!CCFCrypto.rsaPemToJwk
55
+ */
56
+ export declare const rsaPemToJwk: (pem: string, kid?: string | undefined) => import("./global.js").JsonWebKeyRSAPrivate;
57
+ export { WrapAlgoParams, AesKwpParams, RsaOaepParams, RsaOaepAesKwpParams, CryptoKeyPair, DigestAlgorithm, SigningAlgorithm, } from "./global";
package/crypto.js CHANGED
@@ -15,34 +15,58 @@
15
15
  */
16
16
  import { ccf } from "./global.js";
17
17
  /**
18
- * @inheritDoc CCF.generateAesKey
18
+ * @inheritDoc global!CCF.generateAesKey
19
19
  */
20
- export const generateAesKey = ccf.generateAesKey;
20
+ export const generateAesKey = ccf.crypto.generateAesKey;
21
21
  /**
22
- * @inheritDoc CCF.generateRsaKeyPair
22
+ * @inheritDoc global!CCF.generateRsaKeyPair
23
23
  */
24
- export const generateRsaKeyPair = ccf.generateRsaKeyPair;
24
+ export const generateRsaKeyPair = ccf.crypto.generateRsaKeyPair;
25
25
  /**
26
- * @inheritDoc CCF.generateEcdsaKeyPair
26
+ * @inheritDoc global!CCF.generateEcdsaKeyPair
27
27
  */
28
- export const generateEcdsaKeyPair = ccf.generateEcdsaKeyPair;
28
+ export const generateEcdsaKeyPair = ccf.crypto.generateEcdsaKeyPair;
29
29
  /**
30
- * @inheritDoc CCF.wrapKey
30
+ * @inheritDoc global!CCF.generateEcdsaKeyPair
31
31
  */
32
- export const wrapKey = ccf.wrapKey;
32
+ export const generateEddsaKeyPair = ccf.crypto.generateEddsaKeyPair;
33
33
  /**
34
- * @inheritDoc CCFCrypto.verifySignature
34
+ * @inheritDoc global!CCF.wrapKey
35
+ */
36
+ export const wrapKey = ccf.crypto.wrapKey;
37
+ /**
38
+ * @inheritDoc global!CCFCrypto.verifySignature
39
+ */
40
+ export const sign = ccf.crypto.sign;
41
+ /**
42
+ * @inheritDoc global!CCFCrypto.verifySignature
35
43
  */
36
44
  export const verifySignature = ccf.crypto.verifySignature;
37
45
  /**
38
- * @inheritDoc CCF.digest
46
+ * @inheritDoc global!CCFCrypto.digest
47
+ */
48
+ export const digest = ccf.crypto.digest;
49
+ /**
50
+ * @inheritDoc global!CCFCrypto.isValidX509CertBundle
51
+ */
52
+ export const isValidX509CertBundle = ccf.crypto.isValidX509CertBundle;
53
+ /**
54
+ * @inheritDoc global!CCFCrypto.isValidX509CertChain
55
+ */
56
+ export const isValidX509CertChain = ccf.crypto.isValidX509CertChain;
57
+ /**
58
+ * @inheritDoc global!CCFCrypto.pubPemToJwk
59
+ */
60
+ export const pubPemToJwk = ccf.crypto.pubPemToJwk;
61
+ /**
62
+ * @inheritDoc global!CCFCrypto.pemToJwk
39
63
  */
40
- export const digest = ccf.digest;
64
+ export const pemToJwk = ccf.crypto.pemToJwk;
41
65
  /**
42
- * @inheritDoc CCF.isValidX509CertBundle
66
+ * @inheritDoc global!CCFCrypto.pubRsaPemToJwk
43
67
  */
44
- export const isValidX509CertBundle = ccf.isValidX509CertBundle;
68
+ export const pubRsaPemToJwk = ccf.crypto.pubRsaPemToJwk;
45
69
  /**
46
- * @inheritDoc CCF.isValidX509CertChain
70
+ * @inheritDoc global!CCFCrypto.rsaPemToJwk
47
71
  */
48
- export const isValidX509CertChain = ccf.isValidX509CertChain;
72
+ export const rsaPemToJwk = ccf.crypto.rsaPemToJwk;
package/endpoints.d.ts CHANGED
@@ -221,11 +221,11 @@ export interface Response<T extends ResponseBodyType<T> = any> {
221
221
  */
222
222
  export declare type EndpointFn<A extends JsonCompatible<A> = any, B extends ResponseBodyType<B> = any> = (request: Request<A>) => Response<B>;
223
223
  /**
224
- * @inheritDoc CCF.rpc.setApplyWrites
224
+ * @inheritDoc global!CCFRpc.setApplyWrites
225
225
  */
226
226
  export declare const setApplyWrites: (force: boolean) => void;
227
227
  /**
228
- * @inheritDoc CCF.rpc.setClaimsDigest
228
+ * @inheritDoc global!CCFRpc.setClaimsDigest
229
229
  */
230
230
  export declare const setClaimsDigest: (digest: ArrayBuffer) => void;
231
231
  export {};
package/endpoints.js CHANGED
@@ -8,10 +8,10 @@
8
8
  */
9
9
  import { ccf } from "./global.js";
10
10
  /**
11
- * @inheritDoc CCF.rpc.setApplyWrites
11
+ * @inheritDoc global!CCFRpc.setApplyWrites
12
12
  */
13
13
  export const setApplyWrites = ccf.rpc.setApplyWrites.bind(ccf.rpc);
14
14
  /**
15
- * @inheritDoc CCF.rpc.setClaimsDigest
15
+ * @inheritDoc global!CCFRpc.setClaimsDigest
16
16
  */
17
17
  export const setClaimsDigest = ccf.rpc.setClaimsDigest.bind(ccf.rpc);
package/global.d.ts CHANGED
@@ -164,47 +164,179 @@ export interface RsaOaepAesKwpParams {
164
164
  export declare type WrapAlgoParams = RsaOaepParams | AesKwpParams | RsaOaepAesKwpParams;
165
165
  export interface CryptoKeyPair {
166
166
  /**
167
- * RSA private key in PEM encoding.
167
+ * Private key in PEM encoding.
168
168
  */
169
169
  privateKey: string;
170
170
  /**
171
- * RSA public key in PEM encoding.
171
+ * Public key in PEM encoding.
172
172
  */
173
173
  publicKey: string;
174
174
  }
175
- /**
176
- * RSASSA-PKCS1-v1_5 signature algorithm parameters.
177
- */
178
- export interface RsaPkcsParams {
179
- name: "RSASSA-PKCS1-v1_5";
180
- hash: DigestAlgorithm;
175
+ export declare type AlgorithmName = "RSASSA-PKCS1-v1_5" | "ECDSA" | "EdDSA";
176
+ export declare type DigestAlgorithm = "SHA-256";
177
+ export interface SigningAlgorithm {
178
+ name: AlgorithmName;
179
+ /**
180
+ * Digest algorithm. It's necessary for "RSASSA-PKCS1-v1_5" and "ECDSA"
181
+ */
182
+ hash?: DigestAlgorithm;
181
183
  }
182
184
  /**
183
- * ECDSA signature algorithm parameters.
184
- *
185
- * Note: ECDSA signatures are assumed to be encoded according
186
- * to the Web Crypto API specification, which is the same
187
- * format used in JSON Web Tokens and more generally known
188
- * as IEEE P1363 encoding.
185
+ * Interfaces for JSON Web Key objects, as per [RFC7517](https://www.rfc-editor.org/rfc/rfc751).
189
186
  */
190
- export interface EcdsaParams {
191
- name: "ECDSA";
192
- hash: DigestAlgorithm;
187
+ export interface JsonWebKey {
188
+ /**
189
+ * Key type.
190
+ */
191
+ kty: string;
192
+ /**
193
+ * Key ID.
194
+ */
195
+ kid?: string;
196
+ }
197
+ export interface JsonWebKeyECPublic extends JsonWebKey {
198
+ /**
199
+ * Elliptic curve identifier.
200
+ */
201
+ crv: string;
202
+ /**
203
+ * Base64url-encoded x coordinate.
204
+ */
205
+ x: string;
206
+ /**
207
+ * Base64url-encoded y coordinate.
208
+ */
209
+ y: string;
210
+ }
211
+ export interface JsonWebKeyECPrivate extends JsonWebKeyECPublic {
212
+ /**
213
+ * Base64url-encoded d coordinate.
214
+ */
215
+ d: string;
216
+ }
217
+ export interface JsonWebKeyRSAPublic extends JsonWebKey {
218
+ /**
219
+ * Base64url-encoded modulus.
220
+ */
221
+ n: string;
222
+ /**
223
+ * Base64url-encoded exponent.
224
+ */
225
+ e: string;
226
+ }
227
+ export interface JsonWebKeyRSAPrivate extends JsonWebKeyRSAPublic {
228
+ /**
229
+ * Private exponent.
230
+ */
231
+ d: string;
232
+ /**
233
+ * Additional exponents.
234
+ */
235
+ p: string;
236
+ q: string;
237
+ dp: string;
238
+ dq: string;
239
+ qi: string;
193
240
  }
194
- export declare type SigningAlgorithm = RsaPkcsParams | EcdsaParams;
195
- export declare type DigestAlgorithm = "SHA-256";
196
241
  export interface CCFCrypto {
242
+ /**
243
+ * Generate a signature.
244
+ *
245
+ * @param algorithm Signing algorithm and parameters
246
+ * @param key A PEM-encoded private key
247
+ * @param plaintext Input data that will be signed
248
+ * @throws Will throw an error if the key is not compatible with the
249
+ * signing algorithm or if an unknown algorithm is used.
250
+ */
251
+ sign(algorithm: SigningAlgorithm, key: string, plaintext: ArrayBuffer): ArrayBuffer;
197
252
  /**
198
253
  * Returns whether digital signature is valid.
199
254
  *
200
255
  * @param algorithm Signing algorithm and parameters
201
256
  * @param key A PEM-encoded public key or X.509 certificate
202
257
  * @param signature Signature to verify
203
- * @param data Data that was signed
258
+ * @param plaintext Input data that was signed
204
259
  * @throws Will throw an error if the key is not compatible with the
205
260
  * signing algorithm or if an unknown algorithm is used.
206
261
  */
207
- verifySignature(algorithm: SigningAlgorithm, key: string, signature: ArrayBuffer, data: ArrayBuffer): boolean;
262
+ verifySignature(algorithm: SigningAlgorithm, key: string, signature: ArrayBuffer, plaintext: ArrayBuffer): boolean;
263
+ /**
264
+ * Generate an AES key.
265
+ *
266
+ * @param size The length in bits of the key to generate. 128, 192, or 256.
267
+ */
268
+ generateAesKey(size: number): ArrayBuffer;
269
+ /**
270
+ * Generate an RSA key pair.
271
+ *
272
+ * @param size The length in bits of the RSA modulus. Minimum: 2048.
273
+ * @param exponent The public exponent. Default: 65537.
274
+ */
275
+ generateRsaKeyPair(size: number, exponent?: number): CryptoKeyPair;
276
+ /**
277
+ * Generate an ECDSA key pair.
278
+ *
279
+ * @param curve The name of the curve, one of "secp256r1", "secp256k1", "secp384r1".
280
+ */
281
+ generateEcdsaKeyPair(curve: string): CryptoKeyPair;
282
+ /**
283
+ * Generate an EdDSA key pair.
284
+ *
285
+ * @param curve The name of the curve. Currently only "curve25519" is supported.
286
+ */
287
+ generateEddsaKeyPair(curve: string): CryptoKeyPair;
288
+ /**
289
+ * Wraps a key using a wrapping key.
290
+ *
291
+ * Constraints on the `key` and `wrappingKey` parameters depend
292
+ * on the wrapping algorithm that is used (`wrapAlgo`).
293
+ */
294
+ wrapKey(key: ArrayBuffer, wrappingKey: ArrayBuffer, wrapAlgo: WrapAlgoParams): ArrayBuffer;
295
+ /**
296
+ * Generate a digest (hash) of the given data.
297
+ */
298
+ digest(algorithm: DigestAlgorithm, plaintext: ArrayBuffer): ArrayBuffer;
299
+ /**
300
+ * Returns whether a string is a PEM-encoded bundle of X.509 certificates.
301
+ *
302
+ * A bundle consists of one or more certificates.
303
+ * Certificates in the bundle do not have to be related to each other.
304
+ * Validation is only syntactical, properties like validity dates are not evaluated.
305
+ */
306
+ isValidX509CertBundle(pem: string): boolean;
307
+ /**
308
+ * Returns whether a certificate chain is valid given a set of trusted certificates.
309
+ * The chain and trusted certificates are PEM-encoded bundles of X.509 certificates.
310
+ */
311
+ isValidX509CertChain(chain: string, trusted: string): boolean;
312
+ /**
313
+ * Converts an elliptic curve public key as PEM to JSON Web Key (JWK) object.
314
+ *
315
+ * @param pem Elliptic curve public key as PEM
316
+ * @param kid Key identifier (optional)
317
+ */
318
+ pubPemToJwk(pem: string, kid?: string): JsonWebKeyECPublic;
319
+ /**
320
+ * Converts an elliptic curve private key as PEM to JSON Web Key (JWK) object.
321
+ *
322
+ * @param pem Elliptic curve private key as PEM
323
+ * @param kid Key identifier (optional)
324
+ */
325
+ pemToJwk(pem: string, kid?: string): JsonWebKeyECPrivate;
326
+ /**
327
+ * Converts an RSA public key as PEM to JSON Web Key (JWK) object.
328
+ *
329
+ * @param pem RSA public key as PEM
330
+ * @param kid Key identifier (optional)
331
+ */
332
+ pubRsaPemToJwk(pem: string, kid?: string): JsonWebKeyRSAPublic;
333
+ /**
334
+ * Converts an RSA private key as PEM to JSON Web Key (JWK) object.
335
+ *
336
+ * @param pem RSA private key as PEM
337
+ * @param kid Key identifier (optional)
338
+ */
339
+ rsaPemToJwk(pem: string, kid?: string): JsonWebKeyRSAPrivate;
208
340
  }
209
341
  export interface CCFRpc {
210
342
  /**
@@ -309,46 +441,38 @@ export interface CCF {
309
441
  */
310
442
  bufToJsonCompatible<T extends JsonCompatible<T>>(v: ArrayBuffer): T;
311
443
  /**
312
- * Generate an AES key.
313
- *
314
- * @param size The length in bits of the key to generate. 128, 192, or 256.
444
+ * @deprecated This method has been moved to ccf.crypto namespace
445
+ * @see crypto.generateAesKey
315
446
  */
316
447
  generateAesKey(size: number): ArrayBuffer;
317
448
  /**
318
- * Generate an RSA key pair.
319
- *
320
- * @param size The length in bits of the RSA modulus. Minimum: 2048.
321
- * @param exponent The public exponent. Default: 65537.
449
+ * @deprecated This method has been moved to ccf.crypto namespace
450
+ * @see crypto.generateRsaKeyPair
322
451
  */
323
452
  generateRsaKeyPair(size: number, exponent?: number): CryptoKeyPair;
324
453
  /**
325
- * Generate an ECDSA key pair.
326
- *
327
- * @param curve The name of the curve, one of "secp256r1", "secp256k1", "secp384r1".
454
+ * @deprecated This method has been moved to ccf.crypto namespace
455
+ * @see crypto.generateEcdsaKeyPair
328
456
  */
329
457
  generateEcdsaKeyPair(curve: string): CryptoKeyPair;
330
458
  /**
331
- * Wraps a key using a wrapping key.
332
- *
333
- * Constraints on the `key` and `wrappingKey` parameters depend
334
- * on the wrapping algorithm that is used (`wrapAlgo`).
459
+ * @deprecated This method has been moved to ccf.crypto namespace
460
+ * @see crypto.wrapKey
335
461
  */
336
462
  wrapKey(key: ArrayBuffer, wrappingKey: ArrayBuffer, wrapAlgo: WrapAlgoParams): ArrayBuffer;
337
463
  /**
338
- * Generate a digest (hash) of the given data.
464
+ * @deprecated This method has been moved to ccf.crypto namespace
465
+ * @see crypto.digest
339
466
  */
340
467
  digest(algorithm: DigestAlgorithm, data: ArrayBuffer): ArrayBuffer;
341
468
  /**
342
- * Returns whether a string is a PEM-encoded bundle of X.509 certificates.
343
- *
344
- * A bundle consists of one or more certificates.
345
- * Certificates in the bundle do not have to be related to each other.
346
- * Validation is only syntactical, properties like validity dates are not evaluated.
469
+ * @deprecated
470
+ * @see crypto.isValidX509CertBundle
347
471
  */
348
472
  isValidX509CertBundle(pem: string): boolean;
349
473
  /**
350
- * Returns whether a certificate chain is valid given a set of trusted certificates.
351
- * The chain and trusted certificates are PEM-encoded bundles of X.509 certificates.
474
+ * @deprecated This method has been moved to ccf.crypto namespace
475
+ * @see crypto.isValidX509CertChain
352
476
  */
353
477
  isValidX509CertChain(chain: string, trusted: string): boolean;
354
478
  crypto: CCFCrypto;
package/historical.d.ts CHANGED
@@ -3,11 +3,11 @@
3
3
  */
4
4
  export declare const historicalState: import("./global.js").HistoricalState | undefined;
5
5
  /**
6
- * @inheritDoc CCFHistorical.getStateRange
6
+ * @inheritDoc global!CCFHistorical.getStateRange
7
7
  */
8
8
  export declare const getStateRange: (handle: number, startSeqno: number, endSeqno: number, secondsUntilExpiry: number) => import("./global.js").HistoricalState[] | null;
9
9
  /**
10
- * @inheritDoc CCFHistorical.dropCachedStates
10
+ * @inheritDoc global!CCFHistorical.dropCachedStates
11
11
  */
12
12
  export declare const dropCachedStates: (handle: number) => boolean;
13
13
  export { HistoricalState, Receipt, Proof, ProofElement } from "./global";
package/historical.js CHANGED
@@ -33,10 +33,10 @@ import { ccf } from "./global.js";
33
33
  */
34
34
  export const historicalState = ccf.historicalState;
35
35
  /**
36
- * @inheritDoc CCFHistorical.getStateRange
36
+ * @inheritDoc global!CCFHistorical.getStateRange
37
37
  */
38
38
  export const getStateRange = ccf.historical.getStateRange.bind(ccf.historical);
39
39
  /**
40
- * @inheritDoc CCFHistorical.dropCachedStates
40
+ * @inheritDoc global!CCFHistorical.dropCachedStates
41
41
  */
42
42
  export const dropCachedStates = ccf.historical.dropCachedStates.bind(ccf.historical);
package/openenclave.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @inheritDoc OpenEnclave.verifyOpenEnclaveEvidence
2
+ * @inheritDoc global!OpenEnclave.verifyOpenEnclaveEvidence
3
3
  */
4
4
  export declare const verifyOpenEnclaveEvidence: (format: string | undefined, evidence: ArrayBuffer, endorsements?: ArrayBuffer | undefined) => import("./global").EvidenceClaims;
5
5
  export { EvidenceClaims } from "./global";
package/openenclave.js CHANGED
@@ -7,6 +7,6 @@
7
7
  */
8
8
  import { openenclave } from "./global";
9
9
  /**
10
- * @inheritDoc OpenEnclave.verifyOpenEnclaveEvidence
10
+ * @inheritDoc global!OpenEnclave.verifyOpenEnclaveEvidence
11
11
  */
12
12
  export const verifyOpenEnclaveEvidence = openenclave.verifyOpenEnclaveEvidence;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@microsoft/ccf-app",
3
- "version": "3.0.0-dev6",
3
+ "version": "3.0.0-rc1",
4
4
  "description": "CCF app support package",
5
5
  "main": "index.js",
6
6
  "files": [
@@ -19,12 +19,14 @@
19
19
  "license": "Apache-2.0",
20
20
  "devDependencies": {
21
21
  "@types/chai": "^4.2.15",
22
+ "@types/jsrsasign": "^10.5.4",
22
23
  "@types/mocha": "^10.0.0",
23
24
  "@types/node": "^18.0.0",
24
25
  "@types/node-forge": "^1.0.0",
25
26
  "chai": "^4.3.4",
26
27
  "colors": "1.4.0",
27
28
  "cross-env": "^7.0.3",
29
+ "jsrsasign": "^10.5.27",
28
30
  "mocha": "^10.0.0",
29
31
  "node-forge": "^1.2.0",
30
32
  "ts-node": "^10.4.0",
package/polyfill.js CHANGED
@@ -14,8 +14,9 @@
14
14
  *
15
15
  * @module
16
16
  */
17
- import * as crypto from "crypto";
17
+ import * as jscrypto from "crypto";
18
18
  import { TextEncoder, TextDecoder } from "util";
19
+ import * as rs from "jsrsasign";
19
20
  // JavaScript's Map uses reference equality for non-primitive types,
20
21
  // whereas CCF compares the content of the ArrayBuffer.
21
22
  // To achieve CCF's semantics, all keys are base64-encoded.
@@ -91,12 +92,48 @@ class CCFPolyfill {
91
92
  },
92
93
  };
93
94
  this.crypto = {
95
+ sign(algorithm, key, data) {
96
+ let padding = undefined;
97
+ const privKey = jscrypto.createPrivateKey(key);
98
+ if (privKey.asymmetricKeyType == "rsa") {
99
+ if (algorithm.name === "RSASSA-PKCS1-v1_5") {
100
+ padding = jscrypto.constants.RSA_PKCS1_PADDING;
101
+ }
102
+ else {
103
+ throw new Error("incompatible signing algorithm for given key type");
104
+ }
105
+ }
106
+ else if (privKey.asymmetricKeyType == "ec") {
107
+ if (algorithm.name !== "ECDSA") {
108
+ throw new Error("incompatible signing algorithm for given key type");
109
+ }
110
+ }
111
+ else if (privKey.asymmetricKeyType == "ed25519") {
112
+ if (algorithm.name !== "EdDSA") {
113
+ throw new Error("incompatible signing algorithm for given key type");
114
+ }
115
+ }
116
+ else {
117
+ throw new Error("unrecognized signing algorithm");
118
+ }
119
+ if (algorithm.name === "EdDSA") {
120
+ return jscrypto.sign(null, new Uint8Array(data), privKey);
121
+ }
122
+ const hashAlg = algorithm.hash.replace("-", "").toLowerCase();
123
+ const signer = jscrypto.createSign(hashAlg);
124
+ signer.update(new Uint8Array(data));
125
+ return signer.sign({
126
+ key: privKey,
127
+ dsaEncoding: "ieee-p1363",
128
+ padding: padding,
129
+ });
130
+ },
94
131
  verifySignature(algorithm, key, signature, data) {
95
132
  let padding = undefined;
96
- const pubKey = crypto.createPublicKey(key);
133
+ const pubKey = jscrypto.createPublicKey(key);
97
134
  if (pubKey.asymmetricKeyType == "rsa") {
98
135
  if (algorithm.name === "RSASSA-PKCS1-v1_5") {
99
- padding = crypto.constants.RSA_PKCS1_PADDING;
136
+ padding = jscrypto.constants.RSA_PKCS1_PADDING;
100
137
  }
101
138
  else {
102
139
  throw new Error("incompatible signing algorithm for given key type");
@@ -107,11 +144,19 @@ class CCFPolyfill {
107
144
  throw new Error("incompatible signing algorithm for given key type");
108
145
  }
109
146
  }
147
+ else if (pubKey.asymmetricKeyType == "ed25519") {
148
+ if (algorithm.name !== "EdDSA") {
149
+ throw new Error("incompatible signing algorithm for given key type");
150
+ }
151
+ }
110
152
  else {
111
153
  throw new Error("unrecognized signing algorithm");
112
154
  }
155
+ if (algorithm.name === "EdDSA") {
156
+ return jscrypto.verify(null, new Uint8Array(data), pubKey, new Uint8Array(signature));
157
+ }
113
158
  const hashAlg = algorithm.hash.replace("-", "").toLowerCase();
114
- const verifier = crypto.createVerify(hashAlg);
159
+ const verifier = jscrypto.createVerify(hashAlg);
115
160
  verifier.update(new Uint8Array(data));
116
161
  return verifier.verify({
117
162
  key: pubKey,
@@ -119,6 +164,189 @@ class CCFPolyfill {
119
164
  padding: padding,
120
165
  }, new Uint8Array(signature));
121
166
  },
167
+ generateAesKey(size) {
168
+ return nodeBufToArrBuf(jscrypto.randomBytes(size / 8));
169
+ },
170
+ generateRsaKeyPair(size, exponent) {
171
+ const rsaKeyPair = jscrypto.generateKeyPairSync("rsa", {
172
+ modulusLength: size,
173
+ publicExponent: exponent,
174
+ publicKeyEncoding: {
175
+ type: "spki",
176
+ format: "pem",
177
+ },
178
+ privateKeyEncoding: {
179
+ type: "pkcs8",
180
+ format: "pem",
181
+ },
182
+ });
183
+ return rsaKeyPair;
184
+ },
185
+ generateEcdsaKeyPair(curve) {
186
+ var curve_name = curve;
187
+ if (curve == "secp256r1")
188
+ curve_name = "prime256v1";
189
+ const ecdsaKeyPair = jscrypto.generateKeyPairSync("ec", {
190
+ namedCurve: curve_name,
191
+ publicKeyEncoding: {
192
+ type: "spki",
193
+ format: "pem",
194
+ },
195
+ privateKeyEncoding: {
196
+ type: "pkcs8",
197
+ format: "pem",
198
+ },
199
+ });
200
+ return ecdsaKeyPair;
201
+ },
202
+ generateEddsaKeyPair(curve) {
203
+ // `type` is always "ed25519" because currently only "curve25519" is supported for `curve`.
204
+ const type = "ed25519";
205
+ const ecdsaKeyPair = jscrypto.generateKeyPairSync(type, {
206
+ publicKeyEncoding: {
207
+ type: "spki",
208
+ format: "pem",
209
+ },
210
+ privateKeyEncoding: {
211
+ type: "pkcs8",
212
+ format: "pem",
213
+ },
214
+ });
215
+ return ecdsaKeyPair;
216
+ },
217
+ wrapKey(key, wrappingKey, parameters) {
218
+ if (parameters.name === "RSA-OAEP") {
219
+ return nodeBufToArrBuf(jscrypto.publicEncrypt({
220
+ key: Buffer.from(wrappingKey),
221
+ oaepHash: "sha256",
222
+ oaepLabel: parameters.label
223
+ ? new Uint8Array(parameters.label)
224
+ : undefined,
225
+ padding: jscrypto.constants.RSA_PKCS1_OAEP_PADDING,
226
+ }, new Uint8Array(key)));
227
+ }
228
+ else if (parameters.name === "AES-KWP") {
229
+ const iv = Buffer.from("A65959A6", "hex"); // defined in RFC 5649
230
+ const cipher = jscrypto.createCipheriv("id-aes256-wrap-pad", new Uint8Array(wrappingKey), iv);
231
+ return nodeBufToArrBuf(Buffer.concat([cipher.update(new Uint8Array(key)), cipher.final()]));
232
+ }
233
+ else if (parameters.name === "RSA-OAEP-AES-KWP") {
234
+ const randomAesKey = this.generateAesKey(parameters.aesKeySize);
235
+ const wrap1 = this.wrapKey(randomAesKey, wrappingKey, {
236
+ name: "RSA-OAEP",
237
+ label: parameters.label,
238
+ });
239
+ const wrap2 = this.wrapKey(key, randomAesKey, {
240
+ name: "AES-KWP",
241
+ });
242
+ return nodeBufToArrBuf(Buffer.concat([Buffer.from(wrap1), Buffer.from(wrap2)]));
243
+ }
244
+ else {
245
+ throw new Error("unsupported wrapAlgo.name");
246
+ }
247
+ },
248
+ digest(algorithm, data) {
249
+ if (algorithm === "SHA-256") {
250
+ return nodeBufToArrBuf(jscrypto.createHash("sha256").update(new Uint8Array(data)).digest());
251
+ }
252
+ else {
253
+ throw new Error("unsupported algorithm");
254
+ }
255
+ },
256
+ isValidX509CertBundle(pem) {
257
+ if ("X509Certificate" in jscrypto) {
258
+ const sep = "-----END CERTIFICATE-----";
259
+ const items = pem.split(sep);
260
+ if (items.length === 1) {
261
+ return false;
262
+ }
263
+ const pems = items.slice(0, -1).map((p) => p + sep);
264
+ for (const [i, p] of pems.entries()) {
265
+ try {
266
+ new jscrypto.X509Certificate(p);
267
+ }
268
+ catch (e) {
269
+ console.error(`cert ${i} is not valid: ${e.message}`);
270
+ console.error(p);
271
+ return false;
272
+ }
273
+ }
274
+ return true;
275
+ }
276
+ else {
277
+ throw new Error("X509 validation unsupported, Node.js version too old (< 15.6.0)");
278
+ }
279
+ },
280
+ isValidX509CertChain(chain, trusted) {
281
+ if (!("X509Certificate" in jscrypto)) {
282
+ throw new Error("X509 validation unsupported, Node.js version too old (< 15.6.0)");
283
+ }
284
+ try {
285
+ const toX509Array = (pem) => {
286
+ const sep = "-----END CERTIFICATE-----";
287
+ const items = pem.split(sep);
288
+ if (items.length === 1) {
289
+ return [];
290
+ }
291
+ const pems = items.slice(0, -1).map((p) => p + sep);
292
+ const arr = pems.map((pem) => new jscrypto.X509Certificate(pem));
293
+ return arr;
294
+ };
295
+ const certsChain = toX509Array(chain);
296
+ const certsTrusted = toX509Array(trusted);
297
+ if (certsChain.length === 0) {
298
+ throw new Error("chain cannot be empty");
299
+ }
300
+ for (let i = 0; i < certsChain.length - 1; i++) {
301
+ if (!certsChain[i].checkIssued(certsChain[i + 1])) {
302
+ throw new Error(`chain[${i}] is not issued by chain[${i + 1}]`);
303
+ }
304
+ }
305
+ for (const certChain of certsChain) {
306
+ for (const certTrusted of certsTrusted) {
307
+ if (certChain.fingerprint === certTrusted.fingerprint) {
308
+ return true;
309
+ }
310
+ if (certChain.verify(certTrusted.publicKey)) {
311
+ return true;
312
+ }
313
+ }
314
+ }
315
+ throw new Error("none of the chain certificates are identical to or issued by a trusted certificate");
316
+ }
317
+ catch (e) {
318
+ console.error(`certificate chain validation failed: ${e.message}`);
319
+ return false;
320
+ }
321
+ },
322
+ pubPemToJwk(pem, kid) {
323
+ let jwk = rs.KEYUTIL.getJWK(rs.KEYUTIL.getKey(pem));
324
+ if (kid !== undefined) {
325
+ jwk.kid = kid;
326
+ }
327
+ return jwk;
328
+ },
329
+ pemToJwk(pem, kid) {
330
+ let jwk = rs.KEYUTIL.getJWK(rs.KEYUTIL.getKey(pem));
331
+ if (kid !== undefined) {
332
+ jwk.kid = kid;
333
+ }
334
+ return jwk;
335
+ },
336
+ pubRsaPemToJwk(pem, kid) {
337
+ let jwk = rs.KEYUTIL.getJWK(rs.KEYUTIL.getKey(pem));
338
+ if (kid !== undefined) {
339
+ jwk.kid = kid;
340
+ }
341
+ return jwk;
342
+ },
343
+ rsaPemToJwk(pem, kid) {
344
+ let jwk = rs.KEYUTIL.getJWK(rs.KEYUTIL.getKey(pem));
345
+ if (kid !== undefined) {
346
+ jwk.kid = kid;
347
+ }
348
+ return jwk;
349
+ },
122
350
  };
123
351
  }
124
352
  strToBuf(s) {
@@ -134,144 +362,25 @@ class CCFPolyfill {
134
362
  return JSON.parse(this.bufToStr(v));
135
363
  }
136
364
  generateAesKey(size) {
137
- return nodeBufToArrBuf(crypto.randomBytes(size / 8));
365
+ return this.crypto.generateAesKey(size);
138
366
  }
139
367
  generateRsaKeyPair(size, exponent) {
140
- const rsaKeyPair = crypto.generateKeyPairSync("rsa", {
141
- modulusLength: size,
142
- publicExponent: exponent,
143
- publicKeyEncoding: {
144
- type: "spki",
145
- format: "pem",
146
- },
147
- privateKeyEncoding: {
148
- type: "pkcs8",
149
- format: "pem",
150
- },
151
- });
152
- return rsaKeyPair;
368
+ return this.crypto.generateRsaKeyPair(size, exponent);
153
369
  }
154
370
  generateEcdsaKeyPair(curve) {
155
- var curve_name = curve;
156
- if (curve == "secp256r1")
157
- curve_name = "prime256v1";
158
- const ecdsaKeyPair = crypto.generateKeyPairSync("ec", {
159
- namedCurve: curve_name,
160
- publicKeyEncoding: {
161
- type: "spki",
162
- format: "pem",
163
- },
164
- privateKeyEncoding: {
165
- type: "pkcs8",
166
- format: "pem",
167
- },
168
- });
169
- return ecdsaKeyPair;
371
+ return this.crypto.generateEcdsaKeyPair(curve);
170
372
  }
171
373
  wrapKey(key, wrappingKey, parameters) {
172
- if (parameters.name === "RSA-OAEP") {
173
- return nodeBufToArrBuf(crypto.publicEncrypt({
174
- key: Buffer.from(wrappingKey),
175
- oaepHash: "sha256",
176
- oaepLabel: parameters.label
177
- ? new Uint8Array(parameters.label)
178
- : undefined,
179
- padding: crypto.constants.RSA_PKCS1_OAEP_PADDING,
180
- }, new Uint8Array(key)));
181
- }
182
- else if (parameters.name === "AES-KWP") {
183
- const iv = Buffer.from("A65959A6", "hex"); // defined in RFC 5649
184
- const cipher = crypto.createCipheriv("id-aes256-wrap-pad", new Uint8Array(wrappingKey), iv);
185
- return nodeBufToArrBuf(Buffer.concat([cipher.update(new Uint8Array(key)), cipher.final()]));
186
- }
187
- else if (parameters.name === "RSA-OAEP-AES-KWP") {
188
- const randomAesKey = this.generateAesKey(parameters.aesKeySize);
189
- const wrap1 = this.wrapKey(randomAesKey, wrappingKey, {
190
- name: "RSA-OAEP",
191
- label: parameters.label,
192
- });
193
- const wrap2 = this.wrapKey(key, randomAesKey, {
194
- name: "AES-KWP",
195
- });
196
- return nodeBufToArrBuf(Buffer.concat([Buffer.from(wrap1), Buffer.from(wrap2)]));
197
- }
198
- else {
199
- throw new Error("unsupported wrapAlgo.name");
200
- }
374
+ return this.crypto.wrapKey(key, wrappingKey, parameters);
201
375
  }
202
376
  digest(algorithm, data) {
203
- if (algorithm === "SHA-256") {
204
- return nodeBufToArrBuf(crypto.createHash("sha256").update(new Uint8Array(data)).digest());
205
- }
206
- else {
207
- throw new Error("unsupported algorithm");
208
- }
377
+ return this.crypto.digest(algorithm, data);
209
378
  }
210
379
  isValidX509CertBundle(pem) {
211
- if ("X509Certificate" in crypto) {
212
- const sep = "-----END CERTIFICATE-----";
213
- const items = pem.split(sep);
214
- if (items.length === 1) {
215
- return false;
216
- }
217
- const pems = items.slice(0, -1).map((p) => p + sep);
218
- for (const [i, p] of pems.entries()) {
219
- try {
220
- new crypto.X509Certificate(p);
221
- }
222
- catch (e) {
223
- console.error(`cert ${i} is not valid: ${e.message}`);
224
- console.error(p);
225
- return false;
226
- }
227
- }
228
- return true;
229
- }
230
- else {
231
- throw new Error("X509 validation unsupported, Node.js version too old (< 15.6.0)");
232
- }
380
+ return this.crypto.isValidX509CertBundle(pem);
233
381
  }
234
382
  isValidX509CertChain(chain, trusted) {
235
- if (!("X509Certificate" in crypto)) {
236
- throw new Error("X509 validation unsupported, Node.js version too old (< 15.6.0)");
237
- }
238
- try {
239
- const toX509Array = (pem) => {
240
- const sep = "-----END CERTIFICATE-----";
241
- const items = pem.split(sep);
242
- if (items.length === 1) {
243
- return [];
244
- }
245
- const pems = items.slice(0, -1).map((p) => p + sep);
246
- const arr = pems.map((pem) => new crypto.X509Certificate(pem));
247
- return arr;
248
- };
249
- const certsChain = toX509Array(chain);
250
- const certsTrusted = toX509Array(trusted);
251
- if (certsChain.length === 0) {
252
- throw new Error("chain cannot be empty");
253
- }
254
- for (let i = 0; i < certsChain.length - 1; i++) {
255
- if (!certsChain[i].checkIssued(certsChain[i + 1])) {
256
- throw new Error(`chain[${i}] is not issued by chain[${i + 1}]`);
257
- }
258
- }
259
- for (const certChain of certsChain) {
260
- for (const certTrusted of certsTrusted) {
261
- if (certChain.fingerprint === certTrusted.fingerprint) {
262
- return true;
263
- }
264
- if (certChain.verify(certTrusted.publicKey)) {
265
- return true;
266
- }
267
- }
268
- }
269
- throw new Error("none of the chain certificates are identical to or issued by a trusted certificate");
270
- }
271
- catch (e) {
272
- console.error(`certificate chain validation failed: ${e.message}`);
273
- return false;
274
- }
383
+ return this.crypto.isValidX509CertChain(chain, trusted);
275
384
  }
276
385
  }
277
386
  globalThis.ccf = new CCFPolyfill();