JavaScript crypto

Non-standard
This feature is non-standard and is not on a standards track. Do not use it on production sites facing the Web: it will not work for every user. There may also be large incompatibilities between implementations and the behavior may change in the future.

Deprecated
This feature has been removed from the Web standards. Though some browsers may still support it, it is in the process of being dropped. Do not use it in old or new projects. Pages or Web apps using it may break at any time.

Warning: The features mentioned in this article are deleted proprietary Mozilla extensions, and are not supported in any other browser. They won't work in Firefox 34 or later. Use <keygen> or the future Web Crypto API instead.

Using the Mozilla crypto object from JavaScript

Mozilla defines a special JavaScript object to allow web pages access to certain cryptographic-related services. These services are a balance between the functionality web pages need and the requirement to protect users from malicious web sites. Most of these services are available via the DOM window object as window.crypto.

Services are provided to enable: smart card events, generating certificate requests, importing user certs, generating random numbers, logging out of your tokens, and signing text.

Handling smart card events

Web sites can make themselves more SmartCard friendly by listening for SmartCard insertion and removal events. To enable your document to receive these events, you must first tell the crypto system you are interested by setting window.crypto.enableSmartCardEvents to true. You can then register event handlers for these events with the document.addEventListener() method.

Two smart card related events are generated: smartcard-insert when SmartCards are inserted, and smartcard-remove when SmartCards are removed.

Web sites which use SSL clientAuth login could use the following code to refresh the page on token insertions and removals:

<!DOCTYPE html>
<p>...
<script>
function onSmartCardChange() {
  window.location.reload();
}
function register() {
  window.crypto.enableSmartCardEvents = true;
  document.addEventListener("smartcard-insert", onSmartCardChange, false);
  document.addEventListener("smartcard-remove", onSmartCardChange, false);
}
function deregister() {
  document.removeEventListener("smartcard-insert", onSmartCardChange, false);
  document.removeEventListener("smartcard-remove", onSmartCardChange, false);
}
document.body.onload = register;
document.body.onunload = deregister;
</script>

With the above example, your web site will automatically reload anytime a SmartCard is inserted or removed. This allows the page to automatically login and logout based on the presence of the SmartCard.

Generating keys and issuing user certificates

There are several crypto object methods used in generating keys for certificates: generateCRMFRequest(), importUserCertificates().

The generateCRMFRequest() function generates a key and creates a CRMF Request object. This object can be passed to a CA using a webform.

The importUserCertificates() function loads certificates into the NSS database or SmartCard if the corresponding key is found there.

The popChallengeResponse() function is not implemented.

Overview of the new cert issuing process

  1. User fills out enrollment form
  2. User action initiates script
  3. Script calls key generation method (generateCRMFRequest)
  4. Signing and Encryption keys are generated
  5. Encryption Private Key is wrapped with public key of Key Recovery Authority (KRA) (passed in in the form of a certificate as part of the script, and checked against a pre-installed certificate copy in the local certificate database)
  6. The public keys, wrapped encryption private key, and text string from the script (possibly containing naming or enrollment info) are signed by the user
  7. Signed blob is returned to the script
  8. Script submits signed blob and any other necessary info to the CA/RA
  9. CA/RA verifies signature on signed blob
  10. CA/RA validates identity of user
  11. CA/RA sends wrapped encryption private key to KRA
  12. KRA sends escrow verification back to CA
  13. CA creates and signs certificates
  14. CA sends certificates back to the user (importUserCertificates)

Typical use

The CA's enrollment page could look something like this:

<!DOCTYPE html>
<h2>Request a cert</h2>
<form name="ReqForm" method="post" action="http://your.ra.site.org">
<p><input type=hidden name=cert_request value="">
<p>Name: <input type=text name=name value="">
<p>Password: <input type=password name="password" value="">
<p><input type=submit Name="Send" value="Submit">
</form>
<script>
/* the following values could be filled in by the server CGI */
var authenticator = "server_magic";
var keyTransportCert = null;
var crmfObject = null;
var form = document.forms[0];
function validate()
{
  // generate keys for nsm.
  if (typeof(crypto.version) != "undefined") {
    crmfObject = crypto.generateCRMFRequest(
      "CN=" + form.name.value,
      form.password.value,
      authenticator,
      keyTransportCert,
      "setCRMFRequest();",
      1024,
      null,
      "rsa-dual-use");
  }
  return false;
}
function setCRMFRequest()
{
  form.cert_request.value = crmfObject.request;
  form.submit();
}
form.onsubmit = validate;
</script>

On completion of the request, the CA may submit a page that looks something like this:

<!DOCTYPE html>
<h2>Certificate Request Successful</h2>
<p>Hit 'load' to load your certificate</p>
<form name="ReqForm">
<p><input type=submit Name="Load" value="Submit"></p>
</form>
<script>
/* the following values could be filled in by the server CGI */
var nickname= "MyCertNickname";
var cert = "Mkjflakdjfiwjflaksufklasf ...";
var forceBackup = false;
function LoadCertificate()
{
  window.crypto.importUserCertificates(nickname, cert, forceBackup);
  return false;
}
document.forms[0].onsubmit = LoadCertificate;
</script>

Signing text

DOMString signText(DOMString stringToSign,
                   DOMString caOption /* ... */);

Loading PKCS #11 modules

long deletemodule(DOMString moduleName);
long addmodule(DOMString moduleName,
               DOMString libraryFullPath,
               long cryptoMechanismFlags,
               long cipherFlags);

Loads or removes a new PKCS #11 module. In the add case, the module will be placed in the NSS secmod.db database and will be loaded automatically on application restart. In the delete case, the module is removed from the NSS secmod.db. This function will issue a user prompt to confirm the operation before the add or delete actually occurs.

Parameters
moduleName
Name of the module.
libraryFullPath
The filename of the library prepended with its full path.
cryptoMechanismFlags
A bit vector indicating all cryptographic mechanisms should be turned on by default (see below).
cipherFlags
A bit vector indicating all SSL or S/MIME cipher functions supported by the module (see below).

Mechanism flag definitions

In general, most tokens should not set any of the cipher flags. Setting these flags means you want your token to supply the default implementation for these functions. Normally Mozilla uses its own internal module to supply these functions. These flags override that preference. If you choose to implement these flags, your module must supply the following additional functions for each flag:

  • PKCS11_MECH_FLAG: must support CKM_RSA_PKCS and CKM_RSA_X_509 and the following functions: C_WRAPKEY, C_ENCRYPT, C_SIGN, C_DECRYPT, C_UNWRAPKEY, C_VERIFYRECOVER, C_VERIFY, C_GENERATEKEYPAIR (2048, 1024, 512) size
  • PKCS11_MECH_DSA_FLAG: must support CKM_DSA and the following functions: C_SIGN, C_VERIFY, C_GENERATEKEYPAIR
  • PKCS11_MECH_RC2_FLAG: must support CKM_RC2_CBC and CKM_RC2_ECB and the following functions: C_GENERATEKEY, C_ENCRYPT, C_DECRYPT, C_WRAPKEY, C_UNWRAPKEY
  • PKCS11_MECH_RC4_FLAG: must support CKM_RC4_CBC and CKM_RC4_ECB and the following functions: C_GENERATEKEY, C_ENCRYPT, C_DECRYPT, C_WRAPKEY, C_UNWRAPKEY
  • PKCS11_MECH_DES_FLAG: must support CKM_CPMF_CBC, CKM_DES_CBC, CKM_DES3_CBC, CKM_CPMF_ECB, CKM_DES_ECB, CKM_DES3_ECB and the following functions: C_GENERATEKEY, C_ENCRYPT, C_DECRYPT, C_WRAPKEY, C_UNWRAPKEY
  • PKCS11_MECH_DH_FLAG: must support CKM_DH_PKCS_DERIVE and CKM_DH_KEY_PAIR_GEN and the following functions: C_DERIVEKEY, C_GENERATEKEYPAIR
  • PKCS11_MECH_MD5_FLAG: Hashing must be able to function without authentication.
  • PKCS11_MECH_SHA1_FLAG: Hashing must be able to function without authentication.
  • PKCS11_MECH_MD2_FLAG: Hashing must be able to function without authentication.*
  • PKCS11_RANDOM_FLAG: Use token's Random Number Generator.
    • Warning: Must be able to use without authentication. Many hardware random number generators are not as secure as the Netscape internal one. Do not select this value unless you can show that your random number generator is secure. Even so, it's highly discouraged.
  • PKCS11_PUB_READABLE_CERT_FLAG: This is the only flag most smart tokens should turn on. You can turn this flag on if:
    • the certs on your token can be read without authentication and,
    • the public key on your token can be found by ID, MODULUS, or VALUE and all your private keys have the associated public key.
      • Turning this flag on will illuminate a large number of password prompts for your token when looking up certs in Communicator.
PKCS11_MECH_RSA_FLAG           =  0x1<<0;
PKCS11_MECH_DSA_FLAG           =  0x1<<1;
PKCS11_MECH_RC2_FLAG           =  0x1<<2;
PKCS11_MECH_RC4_FLAG           =  0x1<<3;
PKCS11_MECH_DES_FLAG           =  0x1<<4;
PKCS11_MECH_DH_FLAG            =  0x1<<5; //Diffie-Hellman
PKCS11_MECH_SKIPJACK_FLAG      =  0x1<<6; //SKIPJACK algorithm as in Fortezza cards
PKCS11_MECH_RC5_FLAG           =  0x1<<7;
PKCS11_MECH_SHA1_FLAG          =  0x1<<8;
PKCS11_MECH_MD5_FLAG           =  0x1<<9;
PKCS11_MECH_MD2_FLAG           =  0x1<<10;
PKCS11_MECH_RANDOM_FLAG        =  0x1<<27; //Random number generator
PKCS11_PUB_READABLE_CERT_FLAG  =  0x1<<28; //Stored certs can be read off the token w/o logging in
PKCS11_DISABLE_FLAG            =  0x1<<30; //tell Mozilla to disable this slot by default

Cipher flags

Reserved

Important for CryptoMechanismFlags

0x1<<11, 0x1<<12, ... , 0x1<<26, 0x1<<29, and 0x1<<31 are reserved for internal use in Mozilla. Therefore, these bits should always be set to 0; otherwise, Mozilla might exhibit unpredictable behavior.

Important for CipherFlags

All values are reserved for internal use in Mozilla. Therefore, this flag should always be set to 0; otherwise, Mozilla might exhibit unpredictable behavior.

Example of CryptoMechanismFlags and CipherFlags

pkcs11MechanismFlags = PKCS11_MECH_DSA_FLAG | PKCS11_MECH_SKIPJACK_FLAG | PKCS11_MECH_RANDOM_FLAG;
pkcs11CipherFlags = 0;

Return Values

JS_OK_ADD_MODULE                  = 3   // Successfully added a module
JS_ERR_OTHER                      = -1  // Errors other than the following
JS_ERR_USER_CANCEL_ACTION         = -2  // User aborted an action
JS_ERR_INCORRECT_NUM_OF_ARGUMENTS = -3  // Calling a method w/ incorrect # of
                                        // arguments
JS_ERR_ADD_MODULE                 = -5  // Error adding a module
JS_ERR_BAD_MODULE_NAME            = -6  // The module name is invalid
JS_ERR_ADD_MODULE_DUPLICATE       = -10 // The module being installed has the
                                        // same name as one of the modules that
                                        // has already been installed

Miscellaneous

DOMString random(in long numBytes);

UnimplementedYou can use window.crypto.getRandomValues instead.

void logout();

Logs the user out of all the cryptographic tokens. The next private operation on any token will require the user password again. The SSL session cache is also cleared (from Firefox 1.5 upward).

This means the master password will be requested the next time a saved password will be accessed after this function is called. This also means the SSL client authentication state will be erased for SSL sites with client authentication, and a client certificate prompt will appear again the next time the user connects to the site.

Note: This function provides a convenient way to erase the SSL session state at the browser level, but in order to really guarantee that the state is erased, it is more secure to do it on the server side whenever possible.

void disableRightClick();

Unimplemented

Document Tags and Contributors

 Last updated by: javier1nc,