summaryrefslogtreecommitdiffstats
path: root/toolkit/identity/tests/unit/test_crypto_service.js
blob: 561c3804a7f0e7fa27847f9731a37872f32f165f (plain)
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
/* Any copyright is dedicated to the Public Domain.
   http://creativecommons.org/publicdomain/zero/1.0/ */

"use strict";

Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import('resource://gre/modules/identity/LogUtils.jsm');

const idService = Cc["@mozilla.org/identity/crypto-service;1"]
                    .getService(Ci.nsIIdentityCryptoService);

const ALG_DSA = "DS160";
const ALG_RSA = "RS256";

const BASE64_URL_ENCODINGS = [
  // The vectors from RFC 4648 are very silly, but we may as well include them.
  ["", ""],
  ["f", "Zg=="],
  ["fo", "Zm8="],
  ["foo", "Zm9v"],
  ["foob", "Zm9vYg=="],
  ["fooba", "Zm9vYmE="],
  ["foobar", "Zm9vYmFy"],

  // It's quite likely you could get a string like this in an assertion audience
  ["i-like-pie.com", "aS1saWtlLXBpZS5jb20="],

  // A few extra to be really sure
  ["andré@example.com", "YW5kcsOpQGV4YW1wbGUuY29t"],
  ["πόλλ' οἶδ' ἀλώπηξ, ἀλλ' ἐχῖνος ἓν μέγα",
   "z4DPjM67zrsnIM6_4by2zrQnIOG8gM67z47PgM63zr4sIOG8gM67zrsnIOG8kM-H4b-Wzr3Ov8-CIOG8k869IM68zq3Os86x"],
];

// When the output of an operation is a
function do_check_eq_or_slightly_less(x, y) {
  do_check_true(x >= y - (3 * 8));
}

function test_base64_roundtrip() {
  let message = "Attack at dawn!";
  let encoded = idService.base64UrlEncode(message);
  let decoded = base64UrlDecode(encoded);
  do_check_neq(message, encoded);
  do_check_eq(decoded, message);
  run_next_test();
}

function test_dsa() {
  idService.generateKeyPair(ALG_DSA, function (rv, keyPair) {
    log("DSA generateKeyPair finished ", rv);
    do_check_true(Components.isSuccessCode(rv));
    do_check_eq(typeof keyPair.sign, "function");
    do_check_eq(keyPair.keyType, ALG_DSA);
    do_check_eq_or_slightly_less(keyPair.hexDSAGenerator.length, 1024 / 8 * 2);
    do_check_eq_or_slightly_less(keyPair.hexDSAPrime.length, 1024 / 8 * 2);
    do_check_eq_or_slightly_less(keyPair.hexDSASubPrime.length, 160 / 8 * 2);
    do_check_eq_or_slightly_less(keyPair.hexDSAPublicValue.length, 1024 / 8 * 2);
    // XXX: test that RSA parameters throw the correct error

    log("about to sign with DSA key");
    keyPair.sign("foo", function (rv2, signature) {
      log("DSA sign finished ", rv2, signature);
      do_check_true(Components.isSuccessCode(rv2));
      do_check_true(signature.length > 1);
      // TODO: verify the signature with the public key
      run_next_test();
    });
  });
}

function test_rsa() {
  idService.generateKeyPair(ALG_RSA, function (rv, keyPair) {
    log("RSA generateKeyPair finished ", rv);
    do_check_true(Components.isSuccessCode(rv));
    do_check_eq(typeof keyPair.sign, "function");
    do_check_eq(keyPair.keyType, ALG_RSA);
    do_check_eq_or_slightly_less(keyPair.hexRSAPublicKeyModulus.length,
                                 2048 / 8);
    do_check_true(keyPair.hexRSAPublicKeyExponent.length > 1);

    log("about to sign with RSA key");
    keyPair.sign("foo", function (rv2, signature) {
      log("RSA sign finished ", rv2, signature);
      do_check_true(Components.isSuccessCode(rv2));
      do_check_true(signature.length > 1);
      run_next_test();
    });
  });
}

function test_base64UrlEncode() {
  for (let [source, target] of BASE64_URL_ENCODINGS) {
    do_check_eq(target, idService.base64UrlEncode(source));
  }
  run_next_test();
}

function test_base64UrlDecode() {
  let utf8Converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"]
                        .createInstance(Ci.nsIScriptableUnicodeConverter);
  utf8Converter.charset = "UTF-8";

  // We know the encoding of our inputs - on conversion back out again, make
  // sure they're the same.
  for (let [source, target] of BASE64_URL_ENCODINGS) {
    let result = utf8Converter.ConvertToUnicode(base64UrlDecode(target));
    result += utf8Converter.Finish();
    do_check_eq(source, result);
  }
  run_next_test();
}

add_test(test_base64_roundtrip);
add_test(test_dsa);
add_test(test_rsa);
add_test(test_base64UrlEncode);
add_test(test_base64UrlDecode);

function run_test() {
  run_next_test();
}