@breakside/jskit 2024.34.0 → 2024.40.0

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 (86) hide show
  1. package/Frameworks/DOM.jsframework/Info.json +2 -2
  2. package/Frameworks/DOM.jsframework/io.breakside.JSKit.DOM-bundle.js +2 -2
  3. package/Frameworks/FontKit.jsframework/Info.json +2 -2
  4. package/Frameworks/FontKit.jsframework/io.breakside.JSKit.FontKit-bundle.js +2 -2
  5. package/Frameworks/Foundation.jsframework/Info.json +2 -2
  6. package/Frameworks/Foundation.jsframework/JS/JSClass.js +4 -1
  7. package/Frameworks/Foundation.jsframework/JS/JSNodeURLSessionStreamTask.js +1 -1
  8. package/Frameworks/Foundation.jsframework/io.breakside.JSKit.Foundation-bundle.js +2 -2
  9. package/Frameworks/SecurityKit.jsframework/Info.json +2 -2
  10. package/Frameworks/SecurityKit.jsframework/JS/SECCOSE.js +135 -0
  11. package/Frameworks/SecurityKit.jsframework/JS/SECCipher+HTML.js +231 -70
  12. package/Frameworks/SecurityKit.jsframework/JS/SECCipher+Node.js +155 -60
  13. package/Frameworks/SecurityKit.jsframework/JS/SECCipher.js +125 -54
  14. package/Frameworks/SecurityKit.jsframework/JS/SECDataKey.js +5 -4
  15. package/Frameworks/SecurityKit.jsframework/JS/SECHMAC+HTML.js +15 -11
  16. package/Frameworks/SecurityKit.jsframework/JS/SECHMAC+Node.js +17 -3
  17. package/Frameworks/SecurityKit.jsframework/JS/SECHTMLDeviceAuthentication.js +139 -106
  18. package/Frameworks/SecurityKit.jsframework/JS/SECHTMLKey.js +17 -0
  19. package/Frameworks/SecurityKit.jsframework/JS/SECHash.js +1 -0
  20. package/Frameworks/SecurityKit.jsframework/JS/SECJSONWebAlgorithms.js +9 -1
  21. package/Frameworks/SecurityKit.jsframework/JS/SECJSONWebEncryption.js +391 -0
  22. package/Frameworks/SecurityKit.jsframework/JS/SECJSONWebToken.js +1 -1
  23. package/Frameworks/SecurityKit.jsframework/JS/SECKey.js +14 -1
  24. package/Frameworks/SecurityKit.jsframework/JS/SECNodeKey.js +66 -1
  25. package/Frameworks/SecurityKit.jsframework/JS/SECSign+HTML.js +2 -27
  26. package/Frameworks/SecurityKit.jsframework/JS/SECSign+Node.js +103 -278
  27. package/Frameworks/SecurityKit.jsframework/JS/SECSign.js +27 -0
  28. package/Frameworks/SecurityKit.jsframework/JS/SECVerify+Node.js +60 -57
  29. package/Frameworks/SecurityKit.jsframework/JS/SecurityKit.js +1 -0
  30. package/Frameworks/SecurityKit.jsframework/io.breakside.JSKit.SecurityKit-bundle.js +2 -2
  31. package/Frameworks/SecurityKit.jsframework/sources.json +6 -0
  32. package/Info.json +2 -2
  33. package/Node/KeyCommand.js +8 -1
  34. package/Node/io.breakside.jskit-bundle.js +2 -2
  35. package/Node/jskit +1 -0
  36. package/Root/Frameworks/APIKit/Info.yaml +1 -1
  37. package/Root/Frameworks/APIKitTesting/Info.yaml +1 -1
  38. package/Root/Frameworks/AuthKit/Info.yaml +1 -1
  39. package/Root/Frameworks/CSSOM/Info.yaml +1 -1
  40. package/Root/Frameworks/ChartKit/Info.yaml +1 -1
  41. package/Root/Frameworks/ConferenceKit/Info.yaml +1 -1
  42. package/Root/Frameworks/DBKit/DBEncryptedObject.js +2 -2
  43. package/Root/Frameworks/DBKit/Info.yaml +1 -1
  44. package/Root/Frameworks/DOM/Info.yaml +1 -1
  45. package/Root/Frameworks/Dispatch/Info.yaml +1 -1
  46. package/Root/Frameworks/FontKit/Info.yaml +1 -1
  47. package/Root/Frameworks/Foundation/Info.yaml +1 -1
  48. package/Root/Frameworks/Foundation/JSClass.js +4 -1
  49. package/Root/Frameworks/Foundation/JSNodeURLSessionStreamTask.js +1 -1
  50. package/Root/Frameworks/ImageKit/Info.yaml +1 -1
  51. package/Root/Frameworks/MediaKit/Info.yaml +1 -1
  52. package/Root/Frameworks/MediaKitUI/Info.yaml +1 -1
  53. package/Root/Frameworks/NotificationKit/Info.yaml +1 -1
  54. package/Root/Frameworks/NotificationKit/NKWebPushService.js +2 -2
  55. package/Root/Frameworks/PDFKit/Info.yaml +1 -1
  56. package/Root/Frameworks/PDFKit/PDFEncryption.js +1 -1
  57. package/Root/Frameworks/QRKit/Info.yaml +1 -1
  58. package/Root/Frameworks/SearchKit/Info.yaml +1 -1
  59. package/Root/Frameworks/SecurityKit/Info.yaml +1 -1
  60. package/Root/Frameworks/SecurityKit/SECCOSE.js +135 -0
  61. package/Root/Frameworks/SecurityKit/SECCipher+HTML.js +231 -70
  62. package/Root/Frameworks/SecurityKit/SECCipher+Node.js +155 -60
  63. package/Root/Frameworks/SecurityKit/SECCipher.js +125 -54
  64. package/Root/Frameworks/SecurityKit/SECDataKey.js +5 -4
  65. package/Root/Frameworks/SecurityKit/SECHMAC+HTML.js +15 -11
  66. package/Root/Frameworks/SecurityKit/SECHMAC+Node.js +17 -3
  67. package/Root/Frameworks/SecurityKit/SECHTMLDeviceAuthentication.js +139 -106
  68. package/Root/Frameworks/SecurityKit/SECHTMLKey.js +17 -0
  69. package/Root/Frameworks/SecurityKit/SECHash.js +1 -0
  70. package/Root/Frameworks/SecurityKit/SECJSONWebAlgorithms.js +9 -1
  71. package/Root/Frameworks/SecurityKit/SECJSONWebEncryption.js +391 -0
  72. package/Root/Frameworks/SecurityKit/SECJSONWebToken.js +1 -1
  73. package/Root/Frameworks/SecurityKit/SECKey.js +14 -1
  74. package/Root/Frameworks/SecurityKit/SECNodeKey.js +66 -1
  75. package/Root/Frameworks/SecurityKit/SECSign+HTML.js +2 -27
  76. package/Root/Frameworks/SecurityKit/SECSign+Node.js +103 -278
  77. package/Root/Frameworks/SecurityKit/SECSign.js +27 -0
  78. package/Root/Frameworks/SecurityKit/SECVerify+Node.js +60 -57
  79. package/Root/Frameworks/SecurityKit/SecurityKit.js +1 -0
  80. package/Root/Frameworks/ServerKit/Info.yaml +1 -1
  81. package/Root/Frameworks/ServerKitTesting/Info.yaml +1 -1
  82. package/Root/Frameworks/TestKit/Info.yaml +1 -1
  83. package/Root/Frameworks/UIKit/Info.yaml +1 -1
  84. package/Root/Frameworks/UIKitTesting/Info.yaml +1 -1
  85. package/package.json +1 -1
  86. package/Root/Templates/workspace/.gitignore +0 -4
@@ -38,14 +38,12 @@ SECHMAC.definePropertiesFromExtensions({
38
38
  if (!completion){
39
39
  completion = Promise.completion(Promise.resolveNonNull);
40
40
  }
41
- var algorithm = {
42
- name: this.htmlAlgorithm.name,
43
- hash: this.htmlAlgorithm.hash,
44
- length: 256
45
- };
41
+ var algorithm = this.htmlAlgorithm;
46
42
  var extractable = true;
47
43
  crypto.subtle.generateKey(algorithm, extractable, ["sign"]).then(function(htmlKey){
48
- completion.call(target, SECHTMLKey.initWithKey(htmlKey));
44
+ var key = SECHTMLKey.initWithKey(htmlKey);
45
+ key.id = JSSHA1Hash(UUID.init().bytes).base64URLStringRepresentation();
46
+ completion.call(target, key);
49
47
  }, function(e){
50
48
  completion.call(target, null);
51
49
  });
@@ -57,7 +55,10 @@ SECHMAC.definePropertiesFromExtensions({
57
55
  completion = Promise.completion(Promise.resolveNonNull);
58
56
  }
59
57
  var extractable = true;
60
- var algorithm = this.htmlAlgorithm;
58
+ var algorithm = {
59
+ name: this.htmlAlgorithm.name,
60
+ hash: this.htmlAlgorithm.hash
61
+ };
61
62
  crypto.subtle.importKey("raw", data, algorithm, extractable, ["sign"]).then(function(htmlKey){
62
63
  completion.call(target, SECHTMLKey.initWithKey(htmlKey));
63
64
  }, function(e){
@@ -77,7 +78,10 @@ SECHMAC.definePropertiesFromExtensions({
77
78
  if (!completion){
78
79
  completion = Promise.completion(Promise.resolveNonNull);
79
80
  }
80
- var algorithm = this.htmlAlgorithm;
81
+ var algorithm = {
82
+ name: this.htmlAlgorithm.name,
83
+ hash: this.htmlAlgorithm.hash
84
+ };
81
85
  var data = JSData.initWithChunks(this.chunks);
82
86
  crypto.subtle.sign(algorithm, this.key.htmlKey, data).then(function(computed){
83
87
  completion.call(target, JSData.initWithBuffer(computed));
@@ -91,9 +95,9 @@ SECHMAC.definePropertiesFromExtensions({
91
95
 
92
96
  var htmlAlgorithms = {};
93
97
  htmlAlgorithms[SECHMAC.Algorithm.sha1] = { name: 'HMAC', hash: 'SHA-1'};
94
- htmlAlgorithms[SECHMAC.Algorithm.sha256] = { name: 'HMAC', hash: 'SHA-256'};
95
- htmlAlgorithms[SECHMAC.Algorithm.sha384] = { name: 'HMAC', hash: 'SHA-384'};
96
- htmlAlgorithms[SECHMAC.Algorithm.sha512] = { name: 'HMAC', hash: 'SHA-512'};
98
+ htmlAlgorithms[SECHMAC.Algorithm.sha256] = { name: 'HMAC', hash: 'SHA-256', length: 256};
99
+ htmlAlgorithms[SECHMAC.Algorithm.sha384] = { name: 'HMAC', hash: 'SHA-384', length: 384};
100
+ htmlAlgorithms[SECHMAC.Algorithm.sha512] = { name: 'HMAC', hash: 'SHA-512', length: 512};
97
101
 
98
102
 
99
103
  })();
@@ -36,11 +36,25 @@ SECHMAC.definePropertiesFromExtensions({
36
36
  if (!completion){
37
37
  completion = Promise.completion(Promise.resolveNonNull);
38
38
  }
39
- crypto.randomBytes(32, function(error, keyBytes){
39
+ var length;
40
+ switch (this.nodeAlgorithm){
41
+ case "sha512":
42
+ length = 512;
43
+ break;
44
+ case "sha384":
45
+ length = 384;
46
+ break;
47
+ default:
48
+ length = 256;
49
+ break;
50
+ }
51
+ crypto.generateKey("hmac", {length: length}, function(error, nodeKeyObject){
40
52
  if (error){
41
53
  completion.call(target, null);
42
54
  }else{
43
- completion.call(target, SECNodeKey.initWithData(JSData.initWithNodeBuffer(keyBytes)));
55
+ var key = SECNodeKey.initWithNodeKeyObject(nodeKeyObject);
56
+ key.id = JSSHA1Hash(UUID.init().bytes).base64URLStringRepresentation();
57
+ completion.call(target, key);
44
58
  }
45
59
  });
46
60
  return completion.promise;
@@ -60,7 +74,7 @@ SECHMAC.definePropertiesFromExtensions({
60
74
  throw new Error("SECHMAC must have a key before calling update()");
61
75
  }
62
76
  if (this.nodeHash === null){
63
- this.nodeHash = crypto.createHmac(this.nodeAlgorithm, this.key.keyData);
77
+ this.nodeHash = crypto.createHmac(this.nodeAlgorithm, this.key.nodeKeyObject);
64
78
  }
65
79
  this.nodeHash.update(data);
66
80
  },
@@ -18,7 +18,7 @@
18
18
  // #import "SECSign.js"
19
19
  // #import "SECCBOR.js"
20
20
  // #import "SECHash.js"
21
- // #import "SECJSONWebAlgorithms.js"
21
+ // #import "SECCOSE.js"
22
22
  // jshint browser: true
23
23
  /* global AuthenticatorAttestationResponse */
24
24
  'use strict';
@@ -66,12 +66,13 @@ JSClass("SECHTMLDeviceAuthentication", JSObject, {
66
66
  // challengeData
67
67
  // supportedAlgorithms
68
68
  // platform
69
+ // conditional
69
70
  if (!completion){
70
71
  completion = Promise.completion();
71
72
  }
72
73
  if (this.credentialStore === null){
73
74
  JSRunLoop.main.schedule(completion, target, null);
74
- return;
75
+ return completion.promise;
75
76
  }
76
77
  registration = JSCopy(registration);
77
78
  if (!registration.providerName){
@@ -108,7 +109,7 @@ JSClass("SECHTMLDeviceAuthentication", JSObject, {
108
109
  // the client before authenticating
109
110
  requireResidentKey: false,
110
111
  residentKey: "discouraged",
111
- userVerification: registration.platform ? "required" : "discouraged",
112
+ userVerification: registration.platform && !registration.conditional ? "required" : "discouraged",
112
113
  authenticatorAttachment: registration.platform ? "platform" : "cross-platform"
113
114
  },
114
115
  attestation: "none",
@@ -132,34 +133,42 @@ JSClass("SECHTMLDeviceAuthentication", JSObject, {
132
133
  ];
133
134
  }
134
135
  var credentials = this.credentialStore;
135
- this.credentialStore.create({publicKey: info}).then(function(credential){
136
+ var handleCredential = function(credential){
136
137
  if (!credential || credential.type != "public-key"){
137
138
  completion.call(target, null);
138
139
  return;
139
140
  }
140
- var clientData = JSData.initWithBuffer(credential.response.clientDataJSON);
141
- var attestationCBOR = JSData.initWithBuffer(credential.response.attestationObject);
142
- var attestationParser = SECCBORParser.initWithData(attestationCBOR);
143
- attestationParser.encodeDataAsBase64URL = true;
144
- var attestation = attestationParser.parse();
145
- var authData = attestation.authData.dataByDecodingBase64URL();
146
- var length = (authData[53] << 8) | authData[54];
147
- var keyParser = SECCBORParser.initWithData(authData);
148
- keyParser.offset = 55 + length;
149
- var coseKey = keyParser.readNext();
150
- var jwk = jwkForCoseKey(coseKey, credential.id);
141
+ var jwk = credential.response.getPublicJWK();
142
+ var webauthn = credential.toJSON();
151
143
  var result = {
152
144
  jwk: jwk,
153
- webauthn: {
154
- attestation: attestation,
155
- clientData: clientData.base64URLStringRepresentation()
156
- },
157
- challenge: registration.challengeData
145
+ challenge: registration.challengeData,
146
+ webauthn: webauthn
158
147
  };
159
148
  completion.call(target, result);
160
- }, function(error){
161
- completion.call(target, null);
162
- });
149
+ };
150
+ if (registration.conditional){
151
+ if (!window.PublicKeyCredential || !window.PublicKeyCredential.getClientCapabilities){
152
+ JSRunLoop.main.schedule(completion, target, null);
153
+ return completion.promise;
154
+ }
155
+ window.PublicKeyCredential.getClientCapabilities().then(function(capabilities){
156
+ if (!capabilities || !capabilities.conditionalCreate){
157
+ completion.call(target, null);
158
+ return;
159
+ }
160
+ credentials.create({publicKey: info, mediation: "conditional"}).then(handleCredential,function(error){
161
+ completion.call(target, null);
162
+ });
163
+ }, function(e){
164
+ logger.error("failed to getClientCapabilities(): %{error}", e);
165
+ completion.call(target, null);
166
+ });
167
+ }else{
168
+ credentials.create({publicKey: info}).then(handleCredential, function(error){
169
+ completion.call(target, null);
170
+ });
171
+ }
163
172
  return completion.promise;
164
173
  },
165
174
 
@@ -212,15 +221,10 @@ JSClass("SECHTMLDeviceAuthentication", JSObject, {
212
221
  completion.call(target, null);
213
222
  return;
214
223
  }
215
- var clientData = JSData.initWithBuffer(credential.response.clientDataJSON);
216
- var authData = JSData.initWithBuffer(credential.response.authenticatorData);
217
- var hash = SECHash.initWithAlgorithm(SECHash.Algorithm.sha256);
224
+ var webauthn = credential.toJSON();
218
225
  var result = {
219
226
  kid: credential.id,
220
- webauthn: {
221
- authData: authData.base64URLStringRepresentation(),
222
- clientData: clientData.base64URLStringRepresentation()
223
- },
227
+ webauthn: webauthn,
224
228
  challenge: request.challengeData,
225
229
  signature: JSData.initWithBuffer(credential.response.signature)
226
230
  };
@@ -245,86 +249,115 @@ Object.defineProperties(SECDeviceAuthentication, {
245
249
  });
246
250
 
247
251
  var coseAlgorithmsBySignAlgorithm = {};
248
- coseAlgorithmsBySignAlgorithm[SECSign.Algorithm.rsaSHA256] = -257;
249
- coseAlgorithmsBySignAlgorithm[SECSign.Algorithm.rsaSHA384] = -258;
250
- coseAlgorithmsBySignAlgorithm[SECSign.Algorithm.rsaSHA512] = -259;
251
- coseAlgorithmsBySignAlgorithm[SECSign.Algorithm.ellipticCurveSHA256] = -7;
252
- coseAlgorithmsBySignAlgorithm[SECSign.Algorithm.ellipticCurveSHA384] = -35;
253
- coseAlgorithmsBySignAlgorithm[SECSign.Algorithm.ellipticCurveSHA512] = -36;
252
+ coseAlgorithmsBySignAlgorithm[SECSign.Algorithm.rsaSHA256] = SECCOSE.Algorithm.rsaSHA256;
253
+ coseAlgorithmsBySignAlgorithm[SECSign.Algorithm.rsaSHA384] = SECCOSE.Algorithm.rsaSHA384;
254
+ coseAlgorithmsBySignAlgorithm[SECSign.Algorithm.rsaSHA512] = SECCOSE.Algorithm.rsaSHA512;
255
+ coseAlgorithmsBySignAlgorithm[SECSign.Algorithm.ellipticCurveSHA256] = SECCOSE.Algorithm.ellipticCurveSHA256;
256
+ coseAlgorithmsBySignAlgorithm[SECSign.Algorithm.ellipticCurveSHA384] = SECCOSE.Algorithm.ellipticCurveSHA384;
257
+ coseAlgorithmsBySignAlgorithm[SECSign.Algorithm.ellipticCurveSHA512] = SECCOSE.Algorithm.ellipticCurveSHA512;
254
258
 
255
- var remap = function(dictionary, keyMap){
256
- var copy = {};
257
- for (var k in dictionary){
258
- copy[keyMap[k] || k] = dictionary[k];
259
+ if (window.PublicKeyCredential){
260
+
261
+ if (!window.PublicKeyCredential.prototype.toJSON){
262
+ window.PublicKeyCredential.prototype.toJSON = function PublicKeyCredential_toJSON(){
263
+ var dictionary = {};
264
+ dictionary.id = this.id;
265
+ dictionary.rawId = JSData.initWithBuffer(this.rawId).base64URLStringRepresentation();
266
+ dictionary.authenticatorAttachment = this.authenticatorAttachment || "";
267
+ dictionary.type = this.type || "public-key";
268
+ dictionary.clientExtensionResults = this.getClientExtensionResults ? this.getClientExtensionResults() : {};
269
+ dictionary.response = this.response.toJSON ? this.response.toJSON() : {};
270
+ return dictionary;
271
+ };
259
272
  }
260
- return copy;
261
- };
262
273
 
263
- var jwkForCoseKey = function(coseKey, kid){
264
- coseKey = remap(coseKey, {
265
- "1": "kty",
266
- "2": "kid",
267
- "3": "alg",
268
- "-1": "crv",
269
- "-2": "x",
270
- "-3": "y",
271
- "-4": "d"
272
- });
273
- var jwk = {
274
- kid: kid,
275
- key_ops: ["verify"]
276
- };
277
- if (coseKey.kty == 2){
278
- jwk.kty = SECJSONWebAlgorithms.KeyType.ellipticCurve;
279
- switch (coseKey.alg){
280
- case -7:
281
- jwk.alg = SECJSONWebAlgorithms.Algorithm.ellipticCurveSHA256;
282
- break;
283
- case -35:
284
- jwk.alg = SECJSONWebAlgorithms.Algorithm.ellipticCurveSHA384;
285
- break;
286
- case -36:
287
- jwk.alg = SECJSONWebAlgorithms.Algorithm.ellipticCurveSHA512;
288
- break;
289
- default:
290
- return null;
291
- }
292
- switch (coseKey.crv){
293
- case 1:
294
- jwk.crv = "P-256";
295
- break;
296
- case 2:
297
- jwk.crv = "P-384";
298
- break;
299
- case 3:
300
- jwk.crv = "P-512";
301
- break;
302
- default:
303
- return null;
304
- }
305
- jwk.x = coseKey.x.base64URLStringRepresentation();
306
- jwk.y = coseKey.y.base64URLStringRepresentation();
307
- return jwk;
274
+ }
275
+
276
+ if (window.AuthenticatorAttestationResponse){
277
+
278
+ if (!window.AuthenticatorAttestationResponse.prototype.getAuthenticatorData){
279
+ window.AuthenticatorAttestationResponse.prototype.getAuthenticatorData = function AuthenticatorAttestationResponse_getAuthenticatorData(){
280
+ if (this._jskitAuthDataBuffer === undefined){
281
+ var attestationCBOR = JSData.initWithBuffer(this.attestationObject);
282
+ var attestationParser = SECCBORParser.initWithData(attestationCBOR);
283
+ var attestation = attestationParser.parse();
284
+ var data = attestation.authData;
285
+ this._authDataBuffer = data.buffer.slice(data.byteOffset, data.byteOffset + data.length);
286
+ }
287
+ return this._authDataBuffer;
288
+ };
308
289
  }
309
- if (coseKey.kty == 0){ // RSA
310
- jwk.kty = SECJSONWebAlgorithms.KeyType.rsa;
311
- switch (coseKey.alg){
312
- case -257:
313
- jwk.alg = SECJSONWebAlgorithms.Algorithm.rsaSHA256;
314
- break;
315
- case -258:
316
- jwk.alg = SECJSONWebAlgorithms.Algorithm.rsaSHA384;
317
- break;
318
- case -259:
319
- jwk.alg = SECJSONWebAlgorithms.Algorithm.rsaSHA512;
320
- break;
321
- default:
322
- return null;
323
- }
324
- // TODO: jwk.n, jwk.e
325
- return jwk;
290
+
291
+ if (!window.AuthenticatorAttestationResponse.prototype.jskitGetCOSE){
292
+ window.AuthenticatorAttestationResponse.prototype.jskitGetCOSE = function jskitGuthenticatorAttestationResponse_getCOSEDictionary(){
293
+ if (this._jskitCOSE === undefined){
294
+ var authData = JSData.initWithBuffer(this.getAuthenticatorData());
295
+ var idLength = (authData[53] << 8) | authData[54];
296
+ var offset = 55 + idLength;
297
+ this._jskitCOSE = SECCOSE.initWithData(authData.subdataInRange(JSRange(offset, authData.length - offset)));
298
+ }
299
+ return this._jskitCOSE;
300
+ };
301
+ }
302
+
303
+ if (!window.AuthenticatorAttestationResponse.prototype.getPublicKeyAlgorithm){
304
+ window.AuthenticatorAttestationResponse.prototype.getPublicKeyAlgorithm = function AuthenticatorAttestationResponse_getPublicKeyAlgorithm(){
305
+ var cose = this.jskitGetCOSE();
306
+ return cose[SECCOSE.Attribute.alg];
307
+ };
308
+ }
309
+
310
+ if (!window.AuthenticatorAttestationResponse.prototype.getPublicKey){
311
+ window.AuthenticatorAttestationResponse.prototype.getPublicKey = function AuthenticatorAttestationResponse_getPublicKey(){
312
+ var cose = this.jskitGetCOSE();
313
+ var derData = cose.derRepresentation();
314
+ return derData.buffer.slice(derData.byteOffset, derData.byteOffset + derData.length);
315
+ };
316
+ }
317
+
318
+ if (!window.AuthenticatorAttestationResponse.prototype.getPublicJWK){
319
+ window.AuthenticatorAttestationResponse.prototype.getPublicJWK = function AuthenticatorAttestationResponse_getPublicJWK(){
320
+ var cose = this.jskitGetCOSE();
321
+ var jwk = cose.jwkRepresentation();
322
+ var authData = JSData.initWithBuffer(this.getAuthenticatorData());
323
+ var idLength = (authData[53] << 8) | authData[54];
324
+ var idData = authData.subdataInRange(JSRange(55, idLength));
325
+ jwk.kid = idData.base64URLStringRepresentation();
326
+ jwk.key_ops = ["verify"];
327
+ return jwk;
328
+ };
329
+ }
330
+
331
+ if (!window.AuthenticatorAttestationResponse.prototype.toJSON){
332
+ window.AuthenticatorAttestationResponse.prototype.toJSON = function AuthenticatorAttestationResponse_toJSON(){
333
+ var attestationObjectData = JSData.initWithBuffer(this.attestationObject);
334
+ var authData = JSData.initWithBuffer(this.getAuthenticatorData());
335
+ var dictionary = {};
336
+ dictionary.clientDataJSON = JSData.initWithBuffer(this.clientDataJSON).base64URLStringRepresentation();
337
+ dictionary.authenticatorData = authData.base64URLStringRepresentation();
338
+ dictionary.transports = this.getTransports ? this.getTransports() : [];
339
+ dictionary.publicKey = JSData.initWithBuffer(this.getPublicKey()).base64URLStringRepresentation();
340
+ dictionary.publicKeyAlgorithm = this.getPublicKeyAlgorithm();
341
+ dictionary.attestationObject = attestationObjectData.base64URLStringRepresentation();
342
+ return dictionary;
343
+ };
344
+ }
345
+
346
+ }
347
+
348
+ if (window.AuthenticatorAssertionResponse){
349
+
350
+ if (!window.AuthenticatorAssertionResponse.prototype.toJSON){
351
+ window.AuthenticatorAssertionResponse.prototype.toJSON = function AuthenticatorAssertionResponse_toJSON(){
352
+ var dictionary = {};
353
+ dictionary.clientDataJSON = JSData.initWithBuffer(this.clientDataJSON).base64URLStringRepresentation();
354
+ dictionary.authenticatorData = JSData.initWithBuffer(this.authenticatorData).base64URLStringRepresentation();
355
+ dictionary.signature = JSData.initWithBuffer(this.signature).base64URLStringRepresentation();
356
+ dictionary.userHandle = this.userHandle ? JSData.initWithBuffer(this.userHandle).base64URLStringRepresentation() : null;
357
+ return dictionary;
358
+ };
326
359
  }
327
- return null;
328
- };
360
+
361
+ }
329
362
 
330
363
  })();
@@ -24,6 +24,7 @@ JSClass("SECHTMLKey", SECKey, {
24
24
 
25
25
  initWithKey: function(htmlKey){
26
26
  this.htmlKey = htmlKey;
27
+ this.type = htmlKey.type;
27
28
  },
28
29
 
29
30
  getData: function(completion, target){
@@ -36,6 +37,22 @@ JSClass("SECHTMLKey", SECKey, {
36
37
  completion.call(target, null);
37
38
  });
38
39
  return completion.promise;
40
+ },
41
+
42
+ getJWK: function(completion, target){
43
+ if (!completion){
44
+ completion = Promise.completion(Promise.resolveNonNull);
45
+ }
46
+ var kid = this.id;
47
+ crypto.subtle.exportKey("jwk", this.htmlKey).then(function(jwk){
48
+ if (kid !== null){
49
+ jwk.kid = kid;
50
+ }
51
+ completion.call(target, jwk);
52
+ }, function(){
53
+ completion.call(target, null);
54
+ });
55
+ return completion.promise;
39
56
  }
40
57
 
41
58
  });
@@ -30,6 +30,7 @@ JSClass("SECHash", JSObject, {
30
30
  });
31
31
 
32
32
  SECHash.Algorithm = {
33
+ sha1: "sha1",
33
34
  sha256: "sha256",
34
35
  sha384: "sha384",
35
36
  sha512: "sha512",
@@ -23,6 +23,7 @@ JSClass("SECJSONWebAlgorithms", JSObject, {
23
23
  SECJSONWebAlgorithms.Algorithm = {
24
24
 
25
25
  none: 'none',
26
+ direct: "dir",
26
27
  hmacSHA256: "HS256",
27
28
  hmacSHA384: "HS384",
28
29
  hmacSHA512: "HS512",
@@ -32,7 +33,14 @@ SECJSONWebAlgorithms.Algorithm = {
32
33
  ellipticCurveSHA256: "ES256",
33
34
  ellipticCurveSHA384: "ES384",
34
35
  ellipticCurveSHA512: "ES512",
35
-
36
+ aesGCM128: "A128GCM",
37
+ aesGCM192: "A192GCM",
38
+ aesGCM256: "A256GCM",
39
+ aesCBC128HS256: "A128CBC-HS256",
40
+ aesCBC192HS384: "A192CBC-HS384",
41
+ aesCBC256HS512: "A256CBC-HS512",
42
+ rsaOAEP: "RSA-OAEP",
43
+ ecdhES: "ECDH-ES"
36
44
  };
37
45
 
38
46
  SECJSONWebAlgorithms.KeyType = {