diff --git a/toolkit/identity/IdentityCryptoService.cpp b/toolkit/identity/IdentityCryptoService.cpp index efa1e6c5615..08eea80fef5 100644 --- a/toolkit/identity/IdentityCryptoService.cpp +++ b/toolkit/identity/IdentityCryptoService.cpp @@ -65,6 +65,28 @@ Base64UrlEncodeImpl(const nsACString & utf8Input, nsACString & result) return NS_OK; } +nsresult +Base64UrlDecodeImpl(const nsACString & base64Input, nsACString & result) +{ + nsresult rv = Base64Decode(base64Input, result); + NS_ENSURE_SUCCESS(rv, rv); + + nsACString::char_type * out = result.BeginWriting(); + nsACString::size_type length = result.Length(); + // base64url encoding is defined in RFC 4648. It replaces the last two + // alphabet characters of base64 encoding with '-' and '_' respectively. + // Reverse that encoding here. + for (unsigned int i = 0; i < length; ++i) { + if (out[i] == '-') { + out[i] = '+'; + } else if (out[i] == '_') { + out[i] = '/'; + } + } + + return NS_OK; +} + #define DSA_KEY_TYPE_STRING (NS_LITERAL_CSTRING("DS160")) #define RSA_KEY_TYPE_STRING (NS_LITERAL_CSTRING("RS256")) @@ -239,6 +261,13 @@ IdentityCryptoService::Base64UrlEncode(const nsACString & utf8Input, return Base64UrlEncodeImpl(utf8Input, result); } +NS_IMETHODIMP +IdentityCryptoService::Base64UrlDecode(const nsACString & base64Input, + nsACString & result) +{ + return Base64UrlDecodeImpl(base64Input, result); +} + KeyPair::KeyPair(SECKEYPrivateKey * privateKey, SECKEYPublicKey * publicKey) : mPrivateKey(privateKey) , mPublicKey(publicKey) diff --git a/toolkit/identity/nsIIdentityCryptoService.idl b/toolkit/identity/nsIIdentityCryptoService.idl index 40eb9341d28..7efc776c179 100644 --- a/toolkit/identity/nsIIdentityCryptoService.idl +++ b/toolkit/identity/nsIIdentityCryptoService.idl @@ -38,13 +38,14 @@ interface nsIIdentitySignCallback; */ // "@mozilla.org/identity/crypto-service;1" -[scriptable, builtinclass, uuid(f087e6bc-dd33-4f6c-a106-dd786e052ee9)] +[scriptable, builtinclass, uuid(17e227c4-2c31-4167-9dd4-f55ddee6a53a)] interface nsIIdentityCryptoService : nsISupports { void generateKeyPair(in AUTF8String algorithm, in nsIIdentityKeyGenCallback callback); ACString base64UrlEncode(in AUTF8String toEncode); + ACString base64UrlDecode(in AUTF8String toDecode); }; /** diff --git a/toolkit/identity/tests/unit/test_crypto_service.js b/toolkit/identity/tests/unit/test_crypto_service.js index dc5a49b7168..0d92290922e 100644 --- a/toolkit/identity/tests/unit/test_crypto_service.js +++ b/toolkit/identity/tests/unit/test_crypto_service.js @@ -18,6 +18,15 @@ 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 = idService.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); @@ -61,6 +70,7 @@ function test_rsa() { }); } +add_test(test_base64_roundtrip); add_test(test_dsa); add_test(test_rsa);