Javascript API for Client Certificate Management

## Netscape Personal Security Manager

## JavaScript API for Client Certificate Management

Version 0.3 - 10/27/1999
Comments to: psmfeedback@netscape.com

This document describes a new JavaScript API for performing user certificate management operations within a client. The JavaScript runs in the context of a web page operated by a Certificate Authority (CA) or Registration Authority (RA). The API allows the CA or RA to instruct the client to perform PKI operations such as key generation, certificate request generation, key escrow, import of user certificates, key recovery, and revocation requests.

These properties and methods reflect behavior currently implemented in Personal Security Manager 1.0.

The messages imported by or generated by these JavaScript methods are defined in the CRMF, CMMF, and CMC internet drafts.

## Overview of New Cert Issuing Process

1. User fills out enrollment form
2. User action initiates script
3. Script calls key generation method
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 Communicator

## JavaScript API

### Properties

`crypto.algorithms.dh.keySizes`
`crypto.algorithms.dsa.keySizes`
`crypto.algorithms.rsa.signing.keySizes`
`crypto.algorithms.rsa.keyEx.keySizes`

`keySizes` is an an array that describes the available key sizes for the particular algorithms and operations.

The table below describes the key sizes that will be supported in the US and Export versions of Communicator.

Algorithm | US Version Key Sizes | Export Version Key Sizes
DSA Signing Only | 1024, 2048 | 1024, 2048
RSA Signing Only | 1024, 2048 | 1024, 2048
RSA Encryption Only | 1024, 2048 | 512,1024
RSA Dual Use Signing And Encryption | 1024, 2048 | 512,1024
DH Key Exchange | 1024, 2048 | 512,1024

### Methods

#### generateCRMFRequest()

`crmfObject = crypto.generateCRMFRequest("requestedDN", "regToken", "authenticator","escrowAuthorityCert", "KeyGen Done Code",keySize1, "keyParams1", "keyGenAlg1",..., keySizeN, "keyParamsN", "keyGenAlgN");`

This method will generate a sequence of CRMF requests that has N requests. One request for each key pair that is generated. The first three parameters will be applied to every request. the "escrowAuthorityCert" parameter will only be used for requests that pertain to a key that is being escrowed. After the "escrowAuthorityCert" parameter, the method takes some JavaScript code that is invoked when the CRMF request is ready. Finally, there are 1 or more sets of key generation arguments. Each key generation will be associated with its own request. All the requests will have the same DN.

Argument | Description
`"requestedDN"` | An RFC1485 formatted DN to include in the certificate request.
`"regToken"` | A value used to authenticate the user to the RA/CA.
`"authenticator"` | A value that the user can authenticate with in the future when their private key is not available. Can be used for key recovery or revocation requests.
`"escrowAuthorityCert"` | If this value is NULL, then no key escrow will be performed. This value specifies which KRA certificate should be used to wrap the private key being escrowed. The user will be prompted for confirmation whenever a key will be escrowed. Only key exchange keys will be escrowed. If a dual use key is being generated, it will not be escrowed. The value of this argument is a base-64 encoded certificate.
`"CRMF Generation Done Code"` | This parameter is JavaScript to execute when the CRMF generation is complete.
`keySizeN` | The size in bits of the Nth key to generate
`"keyParamsN"` | This string is an optional algorithm dependent parameter value. For Diffie-Hellman it is used to specify p and g parameters. For DSA, it will be used to specify pqg. If the key generation requires parameters and the value passed in is NULL, then the client will generate the parameters on its own. Currently, this value is ignored.
`"keyGenAlgN"` | Which algorithm the generated key will support. Acceptable values are (the mentioned values for keyUsage pertain to the keyUsage value of the Certificate Extension that will ultimately be in the issued certificate): "rsa-ex" - generate an RSA key for key exchange only (This will have keyEncipherment set for keyUsage.) "rsa-dual-use" - generate a single RSA key for both signing and encryption. (This will have digitalSignature, keyEncipherment, and nonRepudiation set for keyUsage.) "rsa-sign" - generate an RSA key for signing only. (This will have digitalSignature set for keyUsage.) "rsa-nonrepudiation" - generate a single RSA key for nonRepudiation only. (This will have non-repudiation set for keyUsage.) "rsa-sign-nonrepudiation" - generate a single RSA key use for both signing and nonRepudiation. (This will have both digitalSignature and nonRepudiation set for keyUsage.) "dsa-sign" - generate a single DSA key for signing only. (This will have digitalSignature set for keyUsage.) "dsa-nonrepudiation" - generate a single DSA key for nonRepudiation. (This will have nonRepudiation set for keyUsage.) "dsa-sign-nonrepudiation" - generate a single DSA key for signing and non-repudiation. (This will have digitalSignature and nonRepudiation set for keyUsage.)

The generateCRMFRequest() method will cause the user to be presented with a key generation dialog. The dialog describes the key generation process and gives the user the opportunity to cancel the operation.

The method generateCRMFRequest() will return an instance of a CRMF object. The JavaScript passed in as the `"CRMF Generation Done Code"` parameter should look at the attribute request of the returned object to get the result of the CRMF generation.

The string found by accessing `crmfObject.request` is the base-64 encoded CRMF message to be sent to the CA/RA, or an error string. The possible error strings are:

Error String | Description
"error:invalidParameter:XXX" | The parameter XXX was an invalid value.
"error:userCancel" | the user has canceled the key generation operation
"error:internalError" | the software encountered some internal error, such as out of memory

#### importUserCertificates()

`resultString = crypto.importUserCertificates("nicknameString", "certString", allowBackup)`

Argument | Description
`"nicknameString"` | This is the nickname that will be used to describe the certificate in the client's certificate management UI. It should serve to uniquely identify the certificate to the user. For example, "John Smith's VeriSign Class 3 Digital ID" or "John Smith's Ford ID Certificate". However, if this certificate has the same DN as one or more certificates that already exist in the user's certificate store, the nickname associated with the certificate(s) of the same DN in the certificate store is used, and the `"nicknameString"` parameter is ignored. If the string is null and no certificate with the same DN exists in the user's certificate store, Personal Security Manager uses the following pattern to derive the nickname: `<Common Name>'s <Issuer Name> ID`.
`"certRepString"` | This string is the CMMF Certification Response from the CA that contains the user's certificate(s). The response is base-64 encoded.
`allowBackup` | This is a Boolean argument. It allows the CA or RA to indicate to the client whether to force the user to back up a newly issued certificate (PKCS #12).

The importUserCertificates() method is used to import newly issued certificates for the user. The private key for the certificates must already reside in the user's personal private key database.

The request ID in the response being imported must match the request ID in the associated Certification Request or Recovery Request.

If the import operation succeeds, an empty string will be returned. If it fails, one of the following error strings will be returned:

Error String | Description
"error:userCancel" | The user canceled the import operation
"error:invalidCertificate" | One of the certificate packages was incorrectly formatted
"error:internalError" | The software encountered some internal error, such as out of memory
"error:invalidRequestID" | The request ID in the response message does not match any outstanding request

#### popChallengeResponse()

`resultString = crypto.popChallengeResponse("challengeString");`

Argument | Description
`"challengeString"` | A base-64 encoded CMMF POPODecKeyChallContent message. The current implementation does not conform to that defined in the CMMF draft, and we intend to change this implementation to that defined in the CMC RFC.. See below for the current implementation.

The resultString will either be a base-64 encoded POPODecKeyRespContent message, or one of the following error strings:

Error String | Description
"error:invalidParameter:XXX" | The parameter XXX was an invalid value.
"error:internalError" | the software encountered some internal error, such as out of memory

Challenge-Response Proof Of Possession

`Expected Input:`

`POPODecKeyChallContent ::= SEQUENCE OF Challenge`
`-- One Challenge per encryption key certification request (in the`
`-- same order as these requests appear in FullCertTemplates).`

`Challenge ::= SEQUENCE {`
`owf AlgorithmIdentifier OPTIONAL,`
`-- MUST be present in the first Challenge; MAY be omitted in any`
`-- subsequent Challenge in POPODecKeyChallContent (if omitted,`
`-- then the owf used in the immediately preceding Challenge is`
`-- to be used).`
`witness OCTET STRING,`
`-- the result of applying the one-way function (owf) to a`
`-- randomly-generated INTEGER, A. [Note that a different`
`-- INTEGER MUST be used for each Challenge.]`
`sender GeneralName,`
`-- the name of the sender.`
`key OCTET STRING,`
`-- the public key used to encrypt the challenge. This will allow`
`-- the client to find the appropriate key to do the decryption.`
`challenge OCTET STRING`
`-- the encryption (under the public key for which the cert.`
`-- request is being made) of Rand, where Rand is specified as`
`-- Rand ::= SEQUENCE {`
`-- int INTEGER,`
`-- - the randomly-generated INTEGER A (above)`
`-- senderHash OCTET STRING`
`-- - the result of applying the one-way function (owf) to`
`-- - the sender's general name`
`-- }`
`-- the size of "int" must be small enough such that "Rand" can be`
`-- contained within a single PKCS #1 encryption block.`
`}`

© Copyright 1999 Netscape Communications Corporation