UNPKG

pkijs

Version:

Public Key Infrastructure (PKI) is the basis of how identity and key management is performed on the web today. PKIjs is a pure JavaScript library implementing the formats that are used in PKI applications. It is built on WebCrypto and aspires to make it p

1,153 lines (1,064 loc) 265 kB
/* * Copyright (c) 2014, GMO GlobalSign * All rights reserved. * * Author 2014, Yury Strozhevsky <www.strozhevsky.com>. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * 3. Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. * */ ( function(in_window) { //************************************************************************************** // #region Declaration of global variables //************************************************************************************** // #region "org" namespace if(typeof in_window.org === "undefined") in_window.org = {}; else { if(typeof in_window.org !== "object") throw new Error("Name org already exists and it's not an object"); } // #endregion // #region "org.pkijs" namespace if(typeof in_window.org.pkijs === "undefined") in_window.org.pkijs = {}; else { if(typeof in_window.org.pkijs !== "object") throw new Error("Name org.pkijs already exists and it's not an object" + " but " + (typeof in_window.org.pkijs)); } // #endregion // #region "org.pkijs.simpl" namespace if(typeof in_window.org.pkijs.simpl === "undefined") in_window.org.pkijs.simpl = {}; else { if(typeof in_window.org.pkijs.simpl !== "object") throw new Error("Name org.pkijs.simpl already exists and it's not an object" + " but " + (typeof in_window.org.pkijs.simpl)); } // #endregion // #region "org.pkijs.simpl.x509" namespace if(typeof in_window.org.pkijs.simpl.x509 === "undefined") in_window.org.pkijs.simpl.x509 = {}; else { if(typeof in_window.org.pkijs.simpl.x509 !== "object") throw new Error("Name org.pkijs.simpl.x509 already exists and it's not an object" + " but " + (typeof in_window.org.pkijs.simpl.x509)); } // #endregion // #region "local" namespace var local = {}; // #endregion //************************************************************************************** // #endregion //************************************************************************************** // #region Simplified structure for "Time" type //************************************************************************************** in_window.org.pkijs.simpl.TIME = function() { // #region Internal properties of the object this.type = 0; // 0 - UTCTime; 1 - GeneralizedTime; 2 - empty value this.value = new Date(0, 0, 0); // #endregion // #region If input argument array contains "schema" for this object if((arguments[0] instanceof Object) && ("schema" in arguments[0])) in_window.org.pkijs.simpl.TIME.prototype.fromSchema.call(this, arguments[0].schema); // #endregion // #region If input argument array contains "native" values for internal properties else { if(arguments[0] instanceof Object) { this.type = (arguments[0].type || 0); this.value = (arguments[0].value || (new Date(0, 0, 0))); } } // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.TIME.prototype.fromSchema = function(schema) { // #region Check the schema is valid var asn1 = in_window.org.pkijs.compareSchema(schema, schema, in_window.org.pkijs.schema.TIME({ names: { utcTimeName: "utcTimeName", generalTimeName: "generalTimeName" } }) ); if(asn1.verified === false) throw new Error("Object's schema was not verified against input data for TIME"); // #endregion // #region Get internal properties from parsed schema if("utcTimeName" in asn1.result) { this.type = 0; this.value = asn1.result.utcTimeName.toDate(); } if("generalTimeName" in asn1.result) { this.type = 1; this.value = asn1.result.generalTimeName.toDate(); } // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.TIME.prototype.toSchema = function() { // #region Construct and return new ASN.1 schema for this object var result = {}; if(this.type === 0) result = new in_window.org.pkijs.asn1.UTCTIME({ value_date: this.value }); if(this.type === 1) result = new in_window.org.pkijs.asn1.GENERALIZEDTIME({ value_date: this.value }); return result; // #endregion } //************************************************************************************** // #endregion //************************************************************************************** // #region Simplified structure for "GeneralName" type //************************************************************************************** in_window.org.pkijs.simpl.GENERAL_NAME = function() { // #region Internal properties of the object this.NameType = 9; // Name type - from a tagged value (0 for "otherName", 1 for "rfc822Name" etc.) this.Name = {}; // #endregion // #region If input argument array contains "schema" for this object if((arguments[0] instanceof Object) && ("schema" in arguments[0])) in_window.org.pkijs.simpl.GENERAL_NAME.prototype.fromSchema.call(this, arguments[0].schema); // #endregion // #region If input argument array contains "native" values for internal properties else { if(arguments[0] instanceof Object) { this.NameType = arguments[0].NameType || 9; this.Name = arguments[0].Name || {}; } } // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.GENERAL_NAME.prototype.fromSchema = function(schema) { // #region Check the schema is valid var asn1 = in_window.org.pkijs.compareSchema(schema, schema, in_window.org.pkijs.schema.GENERAL_NAME({ names: { block_name: "block_name", otherName: "otherName", rfc822Name: "rfc822Name", dNSName: "dNSName", x400Address: "x400Address", directoryName: { names: { block_name: "directoryName" } }, ediPartyName: "ediPartyName", uniformResourceIdentifier: "uniformResourceIdentifier", iPAddress: "iPAddress", registeredID: "registeredID" } }) ); if(asn1.verified === false) throw new Error("Object's schema was not verified against input data for GENERAL_NAME"); // #endregion // #region Get internal properties from parsed schema this.NameType = asn1.result["block_name"].id_block.tag_number; switch(this.NameType) { case 0: // otherName this.Name = asn1.result["block_name"]; break; case 1: // rfc822Name + dNSName + uniformResourceIdentifier case 2: case 6: { var value = asn1.result["block_name"]; value.id_block.tag_class = 1; // UNIVERSAL value.id_block.tag_number = 22; // IA5STRING var value_ber = value.toBER(false); this.Name = in_window.org.pkijs.fromBER(value_ber).result.value_block.value; } break; case 3: // x400Address this.Name = asn1.result["block_name"]; break; case 4: // directoryName this.Name = new in_window.org.pkijs.simpl.RDN({ schema: asn1.result["directoryName"] }); break; case 5: // ediPartyName this.Name = asn1.result["ediPartyName"]; break; case 7: // iPAddress this.Name = in_window.org.pkijs.asn1.OCTETSTRING({ value_hex: asn1.result["block_name"].value_block.value_hex }); break; case 8: // registeredID { var value = asn1.result["block_name"]; value.id_block.tag_class = 1; // UNIVERSAL value.id_block.tag_number = 6; // OID var value_ber = value.toBER(false); this.Name = in_window.org.pkijs.fromBER(value_ber).result.value_block.toString(); // Getting a string representation of the OID } break; default:; } // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.GENERAL_NAME.prototype.toSchema = function(schema) { // #region Construct and return new ASN.1 schema for this object switch(this.NameType) { case 0: case 3: case 5: return new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ id_block: { tag_class: 3, // CONTEXT-SPECIFIC tag_number: this.NameType }, value: [ this.Name ] }); break; case 1: case 2: case 6: { var value = new in_window.org.pkijs.asn1.IA5STRING({ value: this.Name }); value.id_block.tag_class = 3; value.id_block.tag_number = this.NameType; return value; } break; case 4: return new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ id_block: { tag_class: 3, // CONTEXT-SPECIFIC tag_number: 4 }, value: [this.Name.toSchema()] }); break; case 7: { var value = this.Name; value.id_block.tag_class = 3; value.id_block.tag_number = this.NameType; return value; } break; case 8: { var value = new in_window.org.pkijs.asn1.OID({ value: this.Name }); value.id_block.tag_class = 3; value.id_block.tag_number = this.NameType; return value; } break; default: return in_window.org.pkijs.schema.GENERAL_NAME(); } // #endregion } //************************************************************************************** // #endregion //************************************************************************************** // #region Simplified structure for "GeneralNames" type //************************************************************************************** in_window.org.pkijs.simpl.GENERAL_NAMES = function() { // #region Internal properties of the object this.names = new Array(); // Array of "org.pkijs.simpl.GENERAL_NAME" // #endregion // #region If input argument array contains "schema" for this object if((arguments[0] instanceof Object) && ("schema" in arguments[0])) in_window.org.pkijs.simpl.GENERAL_NAMES.prototype.fromSchema.call(this, arguments[0].schema); // #endregion // #region If input argument array contains "native" values for internal properties else { if(arguments[0] instanceof Object) { this.names = arguments[0].names || new Array(); // Array of "org.pkijs.simpl.GENERAL_NAME" } } // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.GENERAL_NAMES.prototype.fromSchema = function(schema) { // #region Check the schema is valid var asn1 = in_window.org.pkijs.compareSchema(schema, schema, new in_window.org.pkijs.asn1.SEQUENCE({ value: [ in_window.org.pkijs.asn1.REPEATED({ name: "names", value: n_window.org.pkijs.schema.GENERAL_NAME() }) ] }) ); if(asn1.verified === false) throw new Error("Object's schema was not verified against input data for GENERAL_NAMES"); // #endregion // #region Get internal properties from parsed schema var n = asn1.result["names"]; for(var i = 0; i < n.length; i++) this.names.push(new in_window.org.pkijs.simpl.GENERAL_NAME({ schema: n[i] })); // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.GENERAL_NAMES.prototype.toSchema = function(schema) { // #region Construct and return new ASN.1 schema for this object var output_array = new Array(); for(var i = 0; i < this.names.length; i++) output_array.push(this.names[i].toSchema()); return (new in_window.org.pkijs.asn1.SEQUENCE({ value: output_array })); // #endregion } //************************************************************************************** // #endregion //************************************************************************************** // #region Simplified structure for "AlgorithmIdentifier" type //************************************************************************************** in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER = function() { // #region Internal properties of the object this.algorithm_id = ""; // OPTIONAL this.algorithm_params = new in_window.org.pkijs.asn1.NULL(); // #endregion // #region If input argument array contains "schema" for this object if((arguments[0] instanceof Object) && ("schema" in arguments[0])) in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER.prototype.fromSchema.call(this, arguments[0].schema); // #endregion // #region If input argument array contains "native" values for internal properties else { if(arguments[0] instanceof Object) { this.algorithm_id = arguments[0].algorithm_id || ""; if("algorithm_params" in arguments[0]) this.algorithm_params = arguments[0].algorithm_params; } } // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER.prototype.fromSchema = function(schema) { // #region Check the schema is valid var asn1 = in_window.org.pkijs.compareSchema(schema, schema, in_window.org.pkijs.schema.ALGORITHM_IDENTIFIER({ names: { algorithmIdentifier: "algorithm", algorithmParams: "params" } }) ); if(asn1.verified === false) throw new Error("Object's schema was not verified against input data for ALGORITHM_IDENTIFIER"); // #endregion // #region Get internal properties from parsed schema this.algorithm_id = asn1.result.algorithm.value_block.toString(); if("params" in asn1.result) this.algorithm_params = asn1.result.params; // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER.prototype.toSchema = function() { // #region Create array for output sequence var output_array = new Array(); output_array.push(new in_window.org.pkijs.asn1.OID({ value: this.algorithm_id })); if("algorithm_params" in this) output_array.push(this.algorithm_params); // #endregion // #region Construct and return new ASN.1 schema for this object return (new in_window.org.pkijs.asn1.SEQUENCE({ value: output_array })); // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER.prototype.getCommonName = function() { } //************************************************************************************** // #endregion //************************************************************************************** // #region Simplified structure for "RSAPublicKey" type (RFC3447) //************************************************************************************** in_window.org.pkijs.simpl.x509.RSAPublicKey = function() { // #region Internal properties of the object this.modulus = new in_window.org.pkijs.asn1.INTEGER(); this.publicExponent = new in_window.org.pkijs.asn1.INTEGER(); // #endregion // #region If input argument array contains "schema" for this object if((arguments[0] instanceof Object) && ("schema" in arguments[0])) in_window.org.pkijs.simpl.x509.RSAPublicKey.prototype.fromSchema.call(this, arguments[0].schema); // #endregion // #region If input argument array contains "native" values for internal properties else { if(arguments[0] instanceof Object) { this.modulus = arguments[0].modulus || new in_window.org.pkijs.asn1.INTEGER(); this.publicExponent = arguments[0].publicExponent || new in_window.org.pkijs.asn1.INTEGER(); } } // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.x509.RSAPublicKey.prototype.fromSchema = function(schema) { // #region Check the schema is valid var asn1 = in_window.org.pkijs.compareSchema(schema, schema, in_window.org.pkijs.schema.x509.RSAPublicKey({ names: { modulus: "modulus", publicExponent: "publicExponent" } }) ); if(asn1.verified === false) throw new Error("Object's schema was not verified against input data for RSAPublicKey"); // #endregion // #region Get internal properties from parsed schema this.modulus = asn1.result["modulus"]; this.publicExponent = asn1.result["publicExponent"]; // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.x509.RSAPublicKey.prototype.toSchema = function() { // #region Construct and return new ASN.1 schema for this object return (new in_window.org.pkijs.asn1.SEQUENCE({ value: [ this.modulus, this.publicExponent ] })); // #endregion } //************************************************************************************** // #endregion //************************************************************************************** // #region Simplified structure for "OtherPrimeInfo" type (RFC3447) //************************************************************************************** in_window.org.pkijs.simpl.x509.OtherPrimeInfo = function() { // #region Internal properties of the object this.prime = new in_window.org.pkijs.asn1.INTEGER(); this.exponent = new in_window.org.pkijs.asn1.INTEGER(); this.coefficient = new in_window.org.pkijs.asn1.INTEGER(); // #endregion // #region If input argument array contains "schema" for this object if((arguments[0] instanceof Object) && ("schema" in arguments[0])) in_window.org.pkijs.simpl.x509.OtherPrimeInfo.prototype.fromSchema.call(this, arguments[0].schema); // #endregion // #region If input argument array contains "native" values for internal properties else { if(arguments[0] instanceof Object) { this.prime = arguments[0].prime || new in_window.org.pkijs.asn1.INTEGER(); this.exponent = arguments[0].exponent || new in_window.org.pkijs.asn1.INTEGER(); this.coefficient = arguments[0].coefficient || new in_window.org.pkijs.asn1.INTEGER(); } } // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.x509.OtherPrimeInfo.prototype.fromSchema = function(schema) { // #region Check the schema is valid var asn1 = in_window.org.pkijs.compareSchema(schema, schema, in_window.org.pkijs.schema.x509.OtherPrimeInfo({ names: { prime: "prime", exponent: "exponent", coefficient: "coefficient" } }) ); if(asn1.verified === false) throw new Error("Object's schema was not verified against input data for OtherPrimeInfo"); // #endregion // #region Get internal properties from parsed schema this.prime = asn1.result["prime"]; this.exponent = asn1.result["exponent"]; this.coefficient = asn1.result["coefficient"]; // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.x509.OtherPrimeInfo.prototype.toSchema = function() { // #region Construct and return new ASN.1 schema for this object return (new in_window.org.pkijs.asn1.SEQUENCE({ value: [ this.prime, this.exponent, this.coefficient ] })); // #endregion } //************************************************************************************** // #endregion //************************************************************************************** // #region Simplified structure for "RSAPrivateKey" type (RFC3447) //************************************************************************************** in_window.org.pkijs.simpl.x509.RSAPrivateKey = function() { // #region Internal properties of the object this.version = 0; this.modulus = new in_window.org.pkijs.asn1.INTEGER(); this.publicExponent = new in_window.org.pkijs.asn1.INTEGER(); this.privateExponent = new in_window.org.pkijs.asn1.INTEGER(); this.prime1 = new in_window.org.pkijs.asn1.INTEGER(); this.prime2 = new in_window.org.pkijs.asn1.INTEGER(); this.exponent1 = new in_window.org.pkijs.asn1.INTEGER(); this.exponent2 = new in_window.org.pkijs.asn1.INTEGER(); this.coefficient = new in_window.org.pkijs.asn1.INTEGER(); // OPTIONAL this.otherPrimeInfos = new Array(); // Array of "OtherPrimeInfo" // #endregion // #region If input argument array contains "schema" for this object if((arguments[0] instanceof Object) && ("schema" in arguments[0])) in_window.org.pkijs.simpl.x509.RSAPrivateKey.prototype.fromSchema.call(this, arguments[0].schema); // #endregion // #region If input argument array contains "native" values for internal properties else { if(arguments[0] instanceof Object) { this.version = arguments[0].version || 0; this.modulus = arguments[0].modulus || new in_window.org.pkijs.asn1.INTEGER(); this.publicExponent = arguments[0].publicExponent || new in_window.org.pkijs.asn1.INTEGER(); this.privateExponent = arguments[0].privateExponent || new in_window.org.pkijs.asn1.INTEGER(); this.prime1 = arguments[0].prime1 || new in_window.org.pkijs.asn1.INTEGER(); this.prime2 = arguments[0].prime2 || new in_window.org.pkijs.asn1.INTEGER(); this.exponent1 = arguments[0].exponent1 || new in_window.org.pkijs.asn1.INTEGER(); this.exponent2 = arguments[0].exponent2 || new in_window.org.pkijs.asn1.INTEGER(); this.coefficient = arguments[0].coefficient || new in_window.org.pkijs.asn1.INTEGER(); if("otherPrimeInfos" in arguments[0]) this.otherPrimeInfos = arguments[0].otherPrimeInfos || new Array(); } } // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.x509.RSAPrivateKey.prototype.fromSchema = function(schema) { // #region Check the schema is valid var asn1 = in_window.org.pkijs.compareSchema(schema, schema, in_window.org.pkijs.schema.x509.RSAPrivateKey({ names: { version: "version", modulus: "modulus", publicExponent: "publicExponent", privateExponent: "privateExponent", prime1: "prime1", prime2: "prime2", exponent1: "exponent1", exponent2: "exponent2", coefficient: "coefficient", otherPrimeInfos: "otherPrimeInfos" } }) ); if(asn1.verified === false) throw new Error("Object's schema was not verified against input data for RSAPrivateKey"); // #endregion // #region Get internal properties from parsed schema this.version = asn1.result["version"].value_block.value_dec; this.modulus = asn1.result["modulus"]; this.publicExponent = asn1.result["publicExponent"]; this.privateExponent = asn1.result["privateExponent"]; this.prime1 = asn1.result["prime1"]; this.prime2 = asn1.result["prime2"]; this.exponent1 = asn1.result["exponent1"]; this.exponent2 = asn1.result["exponent2"]; this.coefficient = asn1.result["coefficient"]; if("otherPrimeInfos" in asn1.result) { var otherPrimeInfos_array = asn1.result["otherPrimeInfos"]; for(var i = 0; i < otherPrimeInfos_array.length; i++) this.otherPrimeInfos.push(new in_window.org.pkijs.simpl.x509.OtherPrimeInfo({ schema: otherPrimeInfos_array[i] })); } // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.x509.RSAPrivateKey.prototype.toSchema = function() { // #region Create array for output sequence var output_array = new Array(); output_array.push(new in_window.org.pkijs.asn1.INTEGER({ value: this.version })); output_array.push(this.modulus); output_array.push(this.publicExponent); output_array.push(this.privateExponent); output_array.push(this.prime1); output_array.push(this.prime2); output_array.push(this.exponent1); output_array.push(this.exponent2); output_array.push(this.coefficient); if("otherPrimeInfos" in this) { var otherPrimeInfos_array = new Array(); for(var i = 0; i < this.otherPrimeInfos.length; i++) otherPrimeInfos_array.push(this.otherPrimeInfos[i].toSchema()); output_array.push(new in_window.org.pkijs.asn1.SEQUENCE({ value: otherPrimeInfos_array })); } // #endregion // #region Construct and return new ASN.1 schema for this object return (new in_window.org.pkijs.asn1.SEQUENCE({ value: output_array })); // #endregion } //************************************************************************************** // #endregion //************************************************************************************** // #region Simplified structure for "SubjectPublicKeyInfo" type //************************************************************************************** in_window.org.pkijs.simpl.PUBLIC_KEY_INFO = function() { // #region Internal properties of the object this.algorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); this.subjectPublicKey = new in_window.org.pkijs.asn1.BITSTRING(); // #endregion // #region If input argument array contains "schema" for this object if((arguments[0] instanceof Object) && ("schema" in arguments[0])) in_window.org.pkijs.simpl.PUBLIC_KEY_INFO.prototype.fromSchema.call(this, arguments[0].schema); // #endregion // #region If input argument array contains "native" values for internal properties else { if(arguments[0] instanceof Object) { this.algorithm = (arguments[0].algorithm || (new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER())); this.subjectPublicKey = (arguments[0].subjectPublicKey || (new in_window.org.pkijs.asn1.BITSTRING())); } } // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.PUBLIC_KEY_INFO.prototype.fromSchema = function(schema) { // #region Check the schema is valid var asn1 = in_window.org.pkijs.compareSchema(schema, schema, in_window.org.pkijs.schema.PUBLIC_KEY_INFO({ names: { algorithm: { names: { block_name: "algorithm" } }, subjectPublicKey: "subjectPublicKey" } }) ); if(asn1.verified === false) throw new Error("Object's schema was not verified against input data for PUBLIC_KEY_INFO"); // #endregion // #region Get internal properties from parsed schema this.algorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ schema: asn1.result.algorithm }); this.subjectPublicKey = asn1.result.subjectPublicKey; // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.PUBLIC_KEY_INFO.prototype.toSchema = function() { // #region Construct and return new ASN.1 schema for this object return (new in_window.org.pkijs.asn1.SEQUENCE({ value: [ this.algorithm.toSchema(), this.subjectPublicKey ] })); // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.PUBLIC_KEY_INFO.prototype.importKey = function(publicKey) { /// <param name="publicKey" type="Key">Public key to work with</param> // #region Initial variables var sequence = Promise.resolve(); var _this = this; // #endregion // #region Initial check if(typeof publicKey === "undefined") return new Promise(function(resolve, reject) { reject("Need to provide publicKey input parameter"); }); // #endregion // #region Get a "crypto" extension var crypto = in_window.org.pkijs.getCrypto(); if(typeof crypto == "undefined") return new Promise(function(resolve, reject) { reject("Unable to create WebCrypto object"); }); // #endregion // #region Export public key sequence = sequence.then( function() { return crypto.exportKey("spki", publicKey); } ); // #endregion // #region Initialize internal variables by parsing exported value sequence = sequence.then( function(exportedKey) { var asn1 = in_window.org.pkijs.fromBER(exportedKey); try { in_window.org.pkijs.simpl.PUBLIC_KEY_INFO.prototype.fromSchema.call(_this, asn1.result); } catch(exception) { return new Promise(function(resolve, reject) { reject("Error during initializing object from schema"); }); } }, function(error) { return new Promise(function(resolve, reject) { reject("Error during exporting public key: " + error); }); } ); // #endregion return sequence; } //************************************************************************************** // #endregion //************************************************************************************** // #region Simplified structure for "AttributeTypeAndValue" type (part of RelativeDistinguishedName) //************************************************************************************** in_window.org.pkijs.simpl.ATTR_TYPE_AND_VALUE = function() { // #region Internal properties of the object this.type = ""; this.value = {}; // #endregion // #region If input argument array contains "schema" for this object if((arguments[0] instanceof Object) && ("schema" in arguments[0])) in_window.org.pkijs.simpl.ATTR_TYPE_AND_VALUE.prototype.fromSchema.call(this, arguments[0].schema); // #endregion // #region If input argument array contains "native" values for internal properties else { if(arguments[0] instanceof Object) { this.type = (arguments[0].type || ""); this.value = (arguments[0].value || {}); } } // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.ATTR_TYPE_AND_VALUE.prototype.fromSchema = function(schema) { // #region Check the schema is valid var asn1 = in_window.org.pkijs.compareSchema(schema, schema, in_window.org.pkijs.schema.ATTR_TYPE_AND_VALUE({ names: { type: "type", value: "typeValue" } }) ); if(asn1.verified === false) throw new Error("Object's schema was not verified against input data for ATTR_TYPE_AND_VALUE"); // #endregion // #region Get internal properties from parsed schema this.type = asn1.result.type.value_block.toString(); this.value = asn1.result.typeValue; // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.ATTR_TYPE_AND_VALUE.prototype.toSchema = function() { // #region Construct and return new ASN.1 schema for this object return (new in_window.org.pkijs.asn1.SEQUENCE({ value: [ new in_window.org.pkijs.asn1.OID({ value: this.type }), this.value ] })); // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.ATTR_TYPE_AND_VALUE.prototype.isEqual = function() { if(arguments[0] instanceof in_window.org.pkijs.simpl.ATTR_TYPE_AND_VALUE) { if(this.type !== arguments[0].type) return false; if(((this.value instanceof in_window.org.pkijs.asn1.UTF8STRING) && (arguments[0].value instanceof in_window.org.pkijs.asn1.UTF8STRING)) || ((this.value instanceof in_window.org.pkijs.asn1.BMPSTRING) && (arguments[0].value instanceof in_window.org.pkijs.asn1.BMPSTRING)) || ((this.value instanceof in_window.org.pkijs.asn1.UNIVERSALSTRING) && (arguments[0].value instanceof in_window.org.pkijs.asn1.UNIVERSALSTRING)) || ((this.value instanceof in_window.org.pkijs.asn1.NUMERICSTRING) && (arguments[0].value instanceof in_window.org.pkijs.asn1.NUMERICSTRING)) || ((this.value instanceof in_window.org.pkijs.asn1.PRINTABLESTRING) && (arguments[0].value instanceof in_window.org.pkijs.asn1.PRINTABLESTRING)) || ((this.value instanceof in_window.org.pkijs.asn1.TELETEXSTRING) && (arguments[0].value instanceof in_window.org.pkijs.asn1.TELETEXSTRING)) || ((this.value instanceof in_window.org.pkijs.asn1.VIDEOTEXSTRING) && (arguments[0].value instanceof in_window.org.pkijs.asn1.VIDEOTEXSTRING)) || ((this.value instanceof in_window.org.pkijs.asn1.IA5STRING) && (arguments[0].value instanceof in_window.org.pkijs.asn1.IA5STRING)) || ((this.value instanceof in_window.org.pkijs.asn1.GRAPHICSTRING) && (arguments[0].value instanceof in_window.org.pkijs.asn1.GRAPHICSTRING)) || ((this.value instanceof in_window.org.pkijs.asn1.VISIBLESTRING) && (arguments[0].value instanceof in_window.org.pkijs.asn1.VISIBLESTRING)) || ((this.value instanceof in_window.org.pkijs.asn1.GENERALSTRING) && (arguments[0].value instanceof in_window.org.pkijs.asn1.GENERALSTRING)) || ((this.value instanceof in_window.org.pkijs.asn1.CHARACTERSTRING) && (arguments[0].value instanceof in_window.org.pkijs.asn1.CHARACTERSTRING))) { var value1 = in_window.org.pkijs.stringPrep(this.value.value_block.value); var value2 = in_window.org.pkijs.stringPrep(arguments[0].value.value_block.value); if(value1.localeCompare(value2) !== 0) return false; } else // Comparing as two ArrayBuffers { if(in_window.org.pkijs.isEqual_buffer(this.value.value_before_decode, arguments[0].value.value_before_decode) === false) return false; } return true; } else return false; } //************************************************************************************** // #endregion //************************************************************************************** // #region Simplified structure for "RelativeDistinguishedName" type //************************************************************************************** in_window.org.pkijs.simpl.RDN = function() { // #region Internal properties of the object /// <field name="types_and_values" type="Array" elementType="in_window.org.pkijs.simpl.ATTR_TYPE_AND_VALUE">Array of "type and value" objects</field> this.types_and_values = new Array(); /// <field name="value_before_decode" type="ArrayBuffer">Value of the RDN before decoding from schema</field> this.value_before_decode = new ArrayBuffer(0); // #endregion // #region If input argument array contains "schema" for this object if((arguments[0] instanceof Object) && ("schema" in arguments[0])) in_window.org.pkijs.simpl.RDN.prototype.fromSchema.call(this, arguments[0].schema); // #endregion // #region If input argument array contains "native" values for internal properties else { if(arguments[0] instanceof Object) { this.types_and_values = (arguments[0].types_and_values || (new Array())); this.value_before_decode = arguments[0].value_before_decode || new ArrayBuffer(0); } } // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.RDN.prototype.fromSchema = function(schema) { // #region Check the schema is valid var asn1 = in_window.org.pkijs.compareSchema(schema, schema, in_window.org.pkijs.schema.RDN({ names: { block_name: "RDN", repeated_set: "types_and_values" } }) ); if(asn1.verified === false) throw new Error("Object's schema was not verified against input data for RDN"); // #endregion // #region Get internal properties from parsed schema if("types_and_values" in asn1.result) // Could be a case when there is no "types and values" { var types_and_values_array = asn1.result.types_and_values; for(var i = 0; i < types_and_values_array.length; i++) this.types_and_values.push(new in_window.org.pkijs.simpl.ATTR_TYPE_AND_VALUE({ schema: types_and_values_array[i] })); } this.value_before_decode = asn1.result.RDN.value_before_decode; // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.RDN.prototype.toSchema = function() { // #region Decode stored TBS value if(this.value_before_decode.byteLength === 0) // No stored encoded array, create "from scratch" { // #region Create array for output set var output_array = new Array(); for(var i = 0; i < this.types_and_values.length; i++) output_array.push(this.types_and_values[i].toSchema()); // #endregion return (new in_window.org.pkijs.asn1.SEQUENCE({ value: [new in_window.org.pkijs.asn1.SET({ value: output_array })] })); } var asn1 = in_window.org.pkijs.fromBER(this.value_before_decode); // #endregion // #region Construct and return new ASN.1 schema for this object return asn1.result; // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.RDN.prototype.isEqual = function() { if(arguments[0] instanceof in_window.org.pkijs.simpl.RDN) { if(this.types_and_values.length != arguments[0].types_and_values.length) return false; for(var i = 0; i < this.types_and_values.length; i++) { if(this.types_and_values[i].isEqual(arguments[0].types_and_values[i]) === false) return false; } return true; } else { if(arguments[0] instanceof ArrayBuffer) return in_window.org.pkijs.isEqual_buffer(this.value_before_decode, arguments[0]); else return false; } return false; } //************************************************************************************** // #endregion //************************************************************************************** // #region Simplified structure for "AuthorityKeyIdentifier" type of extension //************************************************************************************** in_window.org.pkijs.simpl.x509.AuthorityKeyIdentifier = function() { // #region Internal properties of the object // OPTIONAL this.keyIdentifier - OCTETSTRING // OPTIONAL this.authorityCertIssuer - Array of GeneralName // OPTIONAL this.authorityCertSerialNumber - INTEGER // #endregion // #region If input argument array contains "schema" for this object if((arguments[0] instanceof Object) && ("schema" in arguments[0])) in_window.org.pkijs.simpl.x509.AuthorityKeyIdentifier.prototype.fromSchema.call(this, arguments[0].schema); // #endregion // #region If input argument array contains "native" values for internal properties else { if(arguments[0] instanceof Object) { if("keyIdentifier" in arguments[0]) this.keyIdentifier = arguments[0].keyIdentifier; if("authorityCertIssuer" in arguments[0]) this.authorityCertIssuer = arguments[0].authorityCertIssuer; if("authorityCertSerialNumber" in arguments[0]) this.authorityCertSerialNumber = arguments[0].authorityCertSerialNumber; } } // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.x509.AuthorityKeyIdentifier.prototype.fromSchema = function(schema) { // #region Check the schema is valid var asn1 = in_window.org.pkijs.compareSchema(schema, schema, in_window.org.pkijs.schema.x509.AuthorityKeyIdentifier({ names: { keyIdentifier: "keyIdentifier", authorityCertIssuer: "authorityCertIssuer", authorityCertSerialNumber: "authorityCertSerialNumber" } }) ); if(asn1.verified === false) throw new Error("Object's schema was not verified against input data for AuthorityKeyIdentifier"); // #endregion // #region Get internal properties from parsed schema if("keyIdentifier" in asn1.result) { asn1.result["keyIdentifier"].id_block.tag_class = 1; // UNIVERSAL asn1.result["keyIdentifier"].id_block.tag_number = 4; // OCTETSTRING this.keyIdentifier = asn1.result["keyIdentifier"]; } if("authorityCertIssuer" in asn1.result) { this.authorityCertIssuer = new Array(); var issuer_array = asn1.result["authorityCertIssuer"]; for(var i = 0; i < issuer_array.length; i++) this.authorityCertIssuer.push(new in_window.org.pkijs.simpl.GENERAL_NAME({ schema: issuer_array[i] })); }