-
Notifications
You must be signed in to change notification settings - Fork 5.9k
Expand file tree
/
Copy pathcrypto_key_test.ts
More file actions
1229 lines (1073 loc) · 44.4 KB
/
crypto_key_test.ts
File metadata and controls
1229 lines (1073 loc) · 44.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
// deno-lint-ignore-file no-explicit-any
// Copyright 2018-2026 the Deno authors. MIT license.
import {
createECDH,
createHmac,
createPrivateKey,
createPublicKey,
createSecretKey,
createSign,
createVerify,
generateKeyPair,
generateKeyPairSync,
KeyObject,
randomBytes,
sign,
verify,
X509Certificate,
} from "node:crypto";
import { promisify } from "node:util";
import { Buffer } from "node:buffer";
import { assert, assertEquals, assertThrows } from "@std/assert";
const RUN_SLOW_TESTS = Deno.env.get("SLOW_TESTS") === "1";
const generateKeyPairAsync = promisify(
(
type: any,
options: any,
callback: (
err: Error | null,
key: { publicKey: KeyObject; privateKey: KeyObject },
) => void,
) =>
generateKeyPair(
type,
options,
(err: Error | null, publicKey: KeyObject, privateKey: KeyObject) => {
callback(err, { publicKey, privateKey });
},
),
);
const testDir = new URL(".", import.meta.url);
const pemBuffer = Buffer.from(
await Deno.readTextFile(
new URL("../testdata/x509.pem", import.meta.url),
),
);
Deno.test({
name: "create secret key",
fn() {
const key = createSecretKey(Buffer.alloc(0));
assertEquals(key.type, "secret");
assertEquals(key.asymmetricKeyType, undefined);
assertEquals(key.symmetricKeySize, 0);
},
});
Deno.test({
name: "export secret key",
fn() {
const material = Buffer.from(randomBytes(32));
const key = createSecretKey(material);
assertEquals(Buffer.from(key.export()), material);
},
});
Deno.test({
name: "export jwk secret key",
fn() {
const material = Buffer.from("secret");
const key = createSecretKey(material);
assertEquals(key.export({ format: "jwk" }), {
kty: "oct",
k: "c2VjcmV0",
});
},
});
Deno.test({
name: "createHmac with secret key",
fn() {
const key = createSecretKey(Buffer.from("secret"));
assertEquals(
createHmac("sha256", key).update("hello").digest().toString("hex"),
"88aab3ede8d3adf94d26ab90d3bafd4a2083070c3bcce9c014ee04a443847c0b",
);
},
});
const modulusLengths = RUN_SLOW_TESTS ? [2048, 3072] : [2048];
for (const type of ["rsa", "rsa-pss", "dsa"]) {
for (const modulusLength of modulusLengths) {
Deno.test({
name: `generate ${type} key ${modulusLength}`,
fn() {
const { publicKey, privateKey } = generateKeyPairSync(type as any, {
modulusLength,
});
assertEquals(publicKey.type, "public");
assertEquals(privateKey.type, "private");
},
});
Deno.test({
name: `generate ${type} key async ${modulusLength}`,
async fn() {
const x = await generateKeyPairAsync(type as any, {
modulusLength,
});
const { publicKey, privateKey } = x;
assertEquals(publicKey.type, "public");
assertEquals(privateKey.type, "private");
},
});
}
}
for (
const namedCurve of [
"P-384",
"prime384v1",
"secp384r1",
"P-256",
"prime256v1",
"secp256r1",
]
) {
Deno.test({
name: `generate ec key ${namedCurve}`,
fn() {
const { publicKey, privateKey } = generateKeyPairSync("ec", {
namedCurve,
});
assertEquals(publicKey.type, "public");
assertEquals(privateKey.type, "private");
},
});
Deno.test({
name: `generate ec key ${namedCurve} async`,
async fn() {
const { publicKey, privateKey } = await generateKeyPairAsync("ec", {
namedCurve,
});
assertEquals(publicKey.type, "public");
assertEquals(privateKey.type, "private");
},
});
Deno.test({
name: `generate ec key ${namedCurve} paramEncoding=explicit fails`,
fn() {
assertThrows(() => {
// @ts-ignore: @types/node is broken?
generateKeyPairSync("ec", {
namedCurve,
paramEncoding: "explicit",
});
});
},
});
}
for (
const groupName of ["modp5", "modp14", "modp15", "modp16", "modp17", "modp18"]
) {
Deno.test({
name: `generate dh key ${groupName}`,
fn() {
// @ts-ignore: @types/node is broken?
const { publicKey, privateKey } = generateKeyPairSync("dh", {
group: groupName,
});
assertEquals(publicKey.type, "public");
assertEquals(privateKey.type, "private");
},
});
Deno.test({
name: `generate dh key ${groupName} async`,
async fn() {
// @ts-ignore: @types/node is broken?
const { publicKey, privateKey } = await generateKeyPairAsync("dh", {
group: groupName,
});
assertEquals(publicKey.type, "public");
assertEquals(privateKey.type, "private");
},
});
}
const primeLengths = RUN_SLOW_TESTS ? [1024, 2048, 4096] : [1024];
for (const primeLength of primeLengths) {
Deno.test({
name: `generate dh key ${primeLength}`,
fn() {
// @ts-ignore: @types/node is broken?
const { publicKey, privateKey } = generateKeyPairSync("dh", {
primeLength,
generator: 2,
});
assertEquals(publicKey.type, "public");
assertEquals(privateKey.type, "private");
},
});
Deno.test({
name: `generate dh key ${primeLength} async`,
async fn() {
// @ts-ignore: @types/node is broken?
const { publicKey, privateKey } = await generateKeyPairAsync("dh", {
primeLength,
generator: 2,
});
assertEquals(publicKey.type, "public");
assertEquals(privateKey.type, "private");
},
});
}
const rsaPrivateKey = Deno.readTextFileSync(
new URL("../testdata/rsa_private.pem", import.meta.url),
);
Deno.test("createPrivateKey rsa", function () {
const key = createPrivateKey(rsaPrivateKey);
assertEquals(key.type, "private");
assertEquals(key.asymmetricKeyType, "rsa");
assertEquals(key.asymmetricKeyDetails?.modulusLength, 2048);
assertEquals(key.asymmetricKeyDetails?.publicExponent, 65537n);
assertEquals(
Object.getPrototypeOf(key.asymmetricKeyDetails),
Object.prototype,
);
});
Deno.test("createPrivateKey dh", function () {
// 1.2.840.113549.1.3.1
const pem = "-----BEGIN PRIVATE KEY-----\n" +
"MIIBoQIBADCB1QYJKoZIhvcNAQMBMIHHAoHBAP//////////yQ/aoiFowjTExmKL\n" +
"gNwc0SkCTgiKZ8x0Agu+pjsTmyJRSgh5jjQE3e+VGbPNOkMbMCsKbfJfFDdP4TVt\n" +
"bVHCReSFtXZiXn7G9ExC6aY37WsL/1y29Aa37e44a/taiZ+lrp8kEXxLH+ZJKGZR\n" +
"7ORbPcIAfLihY78FmNpINhxV05ppFj+o/STPX4NlXSPco62WHGLzViCFUrue1SkH\n" +
"cJaWbWcMNU5KvJgE8XRsCMojcyf//////////wIBAgSBwwKBwHxnT7Zw2Ehh1vyw\n" +
"eolzQFHQzyuT0y+3BF+FxK2Ox7VPguTp57wQfGHbORJ2cwCdLx2mFM7gk4tZ6COS\n" +
"E3Vta85a/PuhKXNLRdP79JgLnNtVtKXB+ePDS5C2GgXH1RHvqEdJh7JYnMy7Zj4P\n" +
"GagGtIy3dV5f4FA0B/2C97jQ1pO16ah8gSLQRKsNpTCw2rqsZusE0rK6RaYAef7H\n" +
"y/0tmLIsHxLIn+WK9CANqMbCWoP4I178BQaqhiOBkNyNZ0ndqA==\n" +
"-----END PRIVATE KEY-----";
const key = createPrivateKey(pem);
assertEquals(key.type, "private");
assertEquals(key.asymmetricKeyType, "dh");
});
Deno.test("createPublicKey dh", function () {
// 1.2.840.113549.1.3.1
const pem = "-----BEGIN PUBLIC KEY-----\n" +
"MIIBnzCB1QYJKoZIhvcNAQMBMIHHAoHBAP//////////yQ/aoiFowjTExmKLgNwc\n" +
"0SkCTgiKZ8x0Agu+pjsTmyJRSgh5jjQE3e+VGbPNOkMbMCsKbfJfFDdP4TVtbVHC\n" +
"ReSFtXZiXn7G9ExC6aY37WsL/1y29Aa37e44a/taiZ+lrp8kEXxLH+ZJKGZR7ORb\n" +
"PcIAfLihY78FmNpINhxV05ppFj+o/STPX4NlXSPco62WHGLzViCFUrue1SkHcJaW\n" +
"bWcMNU5KvJgE8XRsCMojcyf//////////wIBAgOBxAACgcBR7+iL5qx7aOb9K+aZ\n" +
"y2oLt7ST33sDKT+nxpag6cWDDWzPBKFDCJ8fr0v7yW453px8N4qi4R7SYYxFBaYN\n" +
"Y3JvgDg1ct2JC9sxSuUOLqSFn3hpmAjW7cS0kExIVGfdLlYtIqbhhuo45cTEbVIM\n" +
"rDEz8mjIlnvbWpKB9+uYmbjfVoc3leFvUBqfG2In2m23Md1swsPxr3n7g68H66JX\n" +
"iBJKZLQMqNdbY14G9rdKmhhTJrQjC+i7Q/wI8JPhOFzHIGA=\n" +
"-----END PUBLIC KEY-----";
const key = createPublicKey(pem);
assertEquals(key.type, "public");
assertEquals(key.asymmetricKeyType, "dh");
});
// openssl ecparam -name secp256r1 -genkey -noout -out a.pem
// openssl pkcs8 -topk8 -nocrypt -in a.pem -out b.pem
const ecPrivateKey = Deno.readTextFileSync(
new URL("./ec_private_secp256r1.pem", import.meta.url),
);
Deno.test("createPrivateKey ec", function () {
const key = createPrivateKey(ecPrivateKey);
assertEquals(key.type, "private");
assertEquals(key.asymmetricKeyType, "ec");
assertEquals(key.asymmetricKeyDetails?.namedCurve, "prime256v1");
});
const rsaPublicKey = Deno.readTextFileSync(
new URL("../testdata/rsa_public.pem", import.meta.url),
);
Deno.test("createPublicKey() RSA", () => {
const key = createPublicKey(rsaPublicKey);
assertEquals(key.type, "public");
assertEquals(key.asymmetricKeyType, "rsa");
assertEquals(key.asymmetricKeyDetails?.modulusLength, 2048);
assertEquals(key.asymmetricKeyDetails?.publicExponent, 65537n);
});
// openssl ecparam -name prime256v1 -genkey -noout -out a.pem
// openssl ec -in a.pem -pubout -out b.pem
const ecPublicKey = Deno.readTextFileSync(
new URL("../testdata/ec_prime256v1_public.pem", import.meta.url),
);
Deno.test("createPublicKey() EC", function () {
const key = createPublicKey(ecPublicKey);
assertEquals(key.type, "public");
assertEquals(key.asymmetricKeyType, "ec");
assertEquals(key.asymmetricKeyDetails?.namedCurve, "prime256v1");
});
Deno.test("createPublicKey SPKI for DH", async function () {
const { publicKey, privateKey } = await crypto.subtle.generateKey(
{
name: "ECDH",
namedCurve: "P-384",
},
true,
["deriveKey", "deriveBits"],
);
const exportedPublicKey = await crypto.subtle.exportKey("spki", publicKey);
const exportedPrivateKey = await crypto.subtle.exportKey("pkcs8", privateKey);
const pubKey = createPublicKey({
key: Buffer.from(exportedPublicKey),
format: "der",
type: "spki",
});
const privKey = createPrivateKey({
key: Buffer.from(exportedPrivateKey),
format: "der",
type: "pkcs8",
});
assertEquals(pubKey.asymmetricKeyType, "ec");
assertEquals(privKey.asymmetricKeyType, "ec");
});
Deno.test("ECDH generateKeys compressed", function () {
const ecdh = createECDH("secp256k1");
const publicKey = ecdh.generateKeys("binary", "compressed");
assertEquals(publicKey.length, 33);
const uncompressedKey = ecdh.generateKeys("binary");
assertEquals(uncompressedKey.length, 65);
});
Deno.test("ECDH getPublicKey compressed", function () {
const ecdh = createECDH("secp256k1");
for (const format of ["compressed", "uncompressed"] as const) {
ecdh.generateKeys("binary", format);
const compressedKey = ecdh.getPublicKey("binary", "compressed");
assertEquals(compressedKey.length, 33);
const uncompressedKey = ecdh.getPublicKey("binary");
assertEquals(uncompressedKey.length, 65);
}
});
// https://github.com/denoland/deno/issues/20938
Deno.test("rsa jwt signer", function () {
const token = `-----BEGIN PRIVATE KEY-----
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCVoKHiWLQKlnCG
oR4d8g+OSGXoJ3yY+BFubB+1TSaCvWGLkqHjYAA0UCgOoaazE2YnXhVlO4tLDLn/
5R6PJrsxksnup+AWnEbur+CuaeQqizGTQXA0nUrsza/QJxb05GSMW9kupzI5BXBi
1R8Tmo5I0CpmXDi1yF+nL2NeDXHB999tXcRSrN/Ai11G1HFoYVs36+cm/Jw71BB1
KsokwFuzvxTFL9bOXDy8/8MlF8QSBFaWBN1tNZ40+oLf/rYeNXpZAFywvC9rc/Ud
B7J9InYHJQaq+vzuWNq7l0LnkJK+/Mq3AYl5yStjBie6tXC3LCmQ5MmLdzHE+SBQ
7tUIL6fvAgMBAAECggEAMSMJRp2+smNpHK04iLj/ZshbvvuIrWt5vfuABjgJ15F9
wSosQ9E4//T60qM/bTuHppH9ELuXKNRLGMATYwtjGgqMifVTX9l+adAURvK7XUVM
yIEK6hxliJKblA3iOhXu9zEKh4mcsqEYoTw/8l4lL8A8zFSowvnEf9DOHwrnOr09
bV6+6BZbLgugLqtOB7i5agnviiCV4Z4llWdhP3zW3c8/PUQyTsqebTkY0DB4FnI0
vC0kQU/v/7MCueH0FA4fMEY9CWuzL3809I9rvUPIBgqSkpXEoWxoGUJxIHGYK6fG
+HHjZQp87Sfz5G4g/Qrq2Gqc2Mb7I0QS2zgBu1tx0QKBgQDH3EyxQ6W9r2S1WqEm
w2B32AuemWwIdxaeLf4est0rO0G0ihAsx4vNZElKO7weYDypp8AjeYfjuriweyQA
R8KDWonn9jA2QQfNNkXDIq+d5+zFbfdOFGqQEThLtpi5pPh0+NeUGQQZIb07jqLF
giuZgOmPVFwru8jYLO04GTZoEwKBgQC/qCP74LHI3/35Ftx5l9CnM5Zr84ByoI5B
3xt2Sd9OsxULxY/omvcB2EdBZSTVKunGmF2a7MDpOn0r/7FdSuuuqzrMwRqbzRFA
GSO06vnoA/k6llcfXKqLZqjHuHEAUNpEeAuzNUKP2DgvnHRtXSkBpFb+IUTMlL9y
O55+g570NQKBgBZiSgSgevOfrTvShrH8t9U0UTjWHg9kpxfYNtnhVnv9CwLZY65g
Ovwp+zthLVSJmsG1lANlHR8YTo8Ve5a8csCbZ06feA7bgbAuH+oW/GxHCXGjO0t3
Zef0xcVVEg3YuCsBo8NmedsGuFbvRrOwPInYsk/nNtt/EKOFhJv/1uQZAoGAdaYb
YLTPrcWCO/PCp4l/9gN+5Ql24eaZLOpuCzDRuZfI5Y8DBgCKfEFtjEEwWQKcuuIx
I7cNvJ3A1M+C6wfgoTpPP/2R/e3mFvjXqGlNuxUlWseK95+EuUntdZxNEaqQMdOX
Kw0YrQBHjUJ3XeMAFxfwptN5TjRJSTA73OGjI7kCgYBtw1LmjFd6wJFyqLEsBnqO
gnVnpxf1DMeMUFpNr+M14P3ETa5UaqiMvCD6VGOzCYv1F7JhnS9TFsYY+FV+L3Nh
1+bZIPY4D4seyPgH0cCycBSVfqdAHJlfxf/Pm7lHCNxTGEfBWri4Ga1bW+zQpWY7
SogaIHQjE81ZkmNtU5gM5Q==
-----END PRIVATE KEY-----`;
const key = createPrivateKey(token);
assertEquals(key.type, "private");
assertEquals(key.asymmetricKeyType, "rsa");
assertEquals(key.asymmetricKeyDetails?.modulusLength, 2048);
assertEquals(key.asymmetricKeyDetails?.publicExponent, 65537n);
const signer = createSign("RSA-SHA256");
signer.update("hello");
const signature = signer.sign(key, "base64");
assertEquals(
signature,
`jEwckJ/d5GkF/8TTm+wllq2JNghG/m2JYJIW7vS8Vms53zCTTNSSegTSoIVoxWymwTPw2dTtZi41Lg0O271/WvEmQhiWD2dnjz6D/0F4eyn+QUhcmGCadDFyfp7+8x1XOppSw2YB8vL5WCL0QDdp3TAa/rWI0Hn4OftHMa6HPvatkGs+8XlQOGCCfd3TLg+t1UROgpgmetjoAM67mlwxXMGGu/Tr/EbXnnINKeB0iuSmD1FCxlrgFuYWDKxd79n2jZ74FrS/zto+bqWSI5uUa4Ar7yvXtek1Cu1OFM6vgdN9Y6Po2UD9+IT04EhU03LUDY5paYOO8yohz7p7kqHvpA==`,
);
});
Deno.test("generate rsa export public key", async function () {
const { publicKey } = await generateKeyPairAsync("rsa", {
modulusLength: 2048,
});
const spkiPem = publicKey.export({ format: "pem", type: "spki" });
assert(typeof spkiPem === "string");
assert(spkiPem.startsWith("-----BEGIN PUBLIC KEY-----"));
const der = publicKey.export({ format: "der", type: "spki" });
assert(der instanceof Uint8Array);
});
Deno.test("create public key with invalid utf-8 string", function () {
// This is an invalid UTF-8 string because it contains a lone utf-16 surrogate.
const invalidPem = Buffer.from(new Uint8Array([0xE2, 0x28, 0xA1]));
assertThrows(
() => {
createPublicKey(invalidPem);
},
Error,
"not valid utf8",
);
});
Deno.test("create private key with invalid utf-8 string", function () {
// This is an invalid UTF-8 string because it contains a lone utf-16 surrogate.
const invalidPem = Buffer.from(new Uint8Array([0xE2, 0x28, 0xA1]));
assertThrows(
() => {
createPrivateKey(invalidPem);
},
Error,
"not valid utf8",
);
});
Deno.test("RSA JWK import public key", function () {
const key = {
"kty": "RSA",
"alg": "RS256",
"n":
"5Ddosh0Bze5zy-nQ6gAJFpBfL13muCXrTyKYTps61bmnUxpp3bJnt_2N2MXGfuxBENO0Rbc8DhVPd-lNa4H3XjMwIBdxDAwW32z3pfVr8pHyWxeFtK4SCbvX8B0C6n8ZHigJsvdiCNmoj7_LO_QUzIXmXLFvEXtAqzD_hCr0pJxRIr0BrBjYwL23PkxOYzBR-URcd4Ilji6410Eh9NXycyFzKOcqZ7rjG_PnRyUX1EBZH_PN4RExjJuXYgiqhtU-tDjQFzXLhvwAd5s3ThP9lax27A6MUpjLSKkNy-dG5tlaA0QvECfDzA-5eQjcL_OfvbHlKHQH9zPh-U9Q8gsf3iXmbJrypkalUiTCqnzJu5TgZORSg6zmxNyOCz53YxBHEEaF8yROPwxWDylZfC4fxCRTdoAyFgmFLfMbiepV7AZ24KLj4jfMbGfKpkbPq0xirnSAS-3vbOfkgko5X420AttP8Z1ZBbFSD20Ath_TA9PSHiRCak4AXvOoCZg0t-WuMwzkd_B2V_JZZSTb1yBWrKTL1QzUamqlufjdWuz7M-O2Wkb2cyDSESVNuQyJgDkYb0AOWo0BaN3wbOeT_D4cSrjQoo01xQQCZHQ9SVR4QzUQNAiQcSriqEiptHYhbi6R5_GfGAeMHmlJa4atO2hense0Qk4vDc2fc-sbnQ1jPiE",
"e": "AQAB",
"key_ops": [
"verify",
],
"ext": true,
};
const keyObject = createPublicKey({ key, format: "jwk" });
const expectedPem = `-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA5Ddosh0Bze5zy+nQ6gAJ
FpBfL13muCXrTyKYTps61bmnUxpp3bJnt/2N2MXGfuxBENO0Rbc8DhVPd+lNa4H3
XjMwIBdxDAwW32z3pfVr8pHyWxeFtK4SCbvX8B0C6n8ZHigJsvdiCNmoj7/LO/QU
zIXmXLFvEXtAqzD/hCr0pJxRIr0BrBjYwL23PkxOYzBR+URcd4Ilji6410Eh9NXy
cyFzKOcqZ7rjG/PnRyUX1EBZH/PN4RExjJuXYgiqhtU+tDjQFzXLhvwAd5s3ThP9
lax27A6MUpjLSKkNy+dG5tlaA0QvECfDzA+5eQjcL/OfvbHlKHQH9zPh+U9Q8gsf
3iXmbJrypkalUiTCqnzJu5TgZORSg6zmxNyOCz53YxBHEEaF8yROPwxWDylZfC4f
xCRTdoAyFgmFLfMbiepV7AZ24KLj4jfMbGfKpkbPq0xirnSAS+3vbOfkgko5X420
AttP8Z1ZBbFSD20Ath/TA9PSHiRCak4AXvOoCZg0t+WuMwzkd/B2V/JZZSTb1yBW
rKTL1QzUamqlufjdWuz7M+O2Wkb2cyDSESVNuQyJgDkYb0AOWo0BaN3wbOeT/D4c
SrjQoo01xQQCZHQ9SVR4QzUQNAiQcSriqEiptHYhbi6R5/GfGAeMHmlJa4atO2he
nse0Qk4vDc2fc+sbnQ1jPiECAwEAAQ==
-----END PUBLIC KEY-----
`;
const pem = keyObject.export({ format: "pem", type: "spki" });
assertEquals(pem, expectedPem);
});
Deno.test("Ed25519 import jwk public key #1", function () {
const key = {
"kty": "OKP",
"crv": "Ed25519",
"d": "nWGxne_9WmC6hEr0kuwsxERJxWl7MmkZcDusAxyuf2A",
"x": "11qYAYKxCrfVS_7TyWQHOg7hcvPapiMlrwIaaPcHURo",
};
const keyObject = createPublicKey({ key, format: "jwk" });
assertEquals(keyObject.type, "public");
const spkiActual = keyObject.export({ type: "spki", format: "pem" });
const spkiExpected = `-----BEGIN PUBLIC KEY-----
MCowBQYDK2VwAyEA11qYAYKxCrfVS/7TyWQHOg7hcvPapiMlrwIaaPcHURo=
-----END PUBLIC KEY-----
`;
assertEquals(spkiActual, spkiExpected);
});
Deno.test("Ed25519 import jwk public key #2", function () {
const key = {
"kty": "OKP",
"crv": "Ed25519",
"x": "11qYAYKxCrfVS_7TyWQHOg7hcvPapiMlrwIaaPcHURo",
};
const keyObject = createPublicKey({ key, format: "jwk" });
assertEquals(keyObject.type, "public");
const spki = keyObject.export({ type: "spki", format: "pem" });
const spkiExpected = `-----BEGIN PUBLIC KEY-----
MCowBQYDK2VwAyEA11qYAYKxCrfVS/7TyWQHOg7hcvPapiMlrwIaaPcHURo=
-----END PUBLIC KEY-----
`;
assertEquals(spki, spkiExpected);
});
Deno.test("Ed25519 import jwk private key", function () {
const key = {
"kty": "OKP",
"crv": "Ed25519",
"d": "nWGxne_9WmC6hEr0kuwsxERJxWl7MmkZcDusAxyuf2A",
"x": "11qYAYKxCrfVS_7TyWQHOg7hcvPapiMlrwIaaPcHURo",
};
const keyObject = createPrivateKey({ key, format: "jwk" });
assertEquals(keyObject.type, "private");
const pkcs8Actual = keyObject.export({ type: "pkcs8", format: "pem" });
const pkcs8Expected = `-----BEGIN PRIVATE KEY-----
MC4CAQAwBQYDK2VwBCIEIJ1hsZ3v/VpguoRK9JLsLMREScVpezJpGXA7rAMcrn9g
-----END PRIVATE KEY-----
`;
assertEquals(pkcs8Actual, pkcs8Expected);
});
Deno.test("RSA export public JWK", function () {
const importKey = "-----BEGIN PUBLIC KEY-----\n" +
"MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAqF66soiDvuqUB7ufWtuV\n" +
"5a1nZIw90m9qHEl2MeNt66HeEjG2GeHDfF5a4uplutnAh3dwpFweHqGIyB16POTI\n" +
"YysJ/rMPKoWZFQ1LEcr23rSgmL49YpifDetl5V/UR+zEygL3UzzZmbdjuyZz+Sjt\n" +
"FY+SAoZ9XPCqIaNha9uVFcurW44MvAkhzQR/yy5NWPaJ/yv4oI/exvuZnUwwBHvH\n" +
"gwVchfr7Jh5LRmYTPeyuI1lUOovVzE+0Ty/2tFfrm2hpedqYXvEuVu+yJzfuNoLf\n" +
"TGfz15J76eoRdFTCTdaG/MQnrzxZnIlmIpdpTPl0xVOwjKRpeYK06GS7EAa7cS9D\n" +
"dnsHkF/Mr9Yys5jw/49fXqh9BH3Iy0p5YmeQIMep04CUDFj7MZ+3SK8b0mA4SscH\n" +
"dIraZZynLZ1crM0ECAJBldM4TKqIDACYGU7XyRV+419cPJvYybHys5m7thS3QI7E\n" +
"LTpMV+WoYtZ5xeBCm7z5i3iPY6eSh2JtTu6oa3ALwwnXPAaZqDIFer8SoQNyVb0v\n" +
"EU8bVDeGXm1ha5gcC5KxqqnadO/WDD6Jke79Ji04sBEKTTodSOARyTGpGFEcC3Nn\n" +
"xSSScGCxMrGJuTDtnz+Eh6l6ysT+Nei9ZRMxNu8sZKAR43XkVXxF/OdSCbftFOAs\n" +
"wyPJtyhQALGPcK5cWPQS2sUCAwEAAQ==\n" +
"-----END PUBLIC KEY-----\n";
const publicKey = createPublicKey(importKey);
const jwk = publicKey.export({ format: "jwk" });
assertEquals(jwk, {
kty: "RSA",
n: "qF66soiDvuqUB7ufWtuV5a1nZIw90m9qHEl2MeNt66HeEjG2GeHDfF5a4uplutnAh3dwpFweHqGIyB16POTIYysJ_rMPKoWZFQ1LEcr23rSgmL49YpifDetl5V_UR-zEygL3UzzZmbdjuyZz-SjtFY-SAoZ9XPCqIaNha9uVFcurW44MvAkhzQR_yy5NWPaJ_yv4oI_exvuZnUwwBHvHgwVchfr7Jh5LRmYTPeyuI1lUOovVzE-0Ty_2tFfrm2hpedqYXvEuVu-yJzfuNoLfTGfz15J76eoRdFTCTdaG_MQnrzxZnIlmIpdpTPl0xVOwjKRpeYK06GS7EAa7cS9DdnsHkF_Mr9Yys5jw_49fXqh9BH3Iy0p5YmeQIMep04CUDFj7MZ-3SK8b0mA4SscHdIraZZynLZ1crM0ECAJBldM4TKqIDACYGU7XyRV-419cPJvYybHys5m7thS3QI7ELTpMV-WoYtZ5xeBCm7z5i3iPY6eSh2JtTu6oa3ALwwnXPAaZqDIFer8SoQNyVb0vEU8bVDeGXm1ha5gcC5KxqqnadO_WDD6Jke79Ji04sBEKTTodSOARyTGpGFEcC3NnxSSScGCxMrGJuTDtnz-Eh6l6ysT-Nei9ZRMxNu8sZKAR43XkVXxF_OdSCbftFOAswyPJtyhQALGPcK5cWPQS2sU",
e: "AQAB",
});
});
Deno.test("EC export public jwk", function () {
const key = "-----BEGIN PUBLIC KEY-----\n" +
"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEVEEIrFEZ+40Pk90LtKBQ3r7FGAPl\n" +
"v4bvX9grC8bNiNiVAcyEKs+QZKQj/0/CUPJV10AmavrUoPk/7Wy0sejopQ==\n" +
"-----END PUBLIC KEY-----\n";
const publicKey = createPublicKey(key);
const jwk = publicKey.export({ format: "jwk" });
assertEquals(jwk, {
kty: "EC",
x: "VEEIrFEZ-40Pk90LtKBQ3r7FGAPlv4bvX9grC8bNiNg",
y: "lQHMhCrPkGSkI_9PwlDyVddAJmr61KD5P-1stLHo6KU",
crv: "P-256",
});
});
Deno.test("Ed25519 export public jwk", function () {
const key = "-----BEGIN PUBLIC KEY-----\n" +
"MCowBQYDK2VwAyEAKCVFOD6Le61XM7HbN/MB/N06mX5bti2p50qjLvT1mzE=\n" +
"-----END PUBLIC KEY-----\n";
const publicKey = createPublicKey(key);
const jwk = publicKey.export({ format: "jwk" });
assertEquals(jwk, {
crv: "Ed25519",
x: "KCVFOD6Le61XM7HbN_MB_N06mX5bti2p50qjLvT1mzE",
kty: "OKP",
});
});
Deno.test("EC import jwk public key", function () {
const publicKey = createPublicKey({
key: {
kty: "EC",
x: "_GGuz19zab5J70zyiUK6sAM5mHqUbsY8H6U2TnVlt-k",
y: "TcZG5efXZDIhNGDp6XuujoJqOEJU2D2ckjG9nOnSPIQ",
crv: "P-256",
},
format: "jwk",
});
const publicSpki = publicKey.export({ type: "spki", format: "pem" });
const spkiExpected = `-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE/GGuz19zab5J70zyiUK6sAM5mHqU
bsY8H6U2TnVlt+lNxkbl59dkMiE0YOnpe66Ogmo4QlTYPZySMb2c6dI8hA==
-----END PUBLIC KEY-----
`;
assertEquals(publicSpki, spkiExpected);
});
Deno.test("EC import jwk private key", function () {
const privateKey = createPrivateKey({
key: {
kty: "EC",
x: "_GGuz19zab5J70zyiUK6sAM5mHqUbsY8H6U2TnVlt-k",
y: "TcZG5efXZDIhNGDp6XuujoJqOEJU2D2ckjG9nOnSPIQ",
crv: "P-256",
d: "Wobjne0GqlB_1NynKu19rsw7zBHa94tKcWIxwIb88m8",
},
format: "jwk",
});
const privatePkcs8 = privateKey.export({ type: "pkcs8", format: "pem" });
const pkcs8Expected = `-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgWobjne0GqlB/1Nyn
Ku19rsw7zBHa94tKcWIxwIb88m+hRANCAAT8Ya7PX3NpvknvTPKJQrqwAzmYepRu
xjwfpTZOdWW36U3GRuXn12QyITRg6el7ro6CajhCVNg9nJIxvZzp0jyE
-----END PRIVATE KEY-----
`;
assertEquals(privatePkcs8, pkcs8Expected);
});
Deno.test("createPublicKey x509", function () {
const certificate = `-----BEGIN CERTIFICATE-----
MIIC8zCCAdugAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExB0ZXN0
LWNlcnRpZmljYXRlMB4XDTI0MDkxNzA5MTczNVoXDTI3MDkxNzA5MTczNVowGzEZ
MBcGA1UEAxMQdGVzdC1jZXJ0aWZpY2F0ZTCCASIwDQYJKoZIhvcNAQEBBQADggEP
ADCCAQoCggEBAMOzTIrwvbUbPIrxCr5DO1XMd3tH37pID0no4cOUq1hxNEnB4l1j
2201atvmXwzWI3xtPzfwOYUtE/DGagFh805/nod5yXwR6liGd9RjkABxPi0UF7jl
lWHfBLyILUHVR9hEOl65vUpKx5ORNgbO9L7WsL/FKH9pvCbWjdI29+pQnZ4gOoWZ
YC6auoKfG7TcbaFb9AubolcIlofC2MHP+cWjPA+iX6ezUqqN1Ug5xGiF/sC79M0o
5d6E83zdXxyyFwydUWUv3EKgmVTLln/2hYQFKCRhy72n6L7y9JNcieOauQK0efJB
+2HwaWeAr2xkhSnWVCRl4nEgiu/E0nL/zNUCAwEAAaNCMEAwDgYDVR0PAQH/BAQD
AgGGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFIAeXho137l8V6daKI33IvRb
N6CyMA0GCSqGSIb3DQEBCwUAA4IBAQAQU1Sast6VsD4uTJiSz/lSEkLZ6wC/6v+R
az0YSnbNmQ5YczBLdTLs07hBC1tDvv0vfopRXvNxP7AxkopX5O7Lc15zf5JdTZnY
/tJwO62jZiaLsfAo2JzrZ31h2cFFFRTYPTx+8E4djgdmwKtaECeQFXqdpOHOJCGv
NfwVlZ7Z/cd8fI8oiNtvJDAhPa/UZXAhFV74hT0DiuMwPiJvsG83rutvAYpZ8lPu
yG6QSsxPnxzEHIKR+vgxUHKwTdv0sWt3XBmpIY5CGXFR2eIQP1jv0ohtcnLMJe8N
z6TExWlQMjt66nV7R8cRAkzmABrG+NW3e8Zpac7Lkuv+zu0S+K7c
-----END CERTIFICATE-----`;
const publicKey = createPublicKey(certificate);
assertEquals(publicKey.type, "public");
assertEquals(publicKey.asymmetricKeyType, "rsa");
});
// https://github.com/denoland/deno/issues/26188
Deno.test("generateKeyPair large pem", function () {
const passphrase = "mypassphrase";
const cipher = "aes-256-cbc";
const modulusLength = 4096;
generateKeyPairSync("rsa", {
modulusLength,
publicKeyEncoding: {
type: "spki",
format: "pem",
},
privateKeyEncoding: {
type: "pkcs8",
format: "pem",
cipher,
passphrase,
},
});
});
Deno.test("generateKeyPair promisify", async () => {
const passphrase = "mypassphrase";
const cipher = "aes-256-cbc";
const modulusLength = 4096;
const { privateKey, publicKey } = await promisify(generateKeyPair)("rsa", {
modulusLength,
publicKeyEncoding: {
type: "spki",
format: "pem",
},
privateKeyEncoding: {
type: "pkcs8",
format: "pem",
cipher,
passphrase,
},
});
assert(publicKey.startsWith("-----BEGIN PUBLIC KEY-----"));
assert(privateKey.startsWith("-----BEGIN PRIVATE KEY-----"));
});
Deno.test("RSA export private JWK", function () {
// @ts-ignore @types/node broken
const { privateKey, publicKey } = generateKeyPairSync("rsa", {
modulusLength: 4096,
publicKeyEncoding: {
format: "jwk",
},
privateKeyEncoding: {
format: "jwk",
},
});
assertEquals((privateKey as any).kty, "RSA");
assertEquals((privateKey as any).n, (publicKey as any).n);
});
Deno.test("X509Certificate checkHost", function () {
const der = Buffer.from(
"308203e8308202d0a0030201020214147d36c1c2f74206de9fab5f2226d78adb00a42630" +
"0d06092a864886f70d01010b0500307a310b3009060355040613025553310b3009060355" +
"04080c024341310b300906035504070c025346310f300d060355040a0c064a6f79656e74" +
"3110300e060355040b0c074e6f64652e6a73310c300a06035504030c036361313120301e" +
"06092a864886f70d010901161172794074696e79636c6f7564732e6f72673020170d3232" +
"303930333231343033375a180f32323936303631373231343033375a307d310b30090603" +
"55040613025553310b300906035504080c024341310b300906035504070c025346310f30" +
"0d060355040a0c064a6f79656e743110300e060355040b0c074e6f64652e6a73310f300d" +
"06035504030c066167656e74313120301e06092a864886f70d010901161172794074696e" +
"79636c6f7564732e6f726730820122300d06092a864886f70d01010105000382010f0030" +
"82010a0282010100d456320afb20d3827093dc2c4284ed04dfbabd56e1ddae529e28b790" +
"cd4256db273349f3735ffd337c7a6363ecca5a27b7f73dc7089a96c6d886db0c62388f1c" +
"dd6a963afcd599d5800e587a11f908960f84ed50ba25a28303ecda6e684fbe7baedc9ce8" +
"801327b1697af25097cee3f175e400984c0db6a8eb87be03b4cf94774ba56fffc8c63c68" +
"d6adeb60abbe69a7b14ab6a6b9e7baa89b5adab8eb07897c07f6d4fa3d660dff574107d2" +
"8e8f63467a788624c574197693e959cea1362ffae1bba10c8c0d88840abfef103631b2e8" +
"f5c39b5548a7ea57e8a39f89291813f45a76c448033a2b7ed8403f4baa147cf35e2d2554" +
"aa65ce49695797095bf4dc6b0203010001a361305f305d06082b06010505070101045130" +
"4f302306082b060105050730018617687474703a2f2f6f6373702e6e6f64656a732e6f72" +
"672f302806082b06010505073002861c687474703a2f2f63612e6e6f64656a732e6f7267" +
"2f63612e63657274300d06092a864886f70d01010b05000382010100c3349810632ccb7d" +
"a585de3ed51e34ed154f0f7215608cf2701c00eda444dc2427072c8aca4da6472c1d9e68" +
"f177f99a90a8b5dbf3884586d61cb1c14ea7016c8d38b70d1b46b42947db30edc1e9961e" +
"d46c0f0e35da427bfbe52900771817e733b371adf19e12137235141a34347db0dfc05579" +
"8b1f269f3bdf5e30ce35d1339d56bb3c570de9096215433047f87ca42447b44e7e6b5d0e" +
"48f7894ab186f85b6b1a74561b520952fea888617f32f582afce1111581cd63efcc68986" +
"00d248bb684dedb9c3d6710c38de9e9bc21f9c3394b729d5f707d64ea890603e5989f8fa" +
"59c19ad1a00732e7adc851b89487cc00799dde068aa64b3b8fd976e8bc113ef2",
"hex",
);
const cert = new X509Certificate(der);
assertEquals(cert.checkHost("www.google.com"), undefined);
assertEquals(cert.checkHost("agent1"), "agent1");
});
Deno.test("X509Certificate inspect", async function () {
const scriptPath = "../testdata/inspect-x509.ts";
const command = new Deno.Command(Deno.execPath(), {
args: ["run", "--allow-read", scriptPath],
stdin: "null",
stdout: "piped",
stderr: "null",
cwd: testDir,
});
const { stdout } = await command.output();
const trimmedStdout = new TextDecoder().decode(stdout).trim();
assertEquals(
trimmedStdout,
`X509Certificate {
subject: 'C=US\\n' +
'ST=CA\\n' +
'L=SF\\n' +
'O=Joyent\\n' +
'OU=Node.js\\n' +
'CN=agent1\\n' +
'emailAddress=ry@tinyclouds.org',
subjectAltName: undefined,
issuer: 'C=US\\nST=CA\\nL=SF\\nO=Joyent\\nOU=Node.js\\nCN=ca1\\nemailAddress=ry@tinyclouds.org',
infoAccess: 'OCSP - URI:http://ocsp.nodejs.org/\\n' +
'CA Issuers - URI:http://ca.nodejs.org/ca.cert',
validFrom: 'Sep 3 21:40:37 2022 GMT',
validTo: 'Jun 17 21:40:37 2296 GMT',
validFromDate: 2022-09-03T21:40:37.000Z,
validToDate: 2296-06-17T21:40:37.000Z,
fingerprint: '8B:89:16:C4:99:87:D2:13:1A:64:94:36:38:A5:32:01:F0:95:3B:53',
fingerprint256: '2C:62:59:16:91:89:AB:90:6A:3E:98:88:A6:D3:C5:58:58:6C:AE:FF:9C:33:22:7C:B6:77:D3:34:E7:53:4B:05',
fingerprint512: '0B:6F:D0:4D:6B:22:53:99:66:62:51:2D:2C:96:F2:58:3F:95:1C:CC:4C:44:9D:B5:59:AA:AD:A8:F6:2A:24:8A:BB:06:A5:26:42:52:30:A3:37:61:30:A9:5A:42:63:E0:21:2F:D6:70:63:07:96:6F:27:A7:78:12:08:02:7A:8B',
keyUsage: undefined,
serialNumber: '147D36C1C2F74206DE9FAB5F2226D78ADB00A426'
}`,
);
});
Deno.test("X509Certificate validFromDate validToDate", function () {
const x509 = new X509Certificate(pemBuffer);
assertEquals(
x509.validFromDate,
new Date("2022-09-03T21:40:37.000Z"),
);
assertEquals(
x509.validToDate,
new Date("2296-06-17T21:40:37.000Z"),
);
});
// https://github.com/denoland/deno/issues/27211
Deno.test("X509Certificate publicKey for Ed25519 cert", function () {
const ed25519Cert = "-----BEGIN CERTIFICATE-----\n" +
"MIIBoTCCAVOgAwIBAgIUde5G4y+mtbb0eRISc7vnINRbSXkwBQYDK2VwMEUxCzAJ\n" +
"BgNVBAYTAkNaMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5l\n" +
"dCBXaWRnaXRzIFB0eSBMdGQwIBcNMjIxMDExMTIyMTUzWhgPMjEyMjA5MTcxMjIx\n" +
"NTNaMEUxCzAJBgNVBAYTAkNaMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQK\n" +
"DBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwKjAFBgMrZXADIQCUFn0ZKG9tAS3L\n" +
"Joaz7Q13hq6sfsRGrpQ4i9cZvn+1cKNTMFEwHQYDVR0OBBYEFAATzoAtBcYTcOdY\n" +
"jkcQqsWXipnSMB8GA1UdIwQYMBaAFAATzoAtBcYTcOdYjkcQqsWXipnSMA8GA1Ud\n" +
"EwEB/wQFMAMBAf8wBQYDK2VwA0EApfw+9jSO0x0IorDfdr5ZVGRBVgrfrd9XhxqQ\n" +
"Krphj6cA4Ls9aMYAHf5w+OW9D/t3a9p6mYm78AKIdBsPEtT1AQ==\n" +
"-----END CERTIFICATE-----\n";
const ed25519Spki = "-----BEGIN PUBLIC KEY-----\n" +
"MCowBQYDK2VwAyEAlBZ9GShvbQEtyyaGs+0Nd4aurH7ERq6UOIvXGb5/tXA=\n" +
"-----END PUBLIC KEY-----\n";
const x509 = new X509Certificate(ed25519Cert);
const pubkey = x509.publicKey;
assertEquals(pubkey.type, "public");
assertEquals(pubkey.asymmetricKeyType, "ed25519");
// Verify extracted key matches the standalone SPKI
const spkiKey = createPublicKey(ed25519Spki);
const x509Der = pubkey.export({ type: "spki", format: "der" });
const spkiDer = spkiKey.export({ type: "spki", format: "der" });
assertEquals(Buffer.compare(x509Der, spkiDer), 0);
});
// https://github.com/denoland/deno/issues/27211
Deno.test("X509Certificate publicKey for P-521 cert", function () {
const p521Cert = "-----BEGIN CERTIFICATE-----\n" +
"MIIBkDCB8wIJALGXk5Wy5tmGMAoGCCqGSM49BAMCMA0xCzAJBgNVBAYTAkNaMB4X\n" +
"DTIyMTAxMTEyMjUzNFoXDTIzMTAwNjEyMjUzNFowDTELMAkGA1UEBhMCQ1owgZsw\n" +
"EAYHKoZIzj0CAQYFK4EEACMDgYYABAFekaDUR+XoIoPU4FOQihwn9h+l1u0ZarPy\n" +
"2WSp0CiQmT/9cekQcNkIMMMvFQr1Hfwv6Mb+OY1Pm6Lrbf3sHMe1qAG6LvS/oVTz\n" +
"JMyjaSTxr4VpwIRzS9QyrF0wLcvgZjQWTxrRMFrKHfFb9ijfMHCHO7bN3S3nUzyJ\n" +
"++zut1d9rfnHOTAKBggqhkjOPQQDAgOBiwAwgYcCQgCfBR/x6atEB5KAaYmNOiKm\n" +
"OHhQISZU62ayPDipxsXf9vh4OK5WDdI4SmC1du07kAlwa2tFVSvz7vkMXGGXVYBr\n" +
"PQJBSjIXjpo07m26F0Jmv0OVX2on98+GN7xP8pRCviAuQj8UWKIQvwnj3esymVWb\n" +
"kmEjhnWo8H38/2wddwksoxHvinU=\n" +
"-----END CERTIFICATE-----\n";
const x509 = new X509Certificate(p521Cert);
const pubkey = x509.publicKey;
assertEquals(pubkey.type, "public");
assertEquals(pubkey.asymmetricKeyType, "ec");
assertEquals(pubkey.asymmetricKeyDetails, { namedCurve: "secp521r1" });
});
const certPem = `-----BEGIN CERTIFICATE-----
MIID6DCCAtCgAwIBAgIUFH02wcL3Qgben6tfIibXitsApCYwDQYJKoZIhvcNAQEL
BQAwejELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQswCQYDVQQHDAJTRjEPMA0G
A1UECgwGSm95ZW50MRAwDgYDVQQLDAdOb2RlLmpzMQwwCgYDVQQDDANjYTExIDAe
BgkqhkiG9w0BCQEWEXJ5QHRpbnljbG91ZHMub3JnMCAXDTIyMDkwMzIxNDAzN1oY
DzIyOTYwNjE3MjE0MDM3WjB9MQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExCzAJ
BgNVBAcMAlNGMQ8wDQYDVQQKDAZKb3llbnQxEDAOBgNVBAsMB05vZGUuanMxDzAN
BgNVBAMMBmFnZW50MTEgMB4GCSqGSIb3DQEJARYRcnlAdGlueWNsb3Vkcy5vcmcw
ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDUVjIK+yDTgnCT3CxChO0E
37q9VuHdrlKeKLeQzUJW2yczSfNzX/0zfHpjY+zKWie39z3HCJqWxtiG2wxiOI8c
3WqWOvzVmdWADlh6EfkIlg+E7VC6JaKDA+zabmhPvnuu3JzogBMnsWl68lCXzuPx
deQAmEwNtqjrh74DtM+Ud0ulb//Ixjxo1q3rYKu+aaexSramuee6qJta2rjrB4l8
B/bU+j1mDf9XQQfSjo9jRnp4hiTFdBl2k+lZzqE2L/rhu6EMjA2IhAq/7xA2MbLo
9cObVUin6lfoo5+JKRgT9Fp2xEgDOit+2EA/S6oUfPNeLSVUqmXOSWlXlwlb9Nxr
AgMBAAGjYTBfMF0GCCsGAQUFBwEBBFEwTzAjBggrBgEFBQcwAYYXaHR0cDovL29j
c3Aubm9kZWpzLm9yZy8wKAYIKwYBBQUHMAKGHGh0dHA6Ly9jYS5ub2RlanMub3Jn
L2NhLmNlcnQwDQYJKoZIhvcNAQELBQADggEBAMM0mBBjLMt9pYXePtUeNO0VTw9y
FWCM8nAcAO2kRNwkJwcsispNpkcsHZ5o8Xf5mpCotdvziEWG1hyxwU6nAWyNOLcN
G0a0KUfbMO3B6ZYe1GwPDjXaQnv75SkAdxgX5zOzca3xnhITcjUUGjQ0fbDfwFV5
ix8mnzvfXjDONdEznVa7PFcN6QliFUMwR/h8pCRHtE5+a10OSPeJSrGG+FtrGnRW
G1IJUv6oiGF/MvWCr84REVgc1j78xomGANJIu2hN7bnD1nEMON6em8IfnDOUtynV
9wfWTqiQYD5Zifj6WcGa0aAHMuetyFG4lIfMAHmd3gaKpks7j9l26LwRPvI=
-----END CERTIFICATE-----
`;
const x509KeyPem = `-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA1FYyCvsg04Jwk9wsQoTtBN+6vVbh3a5Snii3kM1CVtsnM0nz
c1/9M3x6Y2Psylont/c9xwialsbYhtsMYjiPHN1qljr81ZnVgA5YehH5CJYPhO1Q
uiWigwPs2m5oT757rtyc6IATJ7FpevJQl87j8XXkAJhMDbao64e+A7TPlHdLpW//
yMY8aNat62CrvmmnsUq2prnnuqibWtq46weJfAf21Po9Zg3/V0EH0o6PY0Z6eIYk
xXQZdpPpWc6hNi/64buhDIwNiIQKv+8QNjGy6PXDm1VIp+pX6KOfiSkYE/RadsRI
AzorfthAP0uqFHzzXi0lVKplzklpV5cJW/TcawIDAQABAoIBAAvbtHfAhpjJVBgt
15rvaX04MWmZjIugzKRgib/gdq/7FTlcC+iJl85kSUF7tyGl30n62MxgwqFhAX6m
hQ6HMhbelrFFIhGbwbyhEHfgwROlrcAysKt0pprCgVvBhrnNXYLqdyjU3jz9P3LK
TY3s0/YMK2uNFdI+PTjKH+Z9Foqn9NZUnUonEDepGyuRO7fLeccWJPv2L4CR4a/5
ku4VbDgVpvVSVRG3PSVzbmxobnpdpl52og+T7tPx1cLnIknPtVljXPWtZdfekh2E
eAp2KxCCHOKzzG3ItBKsVu0woeqEpy8JcoO6LbgmEoVnZpgmtQClbBgef8+i+oGE
BgW9nmECgYEA8gA63QQuZOUC56N1QXURexN2PogF4wChPaCTFbQSJXvSBkQmbqfL
qRSD8P0t7GOioPrQK6pDwFf4BJB01AvkDf8Z6DxxOJ7cqIC7LOwDupXocWX7Q0Qk
O6cwclBVsrDZK00v60uRRpl/a39GW2dx7IiQDkKQndLh3/0TbMIWHNcCgYEA4J6r
yinZbLpKw2+ezhi4B4GT1bMLoKboJwpZVyNZZCzYR6ZHv+lS7HR/02rcYMZGoYbf
n7OHwF4SrnUS7vPhG4g2ZsOhKQnMvFSQqpGmK1ZTuoKGAevyvtouhK/DgtLWzGvX
9fSahiq/UvfXs/z4M11q9Rv9ztPCmG1cwSEHlo0CgYEAogQNZJK8DMhVnYcNpXke
7uskqtCeQE/Xo06xqkIYNAgloBRYNpUYAGa/vsOBz1UVN/kzDUi8ezVp0oRz8tLT
J5u2WIi+tE2HJTiqF3UbOfvK1sCT64DfUSCpip7GAQ/tFNRkVH8PD9kMOYfILsGe
v+DdsO5Xq5HXrwHb02BNNZkCgYBsl8lt33WiPx5OBfS8pu6xkk+qjPkeHhM2bKZs
nkZlS9j0KsudWGwirN/vkkYg8zrKdK5AQ0dqFRDrDuasZ3N5IA1M+V88u+QjWK7o
B6pSYVXxYZDv9OZSpqC+vUrEQLJf+fNakXrzSk9dCT1bYv2Lt6ox/epix7XYg2bI
Z/OHMQKBgQC2FUGhlndGeugTJaoJ8nhT/0VfRUX/h6sCgSerk5qFr/hNCBV4T022
x0NDR2yLG6MXyqApJpG6rh3QIDElQoQCNlI3/KJ6JfEfmqrLLN2OigTvA5sE4fGU
Dp/ha8OQAx95EwXuaG7LgARduvOIK3x8qi8KsZoUGJcg2ywurUbkWA==
-----END RSA PRIVATE KEY-----
`;
const caPem = `-----BEGIN CERTIFICATE-----
MIIDlDCCAnygAwIBAgIUSrFsjf1qfQ0t/KvfnEsOksatAikwDQYJKoZIhvcNAQEL
BQAwejELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQswCQYDVQQHDAJTRjEPMA0G
A1UECgwGSm95ZW50MRAwDgYDVQQLDAdOb2RlLmpzMQwwCgYDVQQDDANjYTExIDAe
BgkqhkiG9w0BCQEWEXJ5QHRpbnljbG91ZHMub3JnMCAXDTIyMDkwMzIxNDAzN1oY
DzIyOTYwNjE3MjE0MDM3WjB6MQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExCzAJ
BgNVBAcMAlNGMQ8wDQYDVQQKDAZKb3llbnQxEDAOBgNVBAsMB05vZGUuanMxDDAK
BgNVBAMMA2NhMTEgMB4GCSqGSIb3DQEJARYRcnlAdGlueWNsb3Vkcy5vcmcwggEi
MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDNvf4OGGep+ak+4DNjbuNgy0S/
AZPxahEFp4gpbcvsi9YLOPZ31qpilQeQf7d27scIZ02Qx1YBAzljxELB8H/ZxuYS
cQK0s+DNP22xhmgwMWznO7TezkHP5ujN2UkbfbUpfUxGFgncXeZf9wR7yFWppeHi
RWNBOgsvY7sTrS12kXjWGjqntF7xcEDHc7h+KyF6ZjVJZJCnP6pJEQ+rUjd51eCZ
Xt4WjowLnQiCS1VKzXiP83a++Ma1BKKkUitTR112/Uwd5eGoiByhmLzb/BhxnHJN
07GXjhlMItZRm/jfbZsx1mwnNOO3tx4r08l+DaqkinIadvazs+1ugCaKQn8xAgMB
AAGjEDAOMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAFqG0RXURDam
56x5accdg9sY5zEGP5VQhkK3ZDc2NyNNa25rwvrjCpO+e0OSwKAmm4aX6iIf2woY
wF2f9swWYzxn9CG4fDlUA8itwlnHxupeL4fGMTYb72vf31plUXyBySRsTwHwBloc
F7KvAZpYYKN9EMH1S/267By6H2I33BT/Ethv//n8dSfmuCurR1kYRaiOC4PVeyFk
B3sj8TtolrN0y/nToWUhmKiaVFnDx3odQ00yhmxR3t21iB7yDkko6D8Vf2dVC4j/
YYBVprXGlTP/hiYRLDoP20xKOYznx5cvHPJ9p+lVcOZUJsJj/Iy750+2n5UiBmXt
lz88C25ucKA=
-----END CERTIFICATE-----
`;
Deno.test("X509Certificate toString and toJSON", function () {
const x509 = new X509Certificate(certPem);
const pemStr = x509.toString();
assert(pemStr.startsWith("-----BEGIN CERTIFICATE-----\n"));
assert(pemStr.endsWith("-----END CERTIFICATE-----\n"));
assertEquals(x509.toJSON(), x509.toString());
});
Deno.test("X509Certificate raw", function () {
const x509 = new X509Certificate(certPem);
const raw = x509.raw;
assert(Buffer.isBuffer(raw));
assert(raw.length > 0);
});
Deno.test("X509Certificate subjectAltName", function () {
const x509 = new X509Certificate(certPem);
assertEquals(x509.subjectAltName, undefined);
});
Deno.test("X509Certificate checkIP", function () {
const x509 = new X509Certificate(certPem);
assertEquals(x509.checkIP("127.0.0.1"), undefined);
assertEquals(x509.checkIP("::"), undefined);
});
Deno.test("X509Certificate checkIssued", function () {
const x509 = new X509Certificate(certPem);
const caCert = new X509Certificate(caPem);
assertEquals(x509.checkIssued(caCert), true);
assertEquals(x509.checkIssued(x509), false);
assertThrows(
() => (x509 as any).checkIssued({}),
Error,
);
});
Deno.test("X509Certificate checkPrivateKey", function () {
const x509 = new X509Certificate(certPem);
const privKey = createPrivateKey(x509KeyPem);
assertEquals(x509.checkPrivateKey(privKey), true);
assertThrows(
() => (x509 as any).checkPrivateKey(x509.publicKey),
Error,
);
});