@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.
Files changed (94) 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/Foundation+HTML.js +3 -1
  7. package/Frameworks/Foundation.jsframework/JS/JSClass.js +4 -1
  8. package/Frameworks/Foundation.jsframework/JS/JSHTMLUserAgent.js +130 -0
  9. package/Frameworks/Foundation.jsframework/JS/JSNodeURLSessionStreamTask.js +1 -1
  10. package/Frameworks/Foundation.jsframework/io.breakside.JSKit.Foundation-bundle.js +2 -2
  11. package/Frameworks/Foundation.jsframework/sources.json +3 -1
  12. package/Frameworks/SecurityKit.jsframework/Info.json +2 -2
  13. package/Frameworks/SecurityKit.jsframework/JS/SECCBOR.js +4 -0
  14. package/Frameworks/SecurityKit.jsframework/JS/SECCOSE.js +135 -0
  15. package/Frameworks/SecurityKit.jsframework/JS/SECCipher+HTML.js +231 -70
  16. package/Frameworks/SecurityKit.jsframework/JS/SECCipher+Node.js +155 -60
  17. package/Frameworks/SecurityKit.jsframework/JS/SECCipher.js +125 -54
  18. package/Frameworks/SecurityKit.jsframework/JS/SECDataKey.js +5 -4
  19. package/Frameworks/SecurityKit.jsframework/JS/SECHMAC+HTML.js +15 -11
  20. package/Frameworks/SecurityKit.jsframework/JS/SECHMAC+Node.js +17 -3
  21. package/Frameworks/SecurityKit.jsframework/JS/SECHTMLDeviceAuthentication.js +206 -120
  22. package/Frameworks/SecurityKit.jsframework/JS/SECHTMLKey.js +17 -0
  23. package/Frameworks/SecurityKit.jsframework/JS/SECHash.js +1 -0
  24. package/Frameworks/SecurityKit.jsframework/JS/SECJSONWebAlgorithms.js +9 -1
  25. package/Frameworks/SecurityKit.jsframework/JS/SECJSONWebEncryption.js +391 -0
  26. package/Frameworks/SecurityKit.jsframework/JS/SECJSONWebToken.js +1 -1
  27. package/Frameworks/SecurityKit.jsframework/JS/SECKey.js +14 -1
  28. package/Frameworks/SecurityKit.jsframework/JS/SECNodeKey.js +66 -1
  29. package/Frameworks/SecurityKit.jsframework/JS/SECSign+HTML.js +2 -27
  30. package/Frameworks/SecurityKit.jsframework/JS/SECSign+Node.js +103 -278
  31. package/Frameworks/SecurityKit.jsframework/JS/SECSign.js +27 -0
  32. package/Frameworks/SecurityKit.jsframework/JS/SECVerify+Node.js +60 -57
  33. package/Frameworks/SecurityKit.jsframework/JS/SecurityKit.js +1 -0
  34. package/Frameworks/SecurityKit.jsframework/io.breakside.JSKit.SecurityKit-bundle.js +2 -2
  35. package/Frameworks/SecurityKit.jsframework/sources.json +6 -0
  36. package/Info.json +2 -2
  37. package/Node/KeyCommand.js +8 -1
  38. package/Node/io.breakside.jskit-bundle.js +2 -2
  39. package/Node/jskit +1 -0
  40. package/Root/Frameworks/APIKit/Info.yaml +1 -1
  41. package/Root/Frameworks/APIKitTesting/Info.yaml +1 -1
  42. package/Root/Frameworks/AuthKit/Info.yaml +1 -1
  43. package/Root/Frameworks/CSSOM/Info.yaml +1 -1
  44. package/Root/Frameworks/ChartKit/Info.yaml +1 -1
  45. package/Root/Frameworks/ConferenceKit/Info.yaml +1 -1
  46. package/Root/Frameworks/DBKit/DBEncryptedObject.js +2 -2
  47. package/Root/Frameworks/DBKit/Info.yaml +1 -1
  48. package/Root/Frameworks/DOM/Info.yaml +1 -1
  49. package/Root/Frameworks/Dispatch/Info.yaml +1 -1
  50. package/Root/Frameworks/FontKit/Info.yaml +1 -1
  51. package/Root/Frameworks/Foundation/Foundation+HTML.js +3 -1
  52. package/Root/Frameworks/Foundation/Info.yaml +1 -1
  53. package/Root/Frameworks/Foundation/JSClass.js +4 -1
  54. package/Root/Frameworks/Foundation/JSHTMLUserAgent.js +130 -0
  55. package/Root/Frameworks/Foundation/JSNodeURLSessionStreamTask.js +1 -1
  56. package/Root/Frameworks/ImageKit/Info.yaml +1 -1
  57. package/Root/Frameworks/MediaKit/Info.yaml +1 -1
  58. package/Root/Frameworks/MediaKitUI/Info.yaml +1 -1
  59. package/Root/Frameworks/NotificationKit/Info.yaml +1 -1
  60. package/Root/Frameworks/NotificationKit/NKWebPushService.js +2 -2
  61. package/Root/Frameworks/PDFKit/Info.yaml +1 -1
  62. package/Root/Frameworks/PDFKit/PDFEncryption.js +1 -1
  63. package/Root/Frameworks/QRKit/Info.yaml +1 -1
  64. package/Root/Frameworks/SearchKit/Info.yaml +1 -1
  65. package/Root/Frameworks/SecurityKit/Info.yaml +1 -1
  66. package/Root/Frameworks/SecurityKit/SECCBOR.js +4 -0
  67. package/Root/Frameworks/SecurityKit/SECCOSE.js +135 -0
  68. package/Root/Frameworks/SecurityKit/SECCipher+HTML.js +231 -70
  69. package/Root/Frameworks/SecurityKit/SECCipher+Node.js +155 -60
  70. package/Root/Frameworks/SecurityKit/SECCipher.js +125 -54
  71. package/Root/Frameworks/SecurityKit/SECDataKey.js +5 -4
  72. package/Root/Frameworks/SecurityKit/SECHMAC+HTML.js +15 -11
  73. package/Root/Frameworks/SecurityKit/SECHMAC+Node.js +17 -3
  74. package/Root/Frameworks/SecurityKit/SECHTMLDeviceAuthentication.js +206 -120
  75. package/Root/Frameworks/SecurityKit/SECHTMLKey.js +17 -0
  76. package/Root/Frameworks/SecurityKit/SECHash.js +1 -0
  77. package/Root/Frameworks/SecurityKit/SECJSONWebAlgorithms.js +9 -1
  78. package/Root/Frameworks/SecurityKit/SECJSONWebEncryption.js +391 -0
  79. package/Root/Frameworks/SecurityKit/SECJSONWebToken.js +1 -1
  80. package/Root/Frameworks/SecurityKit/SECKey.js +14 -1
  81. package/Root/Frameworks/SecurityKit/SECNodeKey.js +66 -1
  82. package/Root/Frameworks/SecurityKit/SECSign+HTML.js +2 -27
  83. package/Root/Frameworks/SecurityKit/SECSign+Node.js +103 -278
  84. package/Root/Frameworks/SecurityKit/SECSign.js +27 -0
  85. package/Root/Frameworks/SecurityKit/SECVerify+Node.js +60 -57
  86. package/Root/Frameworks/SecurityKit/SecurityKit.js +1 -0
  87. package/Root/Frameworks/ServerKit/Info.yaml +1 -1
  88. package/Root/Frameworks/ServerKitTesting/Info.yaml +1 -1
  89. package/Root/Frameworks/TestKit/Info.yaml +1 -1
  90. package/Root/Frameworks/UIKit/Info.yaml +1 -1
  91. package/Root/Frameworks/UIKit/UIPlatform+HTML.js +2 -1
  92. package/Root/Frameworks/UIKitTesting/Info.yaml +1 -1
  93. package/package.json +1 -1
  94. package/Root/Templates/workspace/.gitignore +0 -4
@@ -0,0 +1,391 @@
1
+ // Copyright 2020 Breakside Inc.
2
+ //
3
+ // Licensed under the Breakside Public License, Version 1.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // If a copy of the License was not distributed with this file, you may
6
+ // obtain a copy at
7
+ //
8
+ // http://breakside.io/licenses/LICENSE-1.0.txt
9
+ //
10
+ // Unless required by applicable law or agreed to in writing, software
11
+ // distributed under the License is distributed on an "AS IS" BASIS,
12
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ // See the License for the specific language governing permissions and
14
+ // limitations under the License.
15
+
16
+ // #import Foundation
17
+ // #import "SECCipher.js"
18
+ // #import "SECHMAC.js"
19
+ // #import "SECJSONWebAlgorithms.js"
20
+ 'use strict';
21
+
22
+ (function(){
23
+
24
+ JSClass("SECJSONWebEncryption", JSObject, {
25
+
26
+ initWithString: function(str){
27
+ if (str === null || str === undefined){
28
+ return null;
29
+ }
30
+ var parts = str.split('.');
31
+ if (parts.length !== 5){
32
+ return null;
33
+ }
34
+ try{
35
+ this._headerData = parts[0].dataByDecodingBase64URL();
36
+ this._header = JSON.parse(this._headerData.stringByDecodingUTF8());
37
+ this._encryptedKey = parts[1].length > 0 ? parts[1].dataByDecodingBase64URL() : null;
38
+ this._initalizationVector = parts[2].dataByDecodingBase64URL();
39
+ this._ciphertext = parts[3].dataByDecodingBase64URL();
40
+ this._authenticationTag = parts[4].dataByDecodingBase64URL();
41
+ }catch (e){
42
+ return null;
43
+ }
44
+ },
45
+
46
+ _headerData: null,
47
+ _header: null,
48
+ _encryptedKey: null,
49
+ _initalizationVector: null,
50
+ _ciphertext: null,
51
+ _authenticationTag: null,
52
+
53
+ encrypt: function(plaintext, jwk, completion, target){
54
+ if (!completion){
55
+ completion = Promise.completion(Promise.resolveNonNull);
56
+ }
57
+ this._header = {
58
+ };
59
+ this._encryptedKey = null;
60
+ this._initalizationVector = null;
61
+ this._ciphertext = null;
62
+ this._authenticationTag = null;
63
+ if (jwk.kid){
64
+ this._header.kid = jwk.kid;
65
+ }
66
+ switch (jwk.alg){
67
+ case SECJSONWebAlgorithms.Algorithm.hmacSHA256:
68
+ this._header.alg = SECJSONWebAlgorithms.Algorithm.direct;
69
+ this._header.enc = SECJSONWebAlgorithms.Algorithm.aesCBC128HS256;
70
+ this._encryptAESCBCHMAC(128, SECHMAC.Algorithm.sha256, plaintext, jwk, completion, target);
71
+ break;
72
+ case SECJSONWebAlgorithms.Algorithm.hmacSHA384:
73
+ this._header.alg = SECJSONWebAlgorithms.Algorithm.direct;
74
+ this._header.enc = SECJSONWebAlgorithms.Algorithm.aesCBC192HS384;
75
+ this._encryptAESCBCHMAC(192, SECHMAC.Algorithm.sha384, plaintext, jwk, completion, target);
76
+ break;
77
+ case SECJSONWebAlgorithms.Algorithm.hmacSHA512:
78
+ this._header.alg = SECJSONWebAlgorithms.Algorithm.direct;
79
+ this._header.enc = SECJSONWebAlgorithms.Algorithm.aesCBC256HS512;
80
+ this._encryptAESCBCHMAC(256, SECHMAC.Algorithm.sha512, plaintext, jwk, completion, target);
81
+ break;
82
+ case SECJSONWebAlgorithms.Algorithm.rsaOAEP:
83
+ this._header.alg = SECJSONWebAlgorithms.Algorithm.rsaOAEP;
84
+ this._header.enc = SECJSONWebAlgorithms.Algorithm.aesCBC256HS512;
85
+ this._encryptAESCBCHMAC(256, SECHMAC.Algorithm.sha512, plaintext, jwk, completion, target);
86
+ break;
87
+ default:
88
+ JSRunLoop.main.schedule(completion, target, null);
89
+ return completion.promise;
90
+ }
91
+ return completion.promise;
92
+ },
93
+
94
+ _encryptAESCBCHMAC: function(keyBitLength, hmacAlgorithm, plaintext, jwk, completion, target){
95
+ this._headerData = JSON.stringify(this._header).utf8();
96
+ var additionalData = this._headerData.base64URLStringRepresentation().latin1();
97
+ var contentCipher = SECCipher.initWithAlgorithm(SECCipher.Algorithm.aesCBC, {keyBitLength: keyBitLength});
98
+ var hmac = SECHMAC.initWithAlgorithm(hmacAlgorithm);
99
+ var keyCipher = null;
100
+ switch (this._header.alg){
101
+ case SECJSONWebAlgorithms.Algorithm.direct:
102
+ break;
103
+ case SECJSONWebAlgorithms.Algorithm.rsaOAEP:
104
+ keyCipher = SECCipher.initWithAlgorithm(SECCipher.Algorithm.rsaOAEP);
105
+ break;
106
+ default:
107
+ JSRunLoop.main.schedule(completion, target, null);
108
+ return;
109
+ }
110
+ var encryptContent = function(combinedKeyData){
111
+ if (combinedKeyData === null){
112
+ completion.call(target, null);
113
+ return;
114
+ }
115
+ var hkeyData = combinedKeyData.subdataInRange(JSRange(0, contentCipher.keyByteLength));
116
+ var cekData = combinedKeyData.subdataInRange(JSRange(contentCipher.keyByteLength, contentCipher.keyByteLength));
117
+ contentCipher.createKeyWithData(cekData, function(cek){
118
+ if (cek === null){
119
+ completion.call(target, null);
120
+ return;
121
+ }
122
+ contentCipher.encrypt(plaintext, cek, function(ciphertext){
123
+ if (ciphertext === null){
124
+ completion.call(target, null);
125
+ return;
126
+ }
127
+ this._initalizationVector = ciphertext.subdataInRange(JSRange(0, contentCipher.ivByteLength));
128
+ this._ciphertext = ciphertext.subdataInRange(JSRange(contentCipher.ivByteLength, ciphertext.length - contentCipher.ivByteLength));
129
+ hmac.createKeyWithData(hkeyData, function(hkey){
130
+ if (hkey === null){
131
+ completion.call(target, null);
132
+ return;
133
+ }
134
+ hmac.key = hkey;
135
+ hmac.update(additionalData);
136
+ hmac.update(this._initalizationVector);
137
+ hmac.update(this._ciphertext);
138
+ hmac.update(uint64DataFromNumber(additionalData.length * 8));
139
+ hmac.sign(function(tag){
140
+ if (tag === null){
141
+ completion.call(target, null);
142
+ return;
143
+ }
144
+ this._authenticationTag = tag.subdataInRange(JSRange(0, hkeyData.length));
145
+ completion.call(target, this.stringRepresentation());
146
+ }, this);
147
+ }, this);
148
+ }, this);
149
+ }, this);
150
+ };
151
+ if (keyCipher !== null){
152
+ keyCipher.createKeyFromJWK(jwk, function(kek){
153
+ if (kek === null){
154
+ completion.call(target, null);
155
+ return;
156
+ }
157
+ hmac.createKey(function(combinedKey){
158
+ if (combinedKey === null){
159
+ completion.call(target, null);
160
+ return;
161
+ }
162
+ keyCipher.wrapKey(combinedKey, kek, function(encryptedKey){
163
+ if (encryptedKey === null){
164
+ completion.call(target, null);
165
+ return;
166
+ }
167
+ this._encryptedKey = encryptedKey;
168
+ combinedKey.getData(encryptContent, this);
169
+ }, this);
170
+ }, this);
171
+ }, this);
172
+ }else{
173
+ JSRunLoop.main.schedule(encryptContent, this, jwk.k.dataByDecodingBase64URL());
174
+ }
175
+ },
176
+
177
+ stringRepresentation: function(){
178
+ if (this._ciphertext === null){
179
+ throw new Error("SECJSONWebEncryption.stringRepresentation() cannot be called before first calling .encrypt()");
180
+ }
181
+ var parts = [
182
+ this._headerData.base64URLStringRepresentation(),
183
+ this._encryptedKey !== null ? this._encryptedKey.base64URLStringRepresentation() : "",
184
+ this._initalizationVector.base64URLStringRepresentation(),
185
+ this._ciphertext.base64URLStringRepresentation(),
186
+ this._authenticationTag.base64URLStringRepresentation()
187
+ ];
188
+ return parts.join(".");
189
+ },
190
+
191
+ decrypt: function(jwkOrSet, completion, target){
192
+ if (!completion){
193
+ completion = Promise.completion();
194
+ }
195
+ var jwk = null;
196
+ if (jwkOrSet instanceof JSData){
197
+ jwk = {
198
+ kty: SECJSONWebAlgorithms.KeyType.symmetric,
199
+ k: jwkOrSet.base64URLStringRepresentation()
200
+ };
201
+ }else if (jwkOrSet instanceof Array){
202
+ for (var i = 0, l = jwkOrSet.length; i < l && jwk === null; ++i){
203
+ var candidate = jwkOrSet[i];
204
+ if (this._header.kid == candidate.kid){
205
+ jwk = candidate;
206
+ }
207
+ }
208
+ }else{
209
+ jwk = jwkOrSet;
210
+ }
211
+ if (jwk === null){
212
+ JSRunLoop.main.schedule(completion, target, null);
213
+ return completion.promise;
214
+ }
215
+ var additionalData = this._headerData.base64URLStringRepresentation().latin1();
216
+ switch (this._header.enc){
217
+ case SECJSONWebAlgorithms.Algorithm.aesGCM128:
218
+ this._decryptAESGCM(128, jwk, additionalData, completion, target);
219
+ break;
220
+ case SECJSONWebAlgorithms.Algorithm.aesGCM192:
221
+ this._decryptAESGCM(192, jwk, additionalData, completion, target);
222
+ break;
223
+ case SECJSONWebAlgorithms.Algorithm.aesGCM256:
224
+ this._decryptAESGCM(256, jwk, additionalData, completion, target);
225
+ break;
226
+ case SECJSONWebAlgorithms.Algorithm.aesCBC128HS256:
227
+ this._decryptAESCBCHMAC(128, SECHMAC.Algorithm.sha256, jwk, additionalData, completion, target);
228
+ break;
229
+ case SECJSONWebAlgorithms.Algorithm.aesCBC192HS384:
230
+ this._decryptAESCBCHMAC(192, SECHMAC.Algorithm.sha384, jwk, additionalData, completion, target);
231
+ break;
232
+ case SECJSONWebAlgorithms.Algorithm.aesCBC256HS512:
233
+ this._decryptAESCBCHMAC(256, SECHMAC.Algorithm.sha512, jwk, additionalData, completion, target);
234
+ break;
235
+ default:
236
+ JSRunLoop.main.schedule(completion, target, null);
237
+ return completion.promise;
238
+ }
239
+ return completion.promise;
240
+ },
241
+
242
+ _decryptAESGCM: function(keyBitLength, jwk, additionalData, completion, target){
243
+ var contentCipher = SECCipher.initWithAlgorithm(SECCipher.Algorithm.aesGCM, {
244
+ keyBitLength: keyBitLength,
245
+ additionalData: additionalData,
246
+ ivByteLength: this._initalizationVector.length,
247
+ tagByteLength: this._authenticationTag.length
248
+ });
249
+ var keyCipher = null;
250
+ switch (this._header.alg){
251
+ case SECJSONWebAlgorithms.Algorithm.direct:
252
+ break;
253
+ case SECJSONWebAlgorithms.Algorithm.rsaOAEP:
254
+ keyCipher = SECCipher.initWithAlgorithm(SECCipher.Algorithm.rsaOAEP);
255
+ break;
256
+ // TODO: support ECDH-ES key derivation
257
+ default:
258
+ JSRunLoop.main.schedule(completion, target, null);
259
+ return;
260
+ }
261
+ var decrypt = function(cek){
262
+ if (cek === null){
263
+ completion.call(target, null);
264
+ return;
265
+ }
266
+ var ciphertext = JSData.initWithChunks([
267
+ this._initalizationVector,
268
+ this._ciphertext,
269
+ this._authenticationTag
270
+ ]);
271
+ contentCipher.decrypt(ciphertext, cek, function(plaintext){
272
+ if (plaintext === null){
273
+ completion.call(target, null);
274
+ return;
275
+ }
276
+ completion.call(target, plaintext, null);
277
+ }, this);
278
+ };
279
+ if (keyCipher !== null){
280
+ keyCipher.createKeyFromJWK(jwk, function(kek){
281
+ if (kek === null){
282
+ decrypt(null);
283
+ return;
284
+ }
285
+ keyCipher.unwrapKey(this._encryptedKey, contentCipher.algorithm, kek, decrypt, this);
286
+ }, this);
287
+ }else{
288
+ contentCipher.createKeyFromJWK(jwk, decrypt, this);
289
+ }
290
+ },
291
+
292
+ _decryptAESCBCHMAC: function(keyBitLength, hmacAlgorithm, jwk, additionalData, completion, target){
293
+ var contentCipher = SECCipher.initWithAlgorithm(SECCipher.Algorithm.aesCBC, {keyBitLength: keyBitLength});
294
+ var keyCipher = null;
295
+ switch (this._header.alg){
296
+ case SECJSONWebAlgorithms.Algorithm.direct:
297
+ break;
298
+ case SECJSONWebAlgorithms.Algorithm.rsaOAEP:
299
+ keyCipher = SECCipher.initWithAlgorithm(SECCipher.Algorithm.rsaOAEP);
300
+ break;
301
+ // TODO: support ECDH-ES key derivation
302
+ default:
303
+ JSRunLoop.main.schedule(completion, target, null);
304
+ return;
305
+ }
306
+ var decrypt = function(combinedKeyData){
307
+ if (combinedKeyData === null){
308
+ completion.call(target, null);
309
+ return;
310
+ }
311
+ if (combinedKeyData.length !== contentCipher.keyByteLength + contentCipher.keyByteLength){
312
+ completion.call(target, null);
313
+ return;
314
+ }
315
+ var hkeyData = combinedKeyData.subdataInRange(JSRange(0, contentCipher.keyByteLength));
316
+ var cekData = combinedKeyData.subdataInRange(JSRange(contentCipher.keyByteLength, contentCipher.keyByteLength));
317
+ contentCipher.createKeyWithData(cekData, function(cek){
318
+ if (cek === null){
319
+ completion.call(target, null);
320
+ return;
321
+ }
322
+ var ciphertext = JSData.initWithChunks([
323
+ this._initalizationVector,
324
+ this._ciphertext
325
+ ]);
326
+ contentCipher.decrypt(ciphertext, cek, function(plaintext){
327
+ if (plaintext === null){
328
+ completion.call(target, null);
329
+ return;
330
+ }
331
+ var hmac = SECHMAC.initWithAlgorithm(hmacAlgorithm);
332
+ hmac.createKeyWithData(hkeyData, function(hkey){
333
+ if (hkey === null){
334
+ completion.call(target, null);
335
+ return;
336
+ }
337
+ hmac.key = hkey;
338
+ hmac.update(additionalData);
339
+ hmac.update(this._initalizationVector);
340
+ hmac.update(this._ciphertext);
341
+ hmac.update(uint64DataFromNumber(additionalData.length * 8));
342
+ hmac.sign(function(tag){
343
+ if (tag === null){
344
+ completion.call(target, null);
345
+ return;
346
+ }
347
+ tag = tag.subdataInRange(JSRange(0, hkeyData.length));
348
+ if (!this._authenticationTag.isEqual(tag)){
349
+ completion.call(target, null);
350
+ return;
351
+ }
352
+ completion.call(target, plaintext);
353
+ }, this);
354
+ }, this);
355
+ }, this);
356
+ }, this);
357
+ };
358
+ if (keyCipher !== null){
359
+ keyCipher.createKeyFromJWK(jwk, function(kek){
360
+ if (kek === null){
361
+ decrypt(null);
362
+ return;
363
+ }
364
+ keyCipher.decrypt(this._encryptedKey, kek, decrypt, this);
365
+ }, this);
366
+ }else{
367
+ JSRunLoop.main.schedule(decrypt, this, jwk.k.dataByDecodingBase64URL());
368
+ }
369
+
370
+ },
371
+
372
+ });
373
+
374
+ SECJSONWebEncryption.Algorithm = SECJSONWebAlgorithms.Algorithm;
375
+
376
+ SECJSONWebEncryption.KeyType = SECJSONWebAlgorithms.KeyType;
377
+
378
+ SECJSONWebEncryption.EllipticCurve = SECJSONWebAlgorithms.EllipticCurve;
379
+
380
+ var uint64DataFromNumber = function(n){
381
+ var data = JSData.initWithLength(8);
382
+ var byte = 7;
383
+ while (n > 0){
384
+ data[byte] = n & 0xFF;
385
+ n >>>= 8;
386
+ --byte;
387
+ }
388
+ return data;
389
+ };
390
+
391
+ })();
@@ -90,7 +90,7 @@ JSClass("SECJSONWebToken", JSObject, {
90
90
  var jwk = null;
91
91
  if (jwkOrSet instanceof JSData){
92
92
  jwk = {
93
- kty: "oct",
93
+ kty: SECJSONWebAlgorithms.KeyType.symmetric,
94
94
  k: jwkOrSet.base64URLStringRepresentation()
95
95
  };
96
96
  }else if (jwkOrSet instanceof Array){
@@ -18,10 +18,23 @@
18
18
 
19
19
  JSClass("SECKey", JSObject, {
20
20
 
21
+ id: null,
22
+ type: null,
23
+ publicKey: null,
24
+
21
25
  getData: function(completion, target){
22
26
  },
23
27
 
28
+ getJWK: function(completion, target){
29
+ },
30
+
24
31
  destroy: function(){
25
32
  }
26
33
 
27
- });
34
+ });
35
+
36
+ SECKey.KeyType = {
37
+ secret: "secret",
38
+ private: "private",
39
+ public: "public"
40
+ };
@@ -14,8 +14,73 @@
14
14
  // limitations under the License.
15
15
 
16
16
  // #import "SECDataKey.js"
17
+ /* jshint node: true */
17
18
  'use strict';
18
19
 
19
- JSClass("SECNodeKey", SECDataKey, {
20
+ var crypto = require('crypto');
21
+
22
+ JSClass("SECNodeKey", SECKey, {
23
+
24
+ nodeKeyObject: null,
25
+ jwkProperties: null,
26
+
27
+ initWithData: function(data){
28
+ if (data === null || data === undefined){
29
+ return null;
30
+ }
31
+ this.nodeKeyObject = crypto.createSecretKey(data.nodeBuffer());
32
+ this.type = this.nodeKeyObject.type;
33
+ },
34
+
35
+ initWithNodeKeyObject: function(nodeKeyObject, jwkProperties){
36
+ if (nodeKeyObject === null || nodeKeyObject === undefined){
37
+ return null;
38
+ }
39
+ this.nodeKeyObject = nodeKeyObject;
40
+ this.jwkProperties = jwkProperties || {};
41
+ },
42
+
43
+ getNodeKeyObject: function(completion, target){
44
+ completion.call(target, this.nodeKeyObject);
45
+ },
46
+
47
+ getData: function(completion, target){
48
+ if (!completion){
49
+ completion = Promise.completion(Promise.resolveNonNull);
50
+ }
51
+ var buffer = this.nodeKeyObject.export({format: "buffer"});
52
+ JSRunLoop.main.schedule(completion, target, JSData.initWithNodeBuffer(buffer));
53
+ return completion.promise;
54
+ },
55
+
56
+ getJWK: function(completion, target){
57
+ if (!completion){
58
+ completion = Promise.completion(Promise.resolveNonNull);
59
+ }
60
+ var jwk = this.nodeKeyObject.export({format: "jwk"});
61
+ for (var k in this.jwkProperties){
62
+ jwk[k] = this.jwkProperties[k];
63
+ }
64
+ if (this.id !== null){
65
+ jwk.kid = this.id;
66
+ }
67
+ JSRunLoop.main.schedule(completion, target, jwk);
68
+ return completion.promise;
69
+ },
70
+
71
+ destroy: function(){
72
+ this.nodeKeyObject = null;
73
+ }
74
+
75
+ });
76
+
77
+ SECKey.definePropertiesFromExtensions({
78
+
79
+ getNodeKeyObject: function(completion, target){
80
+ this.getData(function(data){
81
+ var keyObject = crypto.createSecretKey(data.nodeBuffer());
82
+ completion.call(target, null);
83
+ }, this);
84
+ }
20
85
 
21
86
  });
@@ -55,6 +55,7 @@ SECSign.definePropertiesFromExtensions({
55
55
  public: SECHTMLKey.initWithKey(htmlPair.publicKey),
56
56
  private: SECHTMLKey.initWithKey(htmlPair.privateKey)
57
57
  };
58
+ pair.public.id = pair.private.id = JSSHA1Hash(UUID.init().bytes).base64URLStringRepresentation();
58
59
  completion.call(target, pair);
59
60
  }, function(e){
60
61
  completion.call(target, null);
@@ -62,39 +63,13 @@ SECSign.definePropertiesFromExtensions({
62
63
  return completion.promise;
63
64
  },
64
65
 
65
- createJWKPair: function(options, completion, target){
66
- if (!completion){
67
- completion = Promise.completion(Promise.resolveNonNull);
68
- }
69
- this.createKeyPair(options, function(pair){
70
- if (pair === null){
71
- completion.call(target, null);
72
- return;
73
- }
74
- crypto.subtle.exportKey("jwk", pair.public.htmlKey).then(function(publicJWK){
75
- crypto.subtle.exportKey("jwk", pair.private.htmlKey).then(function(privateJWK){
76
- publicJWK.kid = privateJWK.kid = JSSHA1Hash(UUID.init().bytes).base64URLStringRepresentation();
77
- var pair = {
78
- public: publicJWK,
79
- private: privateJWK
80
- };
81
- completion.call(target, pair);
82
- }, function(){
83
- completion.call(target, null);
84
- });
85
- }, function(){
86
- completion.call(target, null);
87
- });
88
- }, this);
89
- return completion.promise;
90
- },
91
-
92
66
  createKeyFromJWK: function(jwk, completion, target){
93
67
  if (!completion){
94
68
  completion = Promise.completion(Promise.resolveNonNull);
95
69
  }
96
70
  crypto.subtle.importKey("jwk", jwk, this.htmlAlgorithm, true, ["sign"]).then(function(htmlKey){
97
71
  var key = SECHTMLKey.initWithKey(htmlKey);
72
+ key.id = jwk.kid || null;
98
73
  completion.call(target, key);
99
74
  }, function(error){
100
75
  completion.call(target, null);