@dfns/sdk-keysigner 0.3.3 → 0.3.4

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.
Files changed (3) hide show
  1. package/index.d.ts +4 -5
  2. package/index.js +48 -32
  3. package/package.json +2 -2
package/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { CredentialSigner, KeyAssertion } from '@dfns/sdk';
1
+ import { CredentialSigner, KeyAssertion, UserRegistrationChallenge, KeyAttestation } from '@dfns/sdk';
2
2
  export declare class AsymmetricKeySigner implements CredentialSigner<KeyAssertion> {
3
3
  private options;
4
4
  constructor(options: {
@@ -13,12 +13,11 @@ export declare class AsymmetricKeySigner implements CredentialSigner<KeyAssertio
13
13
  export declare class BrowserKeySigner implements CredentialSigner<KeyAssertion> {
14
14
  private options;
15
15
  constructor(options: {
16
- privateKey: CryptoKey;
17
- credId: string;
16
+ keyPair: CryptoKeyPair;
17
+ credId?: string;
18
18
  appOrigin: string;
19
19
  crossOrigin?: boolean;
20
20
  });
21
- minimizeBigInt: (value: Uint8Array) => Uint8Array;
22
- rawSignatureToAns1: (rawSignature: Uint8Array) => Uint8Array;
21
+ create(challenge: UserRegistrationChallenge): Promise<KeyAttestation>;
23
22
  sign(challenge: string): Promise<KeyAssertion>;
24
23
  }
package/index.js CHANGED
@@ -51,37 +51,53 @@ exports.AsymmetricKeySigner = AsymmetricKeySigner;
51
51
  class BrowserKeySigner {
52
52
  constructor(options) {
53
53
  this.options = options;
54
- this.minimizeBigInt = (value) => {
55
- const minValue = [0, ...value];
56
- for (let i = 0; i < minValue.length; ++i) {
57
- if (minValue[i] === 0) {
58
- continue;
59
- }
60
- if (minValue[i] > 0x7f) {
61
- return new Uint8Array(minValue.slice(i - 1));
62
- }
63
- return new Uint8Array(minValue.slice(i));
64
- }
65
- return new Uint8Array([0]);
66
- };
67
- this.rawSignatureToAns1 = (rawSignature) => {
68
- const r = rawSignature.slice(0, 32);
69
- const s = rawSignature.slice(32);
70
- const minR = this.minimizeBigInt(r);
71
- const minS = this.minimizeBigInt(s);
72
- return new Uint8Array([
73
- 0x30,
74
- minR.length + minS.length + 4,
75
- 0x02,
76
- minR.length,
77
- ...minR,
78
- 0x02,
79
- minS.length,
80
- ...minS
81
- ]);
54
+ }
55
+ async create(challenge) {
56
+ let credId = this.options.credId;
57
+ if (credId === undefined || credId === '') {
58
+ credId = (0, utils_1.toBase64Url)(Buffer.from((0, utils_1.generateRandom)(32)));
59
+ this.options.credId = credId;
60
+ }
61
+ const publicKeyPem = await (0, utils_1.exportPublicKeyInPemFormatBrowser)(this.options.keyPair);
62
+ const clientData = JSON.stringify({
63
+ type: 'key.create',
64
+ challenge: challenge.challenge,
65
+ origin: this.options.appOrigin,
66
+ crossOrigin: this.options.crossOrigin ?? false,
67
+ });
68
+ const clientDataHash = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(clientData));
69
+ const clientDataHashHex = (0, utils_1.toHex)(clientDataHash);
70
+ const credInfoFingerprint = JSON.stringify({
71
+ clientDataHash: clientDataHashHex,
72
+ publicKey: publicKeyPem,
73
+ });
74
+ let rawSignature;
75
+ const algorithm = this.options.keyPair.privateKey.algorithm.name;
76
+ if (algorithm == 'ECDSA') {
77
+ rawSignature = await crypto.subtle.sign({ name: 'ECDSA', hash: { name: 'SHA-256' } }, this.options.keyPair.privateKey, new TextEncoder().encode(credInfoFingerprint));
78
+ }
79
+ else {
80
+ throw new Error(`${algorithm} is not supported`);
81
+ }
82
+ const signature = (0, utils_1.rawSignatureToAns1)(new Uint8Array(rawSignature));
83
+ const attestationData = JSON.stringify({
84
+ publicKey: publicKeyPem,
85
+ signature: (0, utils_1.toHex)(signature)
86
+ });
87
+ return {
88
+ credentialKind: 'Key',
89
+ credentialInfo: {
90
+ credId: credId,
91
+ clientData: (0, utils_1.toBase64Url)(clientData),
92
+ attestationData: (0, utils_1.toBase64Url)(attestationData),
93
+ },
82
94
  };
83
95
  }
84
96
  async sign(challenge) {
97
+ const credId = this.options.credId;
98
+ if (credId === undefined || credId === '') {
99
+ throw new Error('credId is needed to sign');
100
+ }
85
101
  const clientData = JSON.stringify({
86
102
  type: 'key.get',
87
103
  challenge,
@@ -89,18 +105,18 @@ class BrowserKeySigner {
89
105
  crossOrigin: this.options.crossOrigin ?? false,
90
106
  });
91
107
  let rawSignature;
92
- const algorithm = this.options.privateKey.algorithm.name;
108
+ const algorithm = this.options.keyPair.privateKey.algorithm.name;
93
109
  if (algorithm == 'ECDSA') {
94
- rawSignature = await crypto.subtle.sign({ name: 'ECDSA', hash: { name: 'SHA-256' } }, this.options.privateKey, new TextEncoder().encode(clientData));
110
+ rawSignature = await crypto.subtle.sign({ name: 'ECDSA', hash: { name: 'SHA-256' } }, this.options.keyPair.privateKey, new TextEncoder().encode(clientData));
95
111
  }
96
112
  else {
97
113
  throw new Error(`${algorithm} is not supported`);
98
114
  }
99
- const signature = this.rawSignatureToAns1(new Uint8Array(rawSignature));
115
+ const signature = (0, utils_1.rawSignatureToAns1)(new Uint8Array(rawSignature));
100
116
  return {
101
117
  kind: 'Key',
102
118
  credentialAssertion: {
103
- credId: this.options.credId,
119
+ credId: this.options.credId ?? '',
104
120
  clientData: (0, utils_1.toBase64Url)(clientData),
105
121
  signature: (0, utils_1.toBase64Url)(Buffer.from(signature)),
106
122
  },
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@dfns/sdk-keysigner",
3
- "version": "0.3.3",
3
+ "version": "0.3.4",
4
4
  "dependencies": {
5
5
  "buffer": "6.0.3",
6
6
  "cross-fetch": "3.1.6",
7
7
  "uuid": "9.0.0"
8
8
  },
9
9
  "peerDependencies": {
10
- "@dfns/sdk": "0.3.3"
10
+ "@dfns/sdk": "0.3.4"
11
11
  },
12
12
  "main": "./index.js",
13
13
  "type": "commonjs"