@breakside/jskit 2024.34.0 → 2024.41.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.
- package/Frameworks/DOM.jsframework/Info.json +2 -2
- package/Frameworks/DOM.jsframework/io.breakside.JSKit.DOM-bundle.js +2 -2
- package/Frameworks/FontKit.jsframework/Info.json +2 -2
- package/Frameworks/FontKit.jsframework/io.breakside.JSKit.FontKit-bundle.js +2 -2
- package/Frameworks/Foundation.jsframework/Info.json +2 -2
- package/Frameworks/Foundation.jsframework/JS/Foundation+HTML.js +3 -1
- package/Frameworks/Foundation.jsframework/JS/JSClass.js +4 -1
- package/Frameworks/Foundation.jsframework/JS/JSHTMLUserAgent.js +130 -0
- package/Frameworks/Foundation.jsframework/JS/JSNodeURLSessionStreamTask.js +1 -1
- package/Frameworks/Foundation.jsframework/io.breakside.JSKit.Foundation-bundle.js +2 -2
- package/Frameworks/Foundation.jsframework/sources.json +3 -1
- package/Frameworks/SecurityKit.jsframework/Info.json +2 -2
- package/Frameworks/SecurityKit.jsframework/JS/SECCBOR.js +4 -0
- package/Frameworks/SecurityKit.jsframework/JS/SECCOSE.js +135 -0
- package/Frameworks/SecurityKit.jsframework/JS/SECCipher+HTML.js +231 -70
- package/Frameworks/SecurityKit.jsframework/JS/SECCipher+Node.js +155 -60
- package/Frameworks/SecurityKit.jsframework/JS/SECCipher.js +125 -54
- package/Frameworks/SecurityKit.jsframework/JS/SECDataKey.js +5 -4
- package/Frameworks/SecurityKit.jsframework/JS/SECHMAC+HTML.js +15 -11
- package/Frameworks/SecurityKit.jsframework/JS/SECHMAC+Node.js +17 -3
- package/Frameworks/SecurityKit.jsframework/JS/SECHTMLDeviceAuthentication.js +206 -120
- package/Frameworks/SecurityKit.jsframework/JS/SECHTMLKey.js +17 -0
- package/Frameworks/SecurityKit.jsframework/JS/SECHash.js +1 -0
- package/Frameworks/SecurityKit.jsframework/JS/SECJSONWebAlgorithms.js +9 -1
- package/Frameworks/SecurityKit.jsframework/JS/SECJSONWebEncryption.js +391 -0
- package/Frameworks/SecurityKit.jsframework/JS/SECJSONWebToken.js +1 -1
- package/Frameworks/SecurityKit.jsframework/JS/SECKey.js +14 -1
- package/Frameworks/SecurityKit.jsframework/JS/SECNodeKey.js +66 -1
- package/Frameworks/SecurityKit.jsframework/JS/SECSign+HTML.js +2 -27
- package/Frameworks/SecurityKit.jsframework/JS/SECSign+Node.js +103 -278
- package/Frameworks/SecurityKit.jsframework/JS/SECSign.js +27 -0
- package/Frameworks/SecurityKit.jsframework/JS/SECVerify+Node.js +60 -57
- package/Frameworks/SecurityKit.jsframework/JS/SecurityKit.js +1 -0
- package/Frameworks/SecurityKit.jsframework/io.breakside.JSKit.SecurityKit-bundle.js +2 -2
- package/Frameworks/SecurityKit.jsframework/sources.json +6 -0
- package/Info.json +2 -2
- package/Node/KeyCommand.js +8 -1
- package/Node/io.breakside.jskit-bundle.js +2 -2
- package/Node/jskit +1 -0
- package/Root/Frameworks/APIKit/Info.yaml +1 -1
- package/Root/Frameworks/APIKitTesting/Info.yaml +1 -1
- package/Root/Frameworks/AuthKit/Info.yaml +1 -1
- package/Root/Frameworks/CSSOM/Info.yaml +1 -1
- package/Root/Frameworks/ChartKit/Info.yaml +1 -1
- package/Root/Frameworks/ConferenceKit/Info.yaml +1 -1
- package/Root/Frameworks/DBKit/DBEncryptedObject.js +2 -2
- package/Root/Frameworks/DBKit/Info.yaml +1 -1
- package/Root/Frameworks/DOM/Info.yaml +1 -1
- package/Root/Frameworks/Dispatch/Info.yaml +1 -1
- package/Root/Frameworks/FontKit/Info.yaml +1 -1
- package/Root/Frameworks/Foundation/Foundation+HTML.js +3 -1
- package/Root/Frameworks/Foundation/Info.yaml +1 -1
- package/Root/Frameworks/Foundation/JSClass.js +4 -1
- package/Root/Frameworks/Foundation/JSHTMLUserAgent.js +130 -0
- package/Root/Frameworks/Foundation/JSNodeURLSessionStreamTask.js +1 -1
- package/Root/Frameworks/ImageKit/Info.yaml +1 -1
- package/Root/Frameworks/MediaKit/Info.yaml +1 -1
- package/Root/Frameworks/MediaKitUI/Info.yaml +1 -1
- package/Root/Frameworks/NotificationKit/Info.yaml +1 -1
- package/Root/Frameworks/NotificationKit/NKWebPushService.js +2 -2
- package/Root/Frameworks/PDFKit/Info.yaml +1 -1
- package/Root/Frameworks/PDFKit/PDFEncryption.js +1 -1
- package/Root/Frameworks/QRKit/Info.yaml +1 -1
- package/Root/Frameworks/SearchKit/Info.yaml +1 -1
- package/Root/Frameworks/SecurityKit/Info.yaml +1 -1
- package/Root/Frameworks/SecurityKit/SECCBOR.js +4 -0
- package/Root/Frameworks/SecurityKit/SECCOSE.js +135 -0
- package/Root/Frameworks/SecurityKit/SECCipher+HTML.js +231 -70
- package/Root/Frameworks/SecurityKit/SECCipher+Node.js +155 -60
- package/Root/Frameworks/SecurityKit/SECCipher.js +125 -54
- package/Root/Frameworks/SecurityKit/SECDataKey.js +5 -4
- package/Root/Frameworks/SecurityKit/SECHMAC+HTML.js +15 -11
- package/Root/Frameworks/SecurityKit/SECHMAC+Node.js +17 -3
- package/Root/Frameworks/SecurityKit/SECHTMLDeviceAuthentication.js +206 -120
- package/Root/Frameworks/SecurityKit/SECHTMLKey.js +17 -0
- package/Root/Frameworks/SecurityKit/SECHash.js +1 -0
- package/Root/Frameworks/SecurityKit/SECJSONWebAlgorithms.js +9 -1
- package/Root/Frameworks/SecurityKit/SECJSONWebEncryption.js +391 -0
- package/Root/Frameworks/SecurityKit/SECJSONWebToken.js +1 -1
- package/Root/Frameworks/SecurityKit/SECKey.js +14 -1
- package/Root/Frameworks/SecurityKit/SECNodeKey.js +66 -1
- package/Root/Frameworks/SecurityKit/SECSign+HTML.js +2 -27
- package/Root/Frameworks/SecurityKit/SECSign+Node.js +103 -278
- package/Root/Frameworks/SecurityKit/SECSign.js +27 -0
- package/Root/Frameworks/SecurityKit/SECVerify+Node.js +60 -57
- package/Root/Frameworks/SecurityKit/SecurityKit.js +1 -0
- package/Root/Frameworks/ServerKit/Info.yaml +1 -1
- package/Root/Frameworks/ServerKitTesting/Info.yaml +1 -1
- package/Root/Frameworks/TestKit/Info.yaml +1 -1
- package/Root/Frameworks/UIKit/Info.yaml +1 -1
- package/Root/Frameworks/UIKit/UIPlatform+HTML.js +2 -1
- package/Root/Frameworks/UIKitTesting/Info.yaml +1 -1
- package/package.json +1 -1
- 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
|
-
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
77
|
+
this.nodeHash = crypto.createHmac(this.nodeAlgorithm, this.key.nodeKeyObject);
|
|
64
78
|
}
|
|
65
79
|
this.nodeHash.update(data);
|
|
66
80
|
},
|
|
@@ -13,12 +13,13 @@
|
|
|
13
13
|
// See the License for the specific language governing permissions and
|
|
14
14
|
// limitations under the License.
|
|
15
15
|
|
|
16
|
+
// #import Foundation
|
|
16
17
|
// #import "SECDeviceAuthentication.js"
|
|
17
18
|
// #import "SECCipher.js"
|
|
18
19
|
// #import "SECSign.js"
|
|
19
20
|
// #import "SECCBOR.js"
|
|
20
21
|
// #import "SECHash.js"
|
|
21
|
-
// #import "
|
|
22
|
+
// #import "SECCOSE.js"
|
|
22
23
|
// jshint browser: true
|
|
23
24
|
/* global AuthenticatorAttestationResponse */
|
|
24
25
|
'use strict';
|
|
@@ -66,12 +67,13 @@ JSClass("SECHTMLDeviceAuthentication", JSObject, {
|
|
|
66
67
|
// challengeData
|
|
67
68
|
// supportedAlgorithms
|
|
68
69
|
// platform
|
|
70
|
+
// conditional
|
|
69
71
|
if (!completion){
|
|
70
72
|
completion = Promise.completion();
|
|
71
73
|
}
|
|
72
74
|
if (this.credentialStore === null){
|
|
73
75
|
JSRunLoop.main.schedule(completion, target, null);
|
|
74
|
-
return;
|
|
76
|
+
return completion.promise;
|
|
75
77
|
}
|
|
76
78
|
registration = JSCopy(registration);
|
|
77
79
|
if (!registration.providerName){
|
|
@@ -98,21 +100,19 @@ JSClass("SECHTMLDeviceAuthentication", JSObject, {
|
|
|
98
100
|
challenge: registration.challengeData,
|
|
99
101
|
pubKeyCredParams: [],
|
|
100
102
|
authenticatorSelection: {
|
|
101
|
-
//
|
|
102
|
-
//
|
|
103
|
-
//
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
// provide so we can lookup allowed key IDs on a server and send them back to
|
|
108
|
-
// the client before authenticating
|
|
109
|
-
requireResidentKey: false,
|
|
110
|
-
residentKey: "discouraged",
|
|
111
|
-
userVerification: registration.platform ? "required" : "discouraged",
|
|
103
|
+
// requiring a resident key is necessary for Android to
|
|
104
|
+
// actually save a passkey. Apple OSes will save a passkey
|
|
105
|
+
// regardless of resident key settings
|
|
106
|
+
requireResidentKey: registration.platform ? true : false,
|
|
107
|
+
residentKey: registration.platform ? "required" : "discouraged",
|
|
108
|
+
userVerification: registration.platform && !registration.conditional ? "required" : "discouraged",
|
|
112
109
|
authenticatorAttachment: registration.platform ? "platform" : "cross-platform"
|
|
113
110
|
},
|
|
114
111
|
attestation: "none",
|
|
115
|
-
timeout:
|
|
112
|
+
timeout: 60000,
|
|
113
|
+
extensions: {
|
|
114
|
+
credProps: true
|
|
115
|
+
}
|
|
116
116
|
};
|
|
117
117
|
if (registration.domain !== undefined){
|
|
118
118
|
info.rp.id = registration.domain;
|
|
@@ -132,34 +132,43 @@ JSClass("SECHTMLDeviceAuthentication", JSObject, {
|
|
|
132
132
|
];
|
|
133
133
|
}
|
|
134
134
|
var credentials = this.credentialStore;
|
|
135
|
-
|
|
135
|
+
var handleCredential = function(credential){
|
|
136
136
|
if (!credential || credential.type != "public-key"){
|
|
137
137
|
completion.call(target, null);
|
|
138
138
|
return;
|
|
139
139
|
}
|
|
140
|
-
var
|
|
141
|
-
var
|
|
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);
|
|
140
|
+
var jwk = credential.response.getPublicJWK();
|
|
141
|
+
var webauthn = credential.toJSON();
|
|
151
142
|
var result = {
|
|
143
|
+
name: credential.jskitName,
|
|
152
144
|
jwk: jwk,
|
|
153
|
-
|
|
154
|
-
|
|
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
|
-
}
|
|
161
|
-
|
|
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
|
|
|
@@ -178,9 +187,9 @@ JSClass("SECHTMLDeviceAuthentication", JSObject, {
|
|
|
178
187
|
}
|
|
179
188
|
var info = {
|
|
180
189
|
challenge: request.challengeData,
|
|
181
|
-
userVerification: "discouraged",
|
|
182
|
-
timeout:
|
|
183
|
-
allowCredentials: []
|
|
190
|
+
userVerification: request.platform ? "required" : "discouraged",
|
|
191
|
+
timeout: 60000,
|
|
192
|
+
allowCredentials: [],
|
|
184
193
|
};
|
|
185
194
|
if (request.domain){
|
|
186
195
|
info.rpId = request.domain;
|
|
@@ -198,7 +207,7 @@ JSClass("SECHTMLDeviceAuthentication", JSObject, {
|
|
|
198
207
|
id: request.allowedKeyIDs[i].dataByDecodingBase64URL()
|
|
199
208
|
};
|
|
200
209
|
if (request.platform){
|
|
201
|
-
allowedCredential.transports = ["internal"];
|
|
210
|
+
allowedCredential.transports = ["internal", "hybrid"];
|
|
202
211
|
}
|
|
203
212
|
info.allowCredentials.push(allowedCredential);
|
|
204
213
|
}catch (e){
|
|
@@ -212,15 +221,10 @@ JSClass("SECHTMLDeviceAuthentication", JSObject, {
|
|
|
212
221
|
completion.call(target, null);
|
|
213
222
|
return;
|
|
214
223
|
}
|
|
215
|
-
var
|
|
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,168 @@ Object.defineProperties(SECDeviceAuthentication, {
|
|
|
245
249
|
});
|
|
246
250
|
|
|
247
251
|
var coseAlgorithmsBySignAlgorithm = {};
|
|
248
|
-
coseAlgorithmsBySignAlgorithm[SECSign.Algorithm.rsaSHA256] =
|
|
249
|
-
coseAlgorithmsBySignAlgorithm[SECSign.Algorithm.rsaSHA384] =
|
|
250
|
-
coseAlgorithmsBySignAlgorithm[SECSign.Algorithm.rsaSHA512] =
|
|
251
|
-
coseAlgorithmsBySignAlgorithm[SECSign.Algorithm.ellipticCurveSHA256] =
|
|
252
|
-
coseAlgorithmsBySignAlgorithm[SECSign.Algorithm.ellipticCurveSHA384] =
|
|
253
|
-
coseAlgorithmsBySignAlgorithm[SECSign.Algorithm.ellipticCurveSHA512] =
|
|
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;
|
|
258
|
+
|
|
259
|
+
if (window.PublicKeyCredential){
|
|
254
260
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
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();
|
|
269
|
+
dictionary.response = this.response.toJSON ? this.response.toJSON() : {};
|
|
270
|
+
return dictionary;
|
|
271
|
+
};
|
|
259
272
|
}
|
|
260
|
-
return copy;
|
|
261
|
-
};
|
|
262
273
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
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
|
+
if (!window.PublicKeyCredential.prototype.getClientExtensionResults){
|
|
275
|
+
window.PublicKeyCredential.prototype.getClientExtensionResults = function PublicKeyCredential_getClientExtensionResults(){
|
|
276
|
+
if (this._clientExtensionResults === undefined){
|
|
277
|
+
var authData = JSData.initWithBuffer(this.getAuthenticatorData());
|
|
278
|
+
var idLength = (authData[53] << 8) | authData[54];
|
|
279
|
+
var offset = 55 + idLength;
|
|
280
|
+
var cbor = SECCBORParser.initWithData(authData.subdataInRange(JSRange(offset, authData.length - offset)));
|
|
281
|
+
var coseKey = cbor.readNext(); // ingored, only reading to arrive at the extensions start location
|
|
282
|
+
this._clientExtensionResults = cbor.readNext() || {};
|
|
283
|
+
}
|
|
284
|
+
return this._clientExtensionResults;
|
|
285
|
+
};
|
|
308
286
|
}
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
287
|
+
|
|
288
|
+
Object.defineProperties(window.PublicKeyCredential.prototype, {
|
|
289
|
+
jskitName: {
|
|
290
|
+
enumerable: false,
|
|
291
|
+
configurable: false,
|
|
292
|
+
get: function PublicKeyCredential_getJSKitName(){
|
|
293
|
+
var extensions = this.getClientExtensionResults();
|
|
294
|
+
if (extensions.credProps){
|
|
295
|
+
if (extensions.credProps.authenticatorDisplayName){
|
|
296
|
+
return extensions.credProps.authenticatorDisplayName;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
var ua = JSHTMLUserAgent.initWithString(navigator.userAgent);
|
|
300
|
+
var apple = ua.containsComment("Macintosh") || ua.containsComment("iPhone") || ua.containsComment("iPad");
|
|
301
|
+
var windows = ua.containsComment("Win64") || ua.containsComment("Windows NT 10.0");
|
|
302
|
+
var linux = ua.containsComment("Linux");
|
|
303
|
+
var android = false;
|
|
304
|
+
if (linux){
|
|
305
|
+
var i, l;
|
|
306
|
+
for (i = 0, l = ua.comments.length; i < l; ++i){
|
|
307
|
+
if (ua.comments[i].startsWith("Android")){
|
|
308
|
+
android = true;
|
|
309
|
+
break;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
if (apple){
|
|
314
|
+
return "iCloud Keychain";
|
|
315
|
+
}
|
|
316
|
+
if (android){
|
|
317
|
+
return "Google Password Manager";
|
|
318
|
+
}
|
|
319
|
+
if (windows){
|
|
320
|
+
return "Windows Hello";
|
|
321
|
+
}
|
|
322
|
+
return "";
|
|
323
|
+
}
|
|
323
324
|
}
|
|
324
|
-
|
|
325
|
-
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
if (window.AuthenticatorAttestationResponse){
|
|
330
|
+
|
|
331
|
+
if (!window.AuthenticatorAttestationResponse.prototype.getAuthenticatorData){
|
|
332
|
+
window.AuthenticatorAttestationResponse.prototype.getAuthenticatorData = function AuthenticatorAttestationResponse_getAuthenticatorData(){
|
|
333
|
+
if (this._jskitAuthDataBuffer === undefined){
|
|
334
|
+
var attestationCBOR = JSData.initWithBuffer(this.attestationObject);
|
|
335
|
+
var attestationParser = SECCBORParser.initWithData(attestationCBOR);
|
|
336
|
+
var attestation = attestationParser.parse();
|
|
337
|
+
var data = attestation.authData;
|
|
338
|
+
this._authDataBuffer = data.buffer.slice(data.byteOffset, data.byteOffset + data.length);
|
|
339
|
+
}
|
|
340
|
+
return this._authDataBuffer;
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
if (!window.AuthenticatorAttestationResponse.prototype.jskitGetCOSE){
|
|
345
|
+
window.AuthenticatorAttestationResponse.prototype.jskitGetCOSE = function jskitGuthenticatorAttestationResponse_getCOSEDictionary(){
|
|
346
|
+
if (this._jskitCOSE === undefined){
|
|
347
|
+
var authData = JSData.initWithBuffer(this.getAuthenticatorData());
|
|
348
|
+
var idLength = (authData[53] << 8) | authData[54];
|
|
349
|
+
var offset = 55 + idLength;
|
|
350
|
+
this._jskitCOSE = SECCOSE.initWithData(authData.subdataInRange(JSRange(offset, authData.length - offset)));
|
|
351
|
+
}
|
|
352
|
+
return this._jskitCOSE;
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
if (!window.AuthenticatorAttestationResponse.prototype.getPublicKeyAlgorithm){
|
|
357
|
+
window.AuthenticatorAttestationResponse.prototype.getPublicKeyAlgorithm = function AuthenticatorAttestationResponse_getPublicKeyAlgorithm(){
|
|
358
|
+
var cose = this.jskitGetCOSE();
|
|
359
|
+
return cose[SECCOSE.Attribute.alg];
|
|
360
|
+
};
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
if (!window.AuthenticatorAttestationResponse.prototype.getPublicKey){
|
|
364
|
+
window.AuthenticatorAttestationResponse.prototype.getPublicKey = function AuthenticatorAttestationResponse_getPublicKey(){
|
|
365
|
+
var cose = this.jskitGetCOSE();
|
|
366
|
+
var derData = cose.derRepresentation();
|
|
367
|
+
return derData.buffer.slice(derData.byteOffset, derData.byteOffset + derData.length);
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
if (!window.AuthenticatorAttestationResponse.prototype.getPublicJWK){
|
|
372
|
+
window.AuthenticatorAttestationResponse.prototype.getPublicJWK = function AuthenticatorAttestationResponse_getPublicJWK(){
|
|
373
|
+
var cose = this.jskitGetCOSE();
|
|
374
|
+
var jwk = cose.jwkRepresentation();
|
|
375
|
+
var authData = JSData.initWithBuffer(this.getAuthenticatorData());
|
|
376
|
+
var idLength = (authData[53] << 8) | authData[54];
|
|
377
|
+
var idData = authData.subdataInRange(JSRange(55, idLength));
|
|
378
|
+
jwk.kid = idData.base64URLStringRepresentation();
|
|
379
|
+
jwk.key_ops = ["verify"];
|
|
380
|
+
return jwk;
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
if (!window.AuthenticatorAttestationResponse.prototype.toJSON){
|
|
385
|
+
window.AuthenticatorAttestationResponse.prototype.toJSON = function AuthenticatorAttestationResponse_toJSON(){
|
|
386
|
+
var attestationObjectData = JSData.initWithBuffer(this.attestationObject);
|
|
387
|
+
var authData = JSData.initWithBuffer(this.getAuthenticatorData());
|
|
388
|
+
var dictionary = {};
|
|
389
|
+
dictionary.clientDataJSON = JSData.initWithBuffer(this.clientDataJSON).base64URLStringRepresentation();
|
|
390
|
+
dictionary.authenticatorData = authData.base64URLStringRepresentation();
|
|
391
|
+
dictionary.transports = this.getTransports ? this.getTransports() : [];
|
|
392
|
+
dictionary.publicKey = JSData.initWithBuffer(this.getPublicKey()).base64URLStringRepresentation();
|
|
393
|
+
dictionary.publicKeyAlgorithm = this.getPublicKeyAlgorithm();
|
|
394
|
+
dictionary.attestationObject = attestationObjectData.base64URLStringRepresentation();
|
|
395
|
+
return dictionary;
|
|
396
|
+
};
|
|
326
397
|
}
|
|
327
|
-
|
|
328
|
-
}
|
|
398
|
+
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
if (window.AuthenticatorAssertionResponse){
|
|
402
|
+
|
|
403
|
+
if (!window.AuthenticatorAssertionResponse.prototype.toJSON){
|
|
404
|
+
window.AuthenticatorAssertionResponse.prototype.toJSON = function AuthenticatorAssertionResponse_toJSON(){
|
|
405
|
+
var dictionary = {};
|
|
406
|
+
dictionary.clientDataJSON = JSData.initWithBuffer(this.clientDataJSON).base64URLStringRepresentation();
|
|
407
|
+
dictionary.authenticatorData = JSData.initWithBuffer(this.authenticatorData).base64URLStringRepresentation();
|
|
408
|
+
dictionary.signature = JSData.initWithBuffer(this.signature).base64URLStringRepresentation();
|
|
409
|
+
dictionary.userHandle = this.userHandle ? JSData.initWithBuffer(this.userHandle).base64URLStringRepresentation() : null;
|
|
410
|
+
return dictionary;
|
|
411
|
+
};
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
}
|
|
329
415
|
|
|
330
416
|
})();
|
|
@@ -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
|
});
|
|
@@ -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 = {
|