|
1 /* Any copyright is dedicated to the Public Domain. |
|
2 http://creativecommons.org/publicdomain/zero/1.0/ */ |
|
3 |
|
4 "use strict"; |
|
5 |
|
6 Cu.import("resource://gre/modules/Services.jsm"); |
|
7 Cu.import("resource://gre/modules/XPCOMUtils.jsm"); |
|
8 Cu.import('resource://gre/modules/identity/LogUtils.jsm'); |
|
9 |
|
10 const idService = Cc["@mozilla.org/identity/crypto-service;1"] |
|
11 .getService(Ci.nsIIdentityCryptoService); |
|
12 |
|
13 const ALG_DSA = "DS160"; |
|
14 const ALG_RSA = "RS256"; |
|
15 |
|
16 const BASE64_URL_ENCODINGS = [ |
|
17 // The vectors from RFC 4648 are very silly, but we may as well include them. |
|
18 ["", ""], |
|
19 ["f", "Zg=="], |
|
20 ["fo", "Zm8="], |
|
21 ["foo", "Zm9v"], |
|
22 ["foob", "Zm9vYg=="], |
|
23 ["fooba", "Zm9vYmE="], |
|
24 ["foobar", "Zm9vYmFy"], |
|
25 |
|
26 // It's quite likely you could get a string like this in an assertion audience |
|
27 ["i-like-pie.com", "aS1saWtlLXBpZS5jb20="], |
|
28 |
|
29 // A few extra to be really sure |
|
30 ["andré@example.com", "YW5kcsOpQGV4YW1wbGUuY29t"], |
|
31 ["πόλλ' οἶδ' ἀλώπηξ, ἀλλ' ἐχῖνος ἓν μέγα", |
|
32 "z4DPjM67zrsnIM6_4by2zrQnIOG8gM67z47PgM63zr4sIOG8gM67zrsnIOG8kM-H4b-Wzr3Ov8-CIOG8k869IM68zq3Os86x"], |
|
33 ]; |
|
34 |
|
35 // When the output of an operation is a |
|
36 function do_check_eq_or_slightly_less(x, y) { |
|
37 do_check_true(x >= y - (3 * 8)); |
|
38 } |
|
39 |
|
40 function test_base64_roundtrip() { |
|
41 let message = "Attack at dawn!"; |
|
42 let encoded = idService.base64UrlEncode(message); |
|
43 let decoded = base64UrlDecode(encoded); |
|
44 do_check_neq(message, encoded); |
|
45 do_check_eq(decoded, message); |
|
46 run_next_test(); |
|
47 } |
|
48 |
|
49 function test_dsa() { |
|
50 idService.generateKeyPair(ALG_DSA, function (rv, keyPair) { |
|
51 log("DSA generateKeyPair finished ", rv); |
|
52 do_check_true(Components.isSuccessCode(rv)); |
|
53 do_check_eq(typeof keyPair.sign, "function"); |
|
54 do_check_eq(keyPair.keyType, ALG_DSA); |
|
55 do_check_eq_or_slightly_less(keyPair.hexDSAGenerator.length, 1024 / 8 * 2); |
|
56 do_check_eq_or_slightly_less(keyPair.hexDSAPrime.length, 1024 / 8 * 2); |
|
57 do_check_eq_or_slightly_less(keyPair.hexDSASubPrime.length, 160 / 8 * 2); |
|
58 do_check_eq_or_slightly_less(keyPair.hexDSAPublicValue.length, 1024 / 8 * 2); |
|
59 // XXX: test that RSA parameters throw the correct error |
|
60 |
|
61 log("about to sign with DSA key"); |
|
62 keyPair.sign("foo", function (rv, signature) { |
|
63 log("DSA sign finished ", rv, signature); |
|
64 do_check_true(Components.isSuccessCode(rv)); |
|
65 do_check_true(signature.length > 1); |
|
66 // TODO: verify the signature with the public key |
|
67 run_next_test(); |
|
68 }); |
|
69 }); |
|
70 } |
|
71 |
|
72 function test_rsa() { |
|
73 idService.generateKeyPair(ALG_RSA, function (rv, keyPair) { |
|
74 log("RSA generateKeyPair finished ", rv); |
|
75 do_check_true(Components.isSuccessCode(rv)); |
|
76 do_check_eq(typeof keyPair.sign, "function"); |
|
77 do_check_eq(keyPair.keyType, ALG_RSA); |
|
78 do_check_eq_or_slightly_less(keyPair.hexRSAPublicKeyModulus.length, |
|
79 2048 / 8); |
|
80 do_check_true(keyPair.hexRSAPublicKeyExponent.length > 1); |
|
81 |
|
82 log("about to sign with RSA key"); |
|
83 keyPair.sign("foo", function (rv, signature) { |
|
84 log("RSA sign finished ", rv, signature); |
|
85 do_check_true(Components.isSuccessCode(rv)); |
|
86 do_check_true(signature.length > 1); |
|
87 run_next_test(); |
|
88 }); |
|
89 }); |
|
90 } |
|
91 |
|
92 function test_base64UrlEncode() { |
|
93 for (let [source, target] of BASE64_URL_ENCODINGS) { |
|
94 do_check_eq(target, idService.base64UrlEncode(source)); |
|
95 } |
|
96 run_next_test(); |
|
97 } |
|
98 |
|
99 function test_base64UrlDecode() { |
|
100 let utf8Converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"] |
|
101 .createInstance(Ci.nsIScriptableUnicodeConverter); |
|
102 utf8Converter.charset = "UTF-8"; |
|
103 |
|
104 // We know the encoding of our inputs - on conversion back out again, make |
|
105 // sure they're the same. |
|
106 for (let [source, target] of BASE64_URL_ENCODINGS) { |
|
107 let result = utf8Converter.ConvertToUnicode(base64UrlDecode(target)); |
|
108 result += utf8Converter.Finish(); |
|
109 do_check_eq(source, result); |
|
110 } |
|
111 run_next_test(); |
|
112 } |
|
113 |
|
114 add_test(test_base64_roundtrip); |
|
115 add_test(test_dsa); |
|
116 add_test(test_rsa); |
|
117 add_test(test_base64UrlEncode); |
|
118 add_test(test_base64UrlDecode); |
|
119 |
|
120 function run_test() { |
|
121 run_next_test(); |
|
122 } |