One of the things that we wanted you to be able to use the PKI.js libraries for is the X.509 Certificates, including those with new extensions (like testing for OCSP MUST Staple or for testing other certificate processing libraries like was done in the Frankencert paper.
Here is an example of what that might look like:
function create_cert() { // #region Initial variables var sequence = Promise.resolve(); var cert_simpl = new org.pkijs.simpl.CERT(); var publicKey; var privateKey; // #endregion // #region Get a "crypto" extension var crypto = org.pkijs.getCrypto(); if(typeof crypto == "undefined") { alert("No WebCrypto extension found"); return; } // #endregion // #region Put a static values cert_simpl.serialNumber = new org.pkijs.asn1.INTEGER({ value: 1 }); cert_simpl.issuer.types_and_values.push(new org.pkijs.simpl.ATTR_TYPE_AND_VALUE({ type: "2.222.333", value: new org.pkijs.asn1.PRINTABLESTRING({ value: "RU" }) })); cert_simpl.issuer.types_and_values.push(new org.pkijs.simpl.ATTR_TYPE_AND_VALUE({ type: "2.222.444", value: new org.pkijs.asn1.PRINTABLESTRING({ value: "Test" }) })); cert_simpl.subject.types_and_values.push(new org.pkijs.simpl.ATTR_TYPE_AND_VALUE({ type: "2.222.333", value: new org.pkijs.asn1.PRINTABLESTRING({ value: "RU" }) })); cert_simpl.subject.types_and_values.push(new org.pkijs.simpl.ATTR_TYPE_AND_VALUE({ type: "2.222.444", value: new org.pkijs.asn1.PRINTABLESTRING({ value: "Test" }) })); cert_simpl.notBefore.value = new Date(); cert_simpl.notAfter.value = new Date(2016, 01, 01); cert_simpl.extensions = new Array(); // Extensions are not a part of certificate by default, it's an optional array // #region "BasicConstraints" extension var basic_constr = new org.pkijs.simpl.x509.BasicConstraints({ cA: true, pathLenConstraint: 3 }); cert_simpl.extensions.push(new org.pkijs.simpl.EXTENSION({ extnID: "2.5.29.19", critical: false, extnValue: basic_constr.toSchema().toBER(false), parsedValue: basic_constr // Parsed value for well-known extensions })); // #endregion // #region "KeyUsage" extension var bit_array = new ArrayBuffer(1); var bit_view = new Uint8Array(bit_array); bit_view[0] = bit_view[0] | 0x02; // Key usage "cRLSign" flag bit_view[0] = bit_view[0] | 0x04; // Key usage "keyCertSign" flag var key_usage = new org.pkijs.asn1.BITSTRING({ value_hex: bit_array }); cert_simpl.extensions.push(new org.pkijs.simpl.EXTENSION({ extnID: "2.5.29.15", critical: false, extnValue: key_usage.toBER(false), parsedValue: key_usage // Parsed value for well-known extensions })); // #endregion cert_simpl.signatureAlgorithm.algorithm_id = "1.2.840.113549.1.1.5"; // RSA + SHA-1 cert_simpl.signature.algorithm_id = cert_simpl.signatureAlgorithm.algorithm_id; // Must be the same value // #endregion // #region Create a new key pair sequence = sequence.then( function() { return crypto.generateKey({ name: "RSASSA-PKCS1-v1_5", modulusLength: 2048, publicExponent: new Uint8Array([0x01, 0x00, 0x01]), hash: { name: "sha-1" } }, true, ["encrypt", "decrypt", "sign", "verify"]); } ); // #endregion // #region Store new key in an interim variables sequence = sequence.then( function(keyPair) { publicKey = keyPair.publicKey; privateKey = keyPair.privateKey; }, function(error) { alert("Error during key generation: " + error); } ); // #endregion // #region Exporting public key into "subjectPublicKeyInfo" sequence = sequence.then( function() { return cert_simpl.subjectPublicKeyInfo.importKey(publicKey); } ); // #endregion // #region Signing final certificate sequence = sequence.then( function() { return cert_simpl.sign(privateKey); }, function(error) { alert("Error during exporting public key: " + error); } ); // #endregion sequence = sequence.then( function() { alert("Good result"); }, function(error) { alert("Error during signing: " + error); } ); sequence.then( function() { return cert_simpl.verify(); } ).then( function(result) { alert("Verification passed: " + result); }, function(error) { alert("Verification failed: " + eror); } ); }
As you can see the library is designed in such a way you are not limited to the creation of some static pre-conceived layouts of these structures, you can fairly easily construct any type of certificate (or any of the other supported message types).
At a later date (if it makes sense to do so) we may also decide to add a simple layer ontop of this that abstracts out the need to understand encoding concepts as well.
This layered approach ensures the library can be used to create real-applications without the need to hack up the underlying APIs enabling developers to avoid the need to understand low-level ASN.1 formats in detail.
Always response Warning: WebCrypto is not available
var crypto = org.pkijs.getCrypto();
if (typeof crypto === ‘undefined’) {
warn(‘WebCrypto is not available’);
// Don’t show any signature information
this._capability.resolve(emptyResult);
return;
}
What browser are you on? IE, for example does not support WebCrypto. We have another library webcrypto-liner that acts as a polyfil for such cases – https://github.com/PeculiarVentures/webcrypto-liner/
Also this is an old post, we have a new version of PKIjs (v2) that is based on ES6 that has a new API but it has over a thousand tests and is much more robust check it out.