/* * Copyright (c) 2014, GMO GlobalSign * Copyright (c) 2015, Peculiar Ventures * All rights reserved. * * Author 2014-2015, Yury Strozhevsky . * * 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 }; //************************************************************************************** in_window.org.pkijs.simpl.TIME.prototype.toJSON = function() { return { type: this.type, value: this.value }; }; //************************************************************************************** // #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 = new 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 }; //************************************************************************************** in_window.org.pkijs.simpl.GENERAL_NAME.prototype.toJSON = function() { var _object = { NameType: this.NameType }; if((typeof this.Name) === "string") _object.Name = this.Name; else _object.Name = this.Name.toJSON(); return _object; }; //************************************************************************************** // #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: [ new in_window.org.pkijs.asn1.REPEATED({ name: "names", value: in_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 }; //************************************************************************************** in_window.org.pkijs.simpl.GENERAL_NAMES.prototype.toJSON = function() { var _names = new Array(); for(var i = 0; i < this.names.length; i++) _names.push(this.names[i].toJSON()); return { names: _names }; }; //************************************************************************************** // #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() { }; //************************************************************************************** in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER.prototype.toJSON = function() { var _object = { algorithm_id: this.algorithm_id }; if("algorithm_params" in this) _object.algorithm_params = this.algorithm_params.toJSON(); return _object; }; //************************************************************************************** in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER.prototype.isEqual = function(algorithmIdentifier) { /// Check that two "ALGORITHM_IDENTIFIERs" are equal /// The algorithm identifier to compare with // #region Check input type if((algorithmIdentifier instanceof in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER) == false) return false; // #endregion // #region Check "algorithm_id" if(this.algorithm_id != algorithmIdentifier.algorithm_id) return false; // #endregion // #region Check "algorithm_params" if("algorithm_params" in this) { if("algorithm_params" in algorithmIdentifier) { return JSON.stringify(this.algorithm_params) == JSON.stringify(algorithmIdentifier.algorithm_params); } else return false; } else { if("algorithm_params" in algorithmIdentifier) return false; } // #endregion return true; }; //************************************************************************************** // #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 }; //************************************************************************************** in_window.org.pkijs.simpl.x509.RSAPublicKey.prototype.toJSON = function() { return { modulus: this.modulus.toJSON(), publicExponent: this.publicExponent.toJSON() }; }; //************************************************************************************** // #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 }; //************************************************************************************** in_window.org.pkijs.simpl.x509.OtherPrimeInfo.prototype.toJSON = function() { return { prime: this.prime.toJSON(), exponent: this.exponent.toJSON(), coefficient: this.coefficient.toJSON() }; }; //************************************************************************************** // #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 }; //************************************************************************************** in_window.org.pkijs.simpl.x509.RSAPrivateKey.prototype.toJSON = function() { var _object = { version: this.version, modulus: this.modulus.toJSON(), publicExponent: this.publicExponent.toJSON(), privateExponent: this.privateExponent.toJSON(), prime1: this.prime1.toJSON(), prime2: this.prime2.toJSON(), exponent1: this.exponent1.toJSON(), exponent2: this.exponent2.toJSON(), coefficient: this.coefficient.toJSON() }; if("otherPrimeInfos" in this) { _object.otherPrimeInfos = new Array(); for(var i = 0; i < this.otherPrimeInfos.length; i++) _object.otherPrimeInfos.push(this.otherPrimeInfos[i].toJSON()); } return _object; }; //************************************************************************************** // #endregion //************************************************************************************** // #region Simplified structure for "RSASSA_PSS_params" type (RFC3447) //************************************************************************************** in_window.org.pkijs.simpl.x509.RSASSA_PSS_params = function() { // #region Internal properties of the object // OPTIONAL this.hashAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); // OPTIONAL this.maskGenAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); // OPTIONAL this.saltLength = 20; // new in_window.org.pkijs.asn1.INTEGER(); // OPTIONAL this.trailerField = 1; // 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.RSASSA_PSS_params.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("hashAlgorithm" in arguments[0]) this.hashAlgorithm = arguments[0].hashAlgorithm; if("maskGenAlgorithm" in arguments[0]) this.maskGenAlgorithm = arguments[0].maskGenAlgorithm; if("saltLength" in arguments[0]) this.saltLength = arguments[0].saltLength; if("trailerField" in arguments[0]) this.trailerField = arguments[0].trailerField; } } // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.x509.RSASSA_PSS_params.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.RSASSA_PSS_params({ names: { hashAlgorithm: { names: { block_name: "hashAlgorithm" } }, maskGenAlgorithm: { names: { block_name: "maskGenAlgorithm" } }, saltLength: "saltLength", trailerField: "trailerField" } }) ); if(asn1.verified === false) throw new Error("Object's schema was not verified against input data for RSASSA_PSS_params"); // #endregion // #region Get internal properties from parsed schema if("hashAlgorithm" in asn1.result) this.hashAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ schema: asn1.result["hashAlgorithm"] }); if("maskGenAlgorithm" in asn1.result) this.maskGenAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ schema: asn1.result["maskGenAlgorithm"] }); if("saltLength" in asn1.result) this.saltLength = asn1.result["saltLength"].value_block.value_dec; if("trailerField" in asn1.result) this.trailerField = asn1.result["trailerField"].value_block.value_dec; // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.x509.RSASSA_PSS_params.prototype.toSchema = function() { // #region Create array for output sequence var output_array = new Array(); if("hashAlgorithm" in this) output_array.push(new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ id_block: { tag_class: 3, // CONTEXT-SPECIFIC tag_number: 0 // [0] }, value: [this.hashAlgorithm.toSchema()] })); if("maskGenAlgorithm" in this) output_array.push(new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ id_block: { tag_class: 3, // CONTEXT-SPECIFIC tag_number: 1 // [1] }, value: [this.maskGenAlgorithm.toSchema()] })); if("saltLength" in this) output_array.push(new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ id_block: { tag_class: 3, // CONTEXT-SPECIFIC tag_number: 2 // [2] }, value: [new in_window.org.pkijs.asn1.INTEGER({ value: this.saltLength })] })); if("trailerField" in this) output_array.push(new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ id_block: { tag_class: 3, // CONTEXT-SPECIFIC tag_number: 3 // [3] }, value: [new in_window.org.pkijs.asn1.INTEGER({ value: this.trailerField })] })); // #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.x509.RSASSA_PSS_params.prototype.toJSON = function() { var _object = {}; if("hashAlgorithm" in this) _object.hashAlgorithm = this.hashAlgorithm.toJSON(); if("maskGenAlgorithm" in this) _object.maskGenAlgorithm = this.maskGenAlgorithm.toJSON(); if("saltLength" in this) _object.saltLength = this.saltLength.toJSON(); if("trailerField" in this) _object.trailerField = this.trailerField.toJSON(); return _object; }; //************************************************************************************** // #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) { /// Public key to work with // #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; }; //************************************************************************************** in_window.org.pkijs.simpl.PUBLIC_KEY_INFO.prototype.toJSON = function() { return { algorithm: this.algorithm.toJSON(), subjectPublicKey: this.subjectPublicKey.toJSON() }; }; //************************************************************************************** // #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 = {}; // ANY -- DEFINED BY AttributeType // #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; }; //************************************************************************************** in_window.org.pkijs.simpl.ATTR_TYPE_AND_VALUE.prototype.toJSON = function() { var _object = { type: this.type }; if(Object.keys(this.value).length !== 0) _object.value = this.value.toJSON(); else _object.value = this.value; return _object; }; //************************************************************************************** // #endregion //************************************************************************************** // #region Simplified structure for "RelativeDistinguishedName" type //************************************************************************************** in_window.org.pkijs.simpl.RDN = function() { // #region Internal properties of the object /// Array of "type and value" objects this.types_and_values = new Array(); /// Value of the RDN before decoding from schema 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; }; //************************************************************************************** in_window.org.pkijs.simpl.RDN.prototype.toJSON = function() { var _object = { types_and_values: new Array() }; for(var i = 0; i < this.types_and_values.length; i++) _object.types_and_values.push(this.types_and_values[i].toJSON()); return _object; }; //************************************************************************************** // #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] })); } if("authorityCertSerialNumber" in asn1.result) { asn1.result["authorityCertSerialNumber"].id_block.tag_class = 1; // UNIVERSAL asn1.result["authorityCertSerialNumber"].id_block.tag_number = 2; // INTEGER this.authorityCertSerialNumber = asn1.result["authorityCertSerialNumber"]; } // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.x509.AuthorityKeyIdentifier.prototype.toSchema = function() { // #region Create array for output sequence var output_array = new Array(); if("keyIdentifier" in this) { var value = this.keyIdentifier; value.id_block.tag_class = 3; // CONTEXT-SPECIFIC value.id_block.tag_number = 0; // [0] output_array.push(value); } if("authorityCertIssuer" in this) { var issuer_array = new Array(); for(var i = 0; i < this.authorityCertIssuer.length; i++) issuer_array.push(this.authorityCertIssuer[i].toSchema()); output_array.push(new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ optional: true, id_block: { tag_class: 3, // CONTEXT-SPECIFIC tag_number: 1 // [1] }, value: [new in_window.org.pkijs.asn1.SEQUENCE({ value: issuer_array })] })); } if("authorityCertSerialNumber" in this) { var value = this.authorityCertSerialNumber; value.id_block.tag_class = 3; // CONTEXT-SPECIFIC value.id_block.tag_number = 2; // [2] output_array.push(value); } // #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.x509.AuthorityKeyIdentifier.prototype.toJSON = function() { var _object = {}; if("keyIdentifier" in this) _object.keyIdentifier = this.keyIdentifier.toJSON(); if("authorityCertIssuer" in this) { _object.authorityCertIssuer = new Array(); for(var i = 0; i < this.authorityCertIssuer.length; i++) _object.authorityCertIssuer.push(this.authorityCertIssuer[i].toJSON()); } if("authorityCertSerialNumber" in this) _object.authorityCertSerialNumber = this.authorityCertSerialNumber.toJSON(); return _object; }; //************************************************************************************** // #endregion //************************************************************************************** // #region Simplified structure for "PrivateKeyUsagePeriod" type of extension //************************************************************************************** in_window.org.pkijs.simpl.x509.PrivateKeyUsagePeriod = function() { // #region Internal properties of the object // OPTIONAL this.notBefore - new Date() // OPTIONAL this.notAfter - new Date() // #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.PrivateKeyUsagePeriod.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("notBefore" in arguments[0]) this.notBefore = arguments[0].notBefore; if("notAfter" in arguments[0]) this.notAfter = arguments[0].notAfter; } } // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.x509.PrivateKeyUsagePeriod.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.PrivateKeyUsagePeriod({ names: { notBefore: "notBefore", notAfter: "notAfter" } }) ); if(asn1.verified === false) throw new Error("Object's schema was not verified against input data for PrivateKeyUsagePeriod"); // #endregion // #region Get internal properties from parsed schema if("notBefore" in asn1.result) { var localNotBefore = new in_window.org.pkijs.asn1.GENERALIZEDTIME(); localNotBefore.fromBuffer(asn1.result["notBefore"].value_block.value_hex); this.notBefore = localNotBefore.toDate(); } if("notAfter" in asn1.result) { var localNotAfter = new in_window.org.pkijs.asn1.GENERALIZEDTIME({ value_hex: asn1.result["notAfter"].value_block.value_hex }); localNotAfter.fromBuffer(asn1.result["notAfter"].value_block.value_hex); this.notAfter = localNotAfter.toDate(); } // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.x509.PrivateKeyUsagePeriod.prototype.toSchema = function() { // #region Create array for output sequence var output_array = new Array(); if("notBefore" in this) output_array.push(new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({ id_block: { tag_class: 3, // CONTEXT-SPECIFIC tag_number: 0 // [0] }, value_hex: (new in_window.org.pkijs.asn1.GENERALIZEDTIME({ value_date: this.notBefore })).value_block.value_hex })); if("notAfter" in this) output_array.push(new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({ id_block: { tag_class: 3, // CONTEXT-SPECIFIC tag_number: 1 // [1] }, value_hex: (new in_window.org.pkijs.asn1.GENERALIZEDTIME({ value_date: this.notAfter })).value_block.value_hex })); // #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.x509.PrivateKeyUsagePeriod.prototype.toJSON = function() { var _object = {}; if("notBefore" in this) _object.notBefore = this.notBefore; if("notAfter" in this) _object.notAfter = this.notAfter; return _object; }; //************************************************************************************** // #endregion //************************************************************************************** // #region Simplified structure for "IssuerAltName" and "SubjectAltName" types of extension //************************************************************************************** in_window.org.pkijs.simpl.x509.AltName = function() { // #region Internal properties of the object this.altNames = new Array(); //Array of GeneralName // #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.AltName.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.altNames = arguments[0].altNames || new Array(); } } // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.x509.AltName.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.AltName({ names: { altNames: "altNames" } }) ); if(asn1.verified === false) throw new Error("Object's schema was not verified against input data for AltName"); // #endregion // #region Get internal properties from parsed schema if("altNames" in asn1.result) { var altNames_array = asn1.result["altNames"]; for(var i = 0; i < altNames_array.length; i++) this.altNames.push(new in_window.org.pkijs.simpl.GENERAL_NAME({ schema: altNames_array[i] })); } // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.x509.AltName.prototype.toSchema = function() { // #region Create array for output sequence var output_array = new Array(); for(var i = 0; i < this.altNames.length; i++) output_array.push(this.altNames[i].toSchema()); // #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.x509.AltName.prototype.toJSON = function() { var _object = { altNames: new Array() }; for(var i = 0; i < this.altNames.length; i++) _object.altNames.push(this.altNames[i].toJSON()); return _object; }; //************************************************************************************** // #endregion //************************************************************************************** // #region Simplified structure for "SubjectDirectoryAttributes" type of extension //************************************************************************************** in_window.org.pkijs.simpl.x509.SubjectDirectoryAttributes = function() { // #region Internal properties of the object this.attributes = new Array(); // Array of "simpl.ATTRIBUTE" // #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.SubjectDirectoryAttributes.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.attributes = arguments[0].attributes || new Array(); // Array of "simpl.ATTRIBUTE" } } // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.x509.SubjectDirectoryAttributes.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.SubjectDirectoryAttributes({ names: { attributes: "attributes" } }) ); if(asn1.verified === false) throw new Error("Object's schema was not verified against input data for SubjectDirectoryAttributes"); // #endregion // #region Get internal properties from parsed schema var attrs = asn1.result["attributes"]; for(var i = 0; i < attrs.length; i++) this.attributes.push(new in_window.org.pkijs.simpl.ATTRIBUTE({ schema: attrs[i] })); // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.x509.SubjectDirectoryAttributes.prototype.toSchema = function() { // #region Create array for output sequence var output_array = new Array(); for(var i = 0; i < this.attributes.length; i++) output_array.push(this.attributes[i].toSchema()); // #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.x509.SubjectDirectoryAttributes.prototype.toJSON = function() { var _object = { attributes: new Array() }; for(var i = 0; i < this.attributes.length; i++) _object.attributes.push(this.attributes[i].toJSON()); return _object; }; //************************************************************************************** // #endregion //************************************************************************************** // #region Simplified structure for "PolicyMapping" type //************************************************************************************** in_window.org.pkijs.simpl.x509.PolicyMapping = function() { // #region Internal properties of the object this.issuerDomainPolicy = ""; this.subjectDomainPolicy = ""; // #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.PolicyMapping.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.issuerDomainPolicy = arguments[0].issuerDomainPolicy || ""; this.subjectDomainPolicy = arguments[0].subjectDomainPolicy || ""; } } // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.x509.PolicyMapping.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.PolicyMapping({ names: { issuerDomainPolicy: "issuerDomainPolicy", subjectDomainPolicy: "subjectDomainPolicy" } }) ); if(asn1.verified === false) throw new Error("Object's schema was not verified against input data for PolicyMapping"); // #endregion // #region Get internal properties from parsed schema this.issuerDomainPolicy = asn1.result["issuerDomainPolicy"].value_block.toString(); this.subjectDomainPolicy = asn1.result["subjectDomainPolicy"].value_block.toString(); // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.x509.PolicyMapping.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.issuerDomainPolicy }), new in_window.org.pkijs.asn1.OID({ value: this.subjectDomainPolicy }) ] })); // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.x509.PolicyMapping.prototype.toJSON = function() { return { issuerDomainPolicy: this.issuerDomainPolicy, subjectDomainPolicy: this.subjectDomainPolicy }; }; //************************************************************************************** // #endregion //************************************************************************************** // #region Simplified structure for "PolicyMappings" type of extension //************************************************************************************** in_window.org.pkijs.simpl.x509.PolicyMappings = function() { // #region Internal properties of the object this.mappings = new Array(); // Array of "simpl.x509.PolicyMapping" // #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.PolicyMappings.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.mappings = arguments[0].mappings || new Array(); } } // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.x509.PolicyMappings.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.PolicyMappings({ names: { mappings: "mappings" } }) ); if(asn1.verified === false) throw new Error("Object's schema was not verified against input data for PolicyMappings"); // #endregion // #region Get internal properties from parsed schema var maps = asn1.result["mappings"]; for(var i = 0; i < maps.length; i++) this.mappings.push(new in_window.org.pkijs.simpl.x509.PolicyMapping({ schema: maps[i] })); // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.x509.PolicyMappings.prototype.toSchema = function() { // #region Create array for output sequence var output_array = new Array(); for(var i = 0; i < this.mappings.length; i++) output_array.push(this.mappings.toSchema()); // #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.x509.PolicyMappings.prototype.toJSON = function() { var _object = { mappings: new Array() }; for(var i = 0; i < this.mappings.length; i++) _object.mappings.push(this.mappings[i].toJSON()); return _object; }; //************************************************************************************** // #endregion //************************************************************************************** // #region Simplified structure for "GeneralSubtree" type //************************************************************************************** in_window.org.pkijs.simpl.x509.GeneralSubtree = function() { // #region Internal properties of the object this.base = new in_window.org.pkijs.simpl.GENERAL_NAME(); // OPTIONAL this.minimum // in_window.org.pkijs.asn1.INTEGER // OPTIONAL this.maximum // 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.GeneralSubtree.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.base = arguments[0].base || new in_window.org.pkijs.simpl.GENERAL_NAME(); if("minimum" in arguments[0]) this.minimum = arguments[0].minimum; if("maximum" in arguments[0]) this.maximum = arguments[0].maximum; } } // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.x509.GeneralSubtree.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.GeneralSubtree({ names: { base: { names: { block_name: "base" } }, minimum: "minimum", maximum: "maximum" } }) ); if(asn1.verified === false) throw new Error("Object's schema was not verified against input data for "); // #endregion // #region Get internal properties from parsed schema this.base = new in_window.org.pkijs.simpl.GENERAL_NAME({ schema: asn1.result["base"] }); if("minimum" in asn1.result) { if(asn1.result["minimum"].value_block.is_hex_only) this.minimum = asn1.result["minimum"]; else this.minimum = asn1.result["minimum"].value_block.value_dec; } if("maximum" in asn1.result) { if(asn1.result["maximum"].value_block.is_hex_only) this.maximum = asn1.result["maximum"]; else this.maximum = asn1.result["maximum"].value_block.value_dec; } // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.x509.GeneralSubtree.prototype.toSchema = function() { // #region Create array for output sequence var output_array = new Array(); output_array.push(this.base.toSchema()); if("minimum" in this) { var value_minimum = 0; if(this.minimum instanceof in_window.org.pkijs.asn1.INTEGER) value_minimum = this.minimum; else value_minimum = new in_window.org.pkijs.asn1.INTEGER({ value: this.minimum }); output_array.push(new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ optional: true, id_block: { tag_class: 3, // CONTEXT-SPECIFIC tag_number: 0 // [0] }, value: [value_minimum] })); } if("maximum" in this) { var value_maximum = 0; if(this.maximum instanceof in_window.org.pkijs.asn1.INTEGER) value_maximum = this.maximum; else value_maximum = new in_window.org.pkijs.asn1.INTEGER({ value: this.maximum }); output_array.push(new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ optional: true, id_block: { tag_class: 3, // CONTEXT-SPECIFIC tag_number: 1 // [1] }, value: [value_maximum] })); } // #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.x509.GeneralSubtree.prototype.toJSON = function() { var _object = { base: this.base.toJSON() }; if("minimum" in this) { if((typeof this.minimum) === "number") _object.minimum = this.minimum; else _object.minimum = this.minimum.toJSON(); } if("maximum" in this) { if((typeof this.maximum) === "number") _object.maximum = this.maximum; else _object.maximum = this.maximum.toJSON(); } return _object; }; //************************************************************************************** // #endregion //************************************************************************************** // #region Simplified structure for "NameConstraints" type of extension //************************************************************************************** in_window.org.pkijs.simpl.x509.NameConstraints = function() { // #region Internal properties of the object // OPTIONAL this.permittedSubtrees - Array of "simpl.x509.GeneralSubtree" // OPTIONAL this.excludedSubtrees - Array of "simpl.x509.GeneralSubtree" // #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.NameConstraints.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("permittedSubtrees" in arguments[0]) this.permittedSubtrees = arguments[0].permittedSubtrees; if("excludedSubtrees" in arguments[0]) this.excludedSubtrees = arguments[0].excludedSubtrees; } } // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.x509.NameConstraints.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.NameConstraints({ names: { permittedSubtrees: "permittedSubtrees", excludedSubtrees: "excludedSubtrees" } }) ); if(asn1.verified === false) throw new Error("Object's schema was not verified against input data for NameConstraints"); // #endregion // #region Get internal properties from parsed schema if("permittedSubtrees" in asn1.result) { this.permittedSubtrees = new Array(); var permited_array = asn1.result["permittedSubtrees"]; for(var i = 0; i < permited_array.length; i++) this.permittedSubtrees.push(new in_window.org.pkijs.simpl.x509.GeneralSubtree({ schema: permited_array[i] })); } if("excludedSubtrees" in asn1.result) { this.excludedSubtrees = new Array(); var excluded_array = asn1.result["excludedSubtrees"]; for(var i = 0; i < excluded_array.length; i++) this.excludedSubtrees.push(new in_window.org.pkijs.simpl.x509.GeneralSubtree({ schema: excluded_array[i] })); } // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.x509.NameConstraints.prototype.toSchema = function() { // #region Create array for output sequence var output_array = new Array(); if("permittedSubtrees" in this) { var permited_array = new Array(); for(var i = 0; i < this.permittedSubtrees.length; i++) permited_array.push(this.permittedSubtrees[i].toSchema()); output_array.push(new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ optional: true, id_block: { tag_class: 3, // CONTEXT-SPECIFIC tag_number: 0 // [0] }, value: [new in_window.org.pkijs.asn1.SEQUENCE({ value: permited_array })] })); } if("excludedSubtrees" in this) { var excluded_array = new Array(); for(var i = 0; i < this.excludedSubtrees.length; i++) excluded_array.push(this.excludedSubtrees[i].toSchema()); output_array.push(new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ optional: true, id_block: { tag_class: 3, // CONTEXT-SPECIFIC tag_number: 1 // [1] }, value: [new in_window.org.pkijs.asn1.SEQUENCE({ value: excluded_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 }; //************************************************************************************** in_window.org.pkijs.simpl.x509.NameConstraints.prototype.toJSON = function() { var _object = {}; if("permittedSubtrees" in this) { _object.permittedSubtrees = new Array(); for(var i = 0; i < this.permittedSubtrees.length; i++) _object.permittedSubtrees.push(this.permittedSubtrees[i].toJSON()); } if("excludedSubtrees" in this) { _object.excludedSubtrees = new Array(); for(var i = 0; i < this.excludedSubtrees.length; i++) _object.excludedSubtrees.push(this.excludedSubtrees[i].toJSON()); } return _object; }; //************************************************************************************** // #endregion //************************************************************************************** // #region Simplified structure for "BasicConstraints" type of extension //************************************************************************************** in_window.org.pkijs.simpl.x509.BasicConstraints = function() { // #region Internal properties of the object // OPTIONAL this.cA - boolean value // OPTIONAL this.pathLenConstraint - integer 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.x509.BasicConstraints.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("cA" in arguments[0]) this.cA = arguments[0].cA; if("pathLenConstraint" in arguments[0]) this.pathLenConstraint = arguments[0].pathLenConstraint; } } // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.x509.BasicConstraints.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.BasicConstraints({ names: { cA: "cA", pathLenConstraint: "pathLenConstraint" } }) ); if(asn1.verified === false) throw new Error("Object's schema was not verified against input data for BasicConstraints"); // #endregion // #region Get internal properties from parsed schema if("cA" in asn1.result) this.cA = asn1.result["cA"].value_block.value; if("pathLenConstraint" in asn1.result) this.pathLenConstraint = asn1.result["pathLenConstraint"].value_block.value_dec; // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.x509.BasicConstraints.prototype.toSchema = function() { // #region Create array for output sequence var output_array = new Array(); if("cA" in this) output_array.push(new in_window.org.pkijs.asn1.BOOLEAN({ value: this.cA })); if("pathLenConstraint" in this) output_array.push(new in_window.org.pkijs.asn1.INTEGER({ value: this.pathLenConstraint })); // #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.x509.BasicConstraints.prototype.toJSON = function() { var _object = {}; if("cA" in this) _object.cA = this.cA; if("pathLenConstraint" in this) _object.pathLenConstraint = this.pathLenConstraint; return _object; }; //************************************************************************************** // #endregion //************************************************************************************** // #region Simplified structure for "PolicyQualifierInfo" type //************************************************************************************** in_window.org.pkijs.simpl.x509.PolicyQualifierInfo = function() { // #region Internal properties of the object this.policyQualifierId = ""; this.qualifier = new in_window.org.pkijs.asn1.ANY(); // #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.PolicyQualifierInfo.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.policyQualifierId = arguments[0].policyQualifierId || ""; this.qualifier = arguments[0].qualifier || new in_window.org.pkijs.asn1.ANY(); } } // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.x509.PolicyQualifierInfo.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.PolicyQualifierInfo({ names: { policyQualifierId: "policyQualifierId", qualifier: "qualifier" } }) ); if(asn1.verified === false) throw new Error("Object's schema was not verified against input data for PolicyQualifierInfo"); // #endregion // #region Get internal properties from parsed schema this.policyQualifierId = asn1.result["policyQualifierId"].value_block.toString(); this.qualifier = asn1.result["qualifier"]; // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.x509.PolicyQualifierInfo.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.policyQualifierId }), this.qualifier ] })); // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.x509.PolicyQualifierInfo.prototype.toJSON = function() { return { policyQualifierId: this.policyQualifierId, qualifier: this.qualifier.toJSON() }; }; //************************************************************************************** // #endregion //************************************************************************************** // #region Simplified structure for "PolicyInformation" type //************************************************************************************** in_window.org.pkijs.simpl.x509.PolicyInformation = function() { // #region Internal properties of the object this.policyIdentifier = ""; // OPTIONAL this.policyQualifiers = new Array(); // Array of "simpl.x509.PolicyQualifierInfo" // #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.PolicyInformation.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.policyIdentifier = arguments[0].policyIdentifier || ""; if("policyQualifiers" in arguments[0]) this.policyQualifiers = arguments[0].policyQualifiers; } } // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.x509.PolicyInformation.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.PolicyInformation({ names: { policyIdentifier: "policyIdentifier", policyQualifiers: "policyQualifiers" } }) ); if(asn1.verified === false) throw new Error("Object's schema was not verified against input data for PolicyInformation"); // #endregion // #region Get internal properties from parsed schema this.policyIdentifier = asn1.result["policyIdentifier"].value_block.toString(); if("policyQualifiers" in asn1.result) { this.policyQualifiers = new Array(); var qualifiers = asn1.result["policyQualifiers"]; for(var i = 0; i < qualifiers.length; i++) this.policyQualifiers.push(new in_window.org.pkijs.simpl.x509.PolicyQualifierInfo({ schema: qualifiers[i] })); } // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.x509.PolicyInformation.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.policyIdentifier })); if("policyQualifiers" in this) { var qualifiers = new Array(); for(var i = 0; i < this.policyQualifiers.length; i++) qualifiers.push(this.policyQualifiers[i].toSchema()); output_array.push(new in_window.org.pkijs.asn1.SEQUENCE({ value: qualifiers })); } // #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.x509.PolicyInformation.prototype.toJSON = function() { var _object = { policyIdentifier: this.policyIdentifier }; if("policyQualifiers" in this) { _object.policyQualifiers = new Array(); for(var i = 0; i < this.policyQualifiers.length; i++) _object.policyQualifiers.push(this.policyQualifiers[i].toJSON()); } return _object; }; //************************************************************************************** // #endregion //************************************************************************************** // #region Simplified structure for "CertificatePolicies" type of extension //************************************************************************************** in_window.org.pkijs.simpl.x509.CertificatePolicies = function() { // #region Internal properties of the object this.certificatePolicies = new Array(); // Array of "simpl.x509.PolicyInformation" // #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.CertificatePolicies.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.certificatePolicies = arguments[0].certificatePolicies || new Array(); // Array of "simpl.x509.PolicyInformation" } } // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.x509.CertificatePolicies.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.CertificatePolicies({ names: { certificatePolicies: "certificatePolicies" } }) ); if(asn1.verified === false) throw new Error("Object's schema was not verified against input data for CertificatePolicies"); // #endregion // #region Get internal properties from parsed schema var policies = asn1.result["certificatePolicies"]; for(var i = 0; i < policies.length; i++) this.certificatePolicies.push(new in_window.org.pkijs.simpl.x509.PolicyInformation({ schema: policies[i] })); // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.x509.CertificatePolicies.prototype.toSchema = function() { // #region Create array for output sequence var output_array = new Array(); for(var i = 0; i < this.certificatePolicies.length; i++) output_array.push(this.certificatePolicies[i].toSchema()); // #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.x509.CertificatePolicies.prototype.toJSON = function() { var _object = { certificatePolicies: new Array() }; for(var i = 0; i < this.certificatePolicies.length; i++) _object.certificatePolicies.push(this.certificatePolicies[i].toJSON()); return _object; }; //************************************************************************************** // #endregion //************************************************************************************** // #region Simplified structure for "PolicyConstraints" type of extension //************************************************************************************** in_window.org.pkijs.simpl.x509.PolicyConstraints = function() { // #region Internal properties of the object // OPTIONAL this.requireExplicitPolicy = 0; // OPTIONAL this.inhibitPolicyMapping = 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.x509.PolicyConstraints.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.requireExplicitPolicy = arguments[0].requireExplicitPolicy || 0; this.inhibitPolicyMapping = arguments[0].inhibitPolicyMapping || 0; } } // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.x509.PolicyConstraints.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.PolicyConstraints({ names: { requireExplicitPolicy: "requireExplicitPolicy", inhibitPolicyMapping: "inhibitPolicyMapping" } }) ); if(asn1.verified === false) throw new Error("Object's schema was not verified against input data for PolicyConstraints"); // #endregion // #region Get internal properties from parsed schema if("requireExplicitPolicy" in asn1.result) { var field1 = asn1.result["requireExplicitPolicy"]; field1.id_block.tag_class = 1; // UNIVERSAL field1.id_block.tag_number = 2; // INTEGER var ber1 = field1.toBER(false); var int1 = in_window.org.pkijs.fromBER(ber1); this.requireExplicitPolicy = int1.result.value_block.value_dec; } if("inhibitPolicyMapping" in asn1.result) { var field2 = asn1.result["inhibitPolicyMapping"]; field2.id_block.tag_class = 1; // UNIVERSAL field2.id_block.tag_number = 2; // INTEGER var ber2 = field2.toBER(false); var int2 = in_window.org.pkijs.fromBER(ber2); this.inhibitPolicyMapping = int2.result.value_block.value_dec; } // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.x509.PolicyConstraints.prototype.toSchema = function() { // #region Create correct values for output sequence var output_array = new Array(); if("requireExplicitPolicy" in this) { var int1 = new in_window.org.pkijs.asn1.INTEGER({ value: this.requireExplicitPolicy }); int1.id_block.tag_class = 3; // CONTEXT-SPECIFIC int1.id_block.tag_number = 0; // [0] output_array.push(int1); } if("inhibitPolicyMapping" in this) { var int2 = new in_window.org.pkijs.asn1.INTEGER({ value: this.inhibitPolicyMapping }); int1.id_block.tag_class = 3; // CONTEXT-SPECIFIC int1.id_block.tag_number = 1; // [1] output_array.push(int2); } // #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.x509.PolicyConstraints.prototype.toJSON = function() { var _object = {}; if("requireExplicitPolicy" in this) _object.requireExplicitPolicy = this.requireExplicitPolicy; if("inhibitPolicyMapping" in this) _object.inhibitPolicyMapping = this.inhibitPolicyMapping; return _object; }; //************************************************************************************** // #endregion //************************************************************************************** // #region Simplified structure for "ExtKeyUsage" type of extension //************************************************************************************** in_window.org.pkijs.simpl.x509.ExtKeyUsage = function() { // #region Internal properties of the object this.keyPurposes = new Array(); // Array of strings (OIDs value for key purposes) // #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.ExtKeyUsage.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.keyPurposes = arguments[0].keyPurposes || new Array(); // Array of strings (OIDs value for key purposes) } } // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.x509.ExtKeyUsage.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.ExtKeyUsage({ names: { keyPurposes: "keyPurposes" } }) ); if(asn1.verified === false) throw new Error("Object's schema was not verified against input data for ExtKeyUsage"); // #endregion // #region Get internal properties from parsed schema var purposes = asn1.result["keyPurposes"]; for(var i = 0; i < purposes.length; i++) this.keyPurposes.push(purposes[i].value_block.toString()); // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.x509.ExtKeyUsage.prototype.toSchema = function() { // #region Create array for output sequence var output_array = new Array(); for(var i = 0; i < this.keyPurposes.length; i++) output_array.push(new in_window.org.pkijs.asn1.OID({ value: this.keyPurposes[i] })); // #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.x509.ExtKeyUsage.prototype.toJSON = function() { var _object = { keyPurposes: new Array() }; for(var i = 0; i < this.keyPurposes.length; i++) _object.keyPurposes.push(this.keyPurposes[i]); return _object; }; //************************************************************************************** // #endregion //************************************************************************************** // #region Simplified structure for "DistributionPoint" type //************************************************************************************** in_window.org.pkijs.simpl.x509.DistributionPoint = function() { // #region Internal properties of the object // OPTIONAL this.distributionPoint // Array of "simpl.GENERAL_NAME" or a value of "simpl.RDN" type // OPTIONAL this.reasons // BITSTRING value // OPTIONAL this.cRLIssuer // Array of "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.x509.DistributionPoint.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("distributionPoint" in arguments[0]) this.distributionPoint = arguments[0].distributionPoint; if("reasons" in arguments[0]) this.reasons = arguments[0].reasons; if("cRLIssuer" in arguments[0]) this.cRLIssuer = arguments[0].cRLIssuer; } } // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.x509.DistributionPoint.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.DistributionPoint({ names: { distributionPoint: "distributionPoint", distributionPoint_names: "distributionPoint_names", reasons: "reasons", cRLIssuer: "cRLIssuer", cRLIssuer_names: "cRLIssuer_names" } }) ); if(asn1.verified === false) throw new Error("Object's schema was not verified against input data for DistributionPoint"); // #endregion // #region Get internal properties from parsed schema if("distributionPoint" in asn1.result) { if(asn1.result["distributionPoint"].id_block.tag_number == 0) // GENERAL_NAMES variant { this.distributionPoint = new Array(); var names = asn1.result["distributionPoint_names"]; for(var i = 0; i < names.length; i++) this.distributionPoint.push(new in_window.org.pkijs.simpl.GENERAL_NAME({ schema: names[i] })); } if(asn1.result["distributionPoint"].id_block.tag_number == 1) // RDN variant { asn1.result["distributionPoint"].id_block.tag_class = 1; // UNIVERSAL asn1.result["distributionPoint"].id_block.tag_number = 16; // SEQUENCE this.distributionPoint = new in_window.org.pkijs.simpl.RDN({ schema: asn1.result["distributionPoint"] }); } } if("reasons" in asn1.result) this.reasons = new in_window.org.pkijs.asn1.BITSTRING({ value_hex: asn1.result["reasons"].value_block.value_hex }); if("cRLIssuer" in asn1.result) { this.cRLIssuer = new Array(); var crl_names = asn1.result["cRLIssuer_names"]; for(var i = 0; i < crl_names; i++) this.cRLIssuer.push(new in_window.org.pkijs.simpl.GENERAL_NAME({ schema: crl_names[i] })); } // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.x509.DistributionPoint.prototype.toSchema = function() { // #region Create array for output sequence var output_array = new Array(); if("distributionPoint" in this) { var internalValue; if(this.distributionPoint instanceof Array) { var namesArray = new Array(); for(var i = 0; i < this.distributionPoint.length; i++) namesArray.push(this.distributionPoint[i].toSchema()); internalValue = new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ id_block: { tag_class: 3, // CONTEXT-SPECIFIC tag_number: 0 // [0] }, value: namesArray }); } else { internalValue = new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ id_block: { tag_class: 3, // CONTEXT-SPECIFIC tag_number: 1 // [1] }, value: [this.distributionPoint.toSchema()] }); } output_array.push(new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ id_block: { tag_class: 3, // CONTEXT-SPECIFIC tag_number: 0 // [0] }, value: [internalValue] })); } if("reasons" in this) { output_array.push(new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({ id_block: { tag_class: 3, // CONTEXT-SPECIFIC tag_number: 1 // [1] }, value_hex: this.reasons.value_block.value_hex })); } if("cRLIssuer" in this) { var value = new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ id_block: { tag_class: 3, // CONTEXT-SPECIFIC tag_number: 2 // [2] } }); for(var i = 0; i < this.cRLIssuer.length; i++) value.value_block.value.push(this.cRLIssuer[i].toSchema()); output_array.push(value); } // #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.x509.DistributionPoint.prototype.toJSON = function() { var _object = {}; if("distributionPoint" in this) { if(this.distributionPoint instanceof Array) { _object.distributionPoint = new Array(); for(var i = 0; i < this.distributionPoint.length; i++) _object.distributionPoint.push(this.distributionPoint[i].toJSON()); } else _object.distributionPoint = this.distributionPoint.toJSON(); } if("reasons" in this) _object.reasons = this.reasons.toJSON(); if("cRLIssuer" in this) { _object.cRLIssuer = new Array(); for(var i = 0; i < this.cRLIssuer.length; i++) _object.cRLIssuer.push(this.cRLIssuer[i].toJSON()); } return _object; }; //************************************************************************************** // #endregion //************************************************************************************** // #region Simplified structure for "CRLDistributionPoints" type of extension //************************************************************************************** in_window.org.pkijs.simpl.x509.CRLDistributionPoints = function() { // #region Internal properties of the object this.distributionPoints = new Array(); // Array of "simpl.x509.DistributionPoint" // #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.CRLDistributionPoints.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.distributionPoints = arguments[0].distributionPoints || new Array(); // Array of "simpl.x509.DistributionPoint" } } // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.x509.CRLDistributionPoints.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.CRLDistributionPoints({ names: { distributionPoints: "distributionPoints" } }) ); if(asn1.verified === false) throw new Error("Object's schema was not verified against input data for CRLDistributionPoints"); // #endregion // #region Get internal properties from parsed schema var points = asn1.result["distributionPoints"]; for(var i = 0; i < points.length; i++) this.distributionPoints.push(new in_window.org.pkijs.simpl.x509.DistributionPoint({ schema: points[i] })); // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.x509.CRLDistributionPoints.prototype.toSchema = function() { // #region Create array for output sequence var output_array = new Array(); for(var i = 0; i < this.distributionPoints.length; i++) output_array.push(this.distributionPoints[i].toSchema()); // #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.x509.CRLDistributionPoints.prototype.toJSON = function() { var _object = { distributionPoints: new Array() }; for(var i = 0; i < this.distributionPoints.length; i++) _object.distributionPoints.push(this.distributionPoints[i].toJSON()); return _object; }; //************************************************************************************** // #endregion //************************************************************************************** // #region Simplified structure for "AccessDescription" type //************************************************************************************** in_window.org.pkijs.simpl.x509.AccessDescription = function() { // #region Internal properties of the object this.accessMethod = ""; this.accessLocation = new in_window.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.x509.AccessDescription.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.accessMethod = arguments[0].accessMethod || ""; this.accessLocation = arguments[0].accessLocation || new in_window.org.pkijs.simpl.GENERAL_NAME(); } } // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.x509.AccessDescription.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.AccessDescription({ names: { accessMethod: "accessMethod", accessLocation: { names: { block_name: "accessLocation" } } } }) ); if(asn1.verified === false) throw new Error("Object's schema was not verified against input data for AccessDescription"); // #endregion // #region Get internal properties from parsed schema this.accessMethod = asn1.result["accessMethod"].value_block.toString(); this.accessLocation = new in_window.org.pkijs.simpl.GENERAL_NAME({ schema: asn1.result["accessLocation"] }); // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.x509.AccessDescription.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.accessMethod }), this.accessLocation.toSchema() ] })); // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.x509.AccessDescription.prototype.toJSON = function() { return { accessMethod: this.accessMethod, accessLocation: this.accessLocation.toJSON() }; }; //************************************************************************************** // #endregion //************************************************************************************** // #region Simplified structure for "AuthorityInfoAccess" and "SubjectInfoAccess" types of extension //************************************************************************************** in_window.org.pkijs.simpl.x509.InfoAccess = function() { // #region Internal properties of the object this.accessDescriptions = new Array(); // Array of "simpl.x509.AccessDescription" // #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.InfoAccess.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.accessDescriptions = arguments[0].accessDescriptions || new Array(); // Array of "simpl.x509.DistributionPoint" } } // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.x509.InfoAccess.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.InfoAccess({ names: { accessDescriptions: "accessDescriptions" } }) ); if(asn1.verified === false) throw new Error("Object's schema was not verified against input data for InfoAccess"); // #endregion // #region Get internal properties from parsed schema var descriptions = asn1.result["accessDescriptions"]; for(var i = 0; i < descriptions.length; i++) this.accessDescriptions.push(new in_window.org.pkijs.simpl.x509.AccessDescription({ schema: descriptions[i] })); // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.x509.InfoAccess.prototype.toSchema = function() { // #region Create array for output sequence var output_array = new Array(); for(var i = 0; i < this.accessDescriptions.length; i++) output_array.push(this.accessDescriptions[i].toSchema()); // #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.x509.InfoAccess.prototype.toJSON = function() { var _object = { accessDescriptions: new Array() }; for(var i = 0; i < this.accessDescriptions.length; i++) _object.accessDescriptions.push(this.accessDescriptions[i].toJSON()); return _object; }; //************************************************************************************** // #endregion //************************************************************************************** // #region Simplified structure for "IssuingDistributionPoint" type of extension //************************************************************************************** in_window.org.pkijs.simpl.x509.IssuingDistributionPoint = function() { // #region Internal properties of the object // OPTIONAL this.distributionPoint // Array of "simpl.GENERAL_NAME" or a value of "simpl.RDN" type // OPTIONAL this.onlyContainsUserCerts // BOOLEAN flag // OPTIONAL this.onlyContainsCACerts // BOOLEAN flag // OPTIONAL this.onlySomeReasons // BITSTRING // OPTIONAL this.indirectCRL // BOOLEAN flag // OPTIONAL this.onlyContainsAttributeCerts // BOOLEAN flag // #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.IssuingDistributionPoint.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("distributionPoint" in arguments[0]) this.distributionPoint = arguments[0].distributionPoint; if("onlyContainsUserCerts" in arguments[0]) this.onlyContainsUserCerts = arguments[0].onlyContainsUserCerts; if("onlyContainsCACerts" in arguments[0]) this.onlyContainsCACerts = arguments[0].onlyContainsCACerts; if("onlySomeReasons" in arguments[0]) this.onlySomeReasons = arguments[0].onlySomeReasons; if("indirectCRL" in arguments[0]) this.indirectCRL = arguments[0].indirectCRL; if("onlyContainsAttributeCerts" in arguments[0]) this.onlyContainsAttributeCerts = arguments[0].onlyContainsAttributeCerts; } } // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.x509.IssuingDistributionPoint.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.IssuingDistributionPoint({ names: { distributionPoint: "distributionPoint", distributionPoint_names: "distributionPoint_names", onlyContainsUserCerts: "onlyContainsUserCerts", onlyContainsCACerts: "onlyContainsCACerts", onlySomeReasons: "onlySomeReasons", indirectCRL: "indirectCRL", onlyContainsAttributeCerts: "onlyContainsAttributeCerts" } }) ); if(asn1.verified === false) throw new Error("Object's schema was not verified against input data for IssuingDistributionPoint"); // #endregion // #region Get internal properties from parsed schema if("distributionPoint" in asn1.result) { if(asn1.result["distributionPoint"].id_block.tag_number == 0) // GENERAL_NAMES variant { this.distributionPoint = new Array(); var names = asn1.result["distributionPoint_names"]; for(var i = 0; i < names.length; i++) this.distributionPoint.push(new in_window.org.pkijs.simpl.GENERAL_NAME({ schema: names[i] })); } if(asn1.result["distributionPoint"].id_block.tag_number == 1) // RDN variant { asn1.result["distributionPoint"].id_block.tag_class = 1; // UNIVERSAL asn1.result["distributionPoint"].id_block.tag_number = 16; // SEQUENCE this.distributionPoint = new in_window.org.pkijs.simpl.RDN({ schema: asn1.result["distributionPoint"] }); } } if("onlyContainsUserCerts" in asn1.result) { var view = new Uint8Array(asn1.result["onlyContainsUserCerts"].value_block.value_hex); this.onlyContainsUserCerts = (view[0] !== 0x00); } if("onlyContainsCACerts" in asn1.result) { var view = new Uint8Array(asn1.result["onlyContainsCACerts"].value_block.value_hex); this.onlyContainsCACerts = (view[0] !== 0x00); } if("onlySomeReasons" in asn1.result) { var view = new Uint8Array(asn1.result["onlySomeReasons"].value_block.value_hex); this.onlySomeReasons = view[0]; } if("indirectCRL" in asn1.result) { var view = new Uint8Array(asn1.result["indirectCRL"].value_block.value_hex); this.indirectCRL = (view[0] !== 0x00); } if("onlyContainsAttributeCerts" in asn1.result) { var view = new Uint8Array(asn1.result["onlyContainsAttributeCerts"].value_block.value_hex); this.onlyContainsAttributeCerts = (view[0] !== 0x00); } // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.x509.IssuingDistributionPoint.prototype.toSchema = function() { // #region Create array for output sequence var output_array = new Array(); if("distributionPoint" in this) { var value; if(this.distributionPoint instanceof Array) { value = new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ id_block: { tag_class: 3, // CONTEXT-SPECIFIC tag_number: 0 // [0] } }); for(var i = 0; i < this.distributionPoint.length; i++) value.value_block.value.push(this.distributionPoint[i].toSchema()); } else { value = this.distributionPoint.toSchema(); value.id_block.tag_class = 3; // CONTEXT - SPECIFIC value.id_block.tag_number = 1; // [1] } output_array.push(value); } if("onlyContainsUserCerts" in this) { var buffer = new ArrayBuffer(1); var view = new Uint8Array(buffer); view[0] = (this.onlyContainsUserCerts === false) ? 0x00 : 0xFF; output_array.push(new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({ id_block: { tag_class: 3, // CONTEXT-SPECIFIC tag_number: 1 // [1] }, value_hex: buffer })); } if("onlyContainsCACerts" in this) { var buffer = new ArrayBuffer(1); var view = new Uint8Array(buffer); view[0] = (this.onlyContainsCACerts === false) ? 0x00 : 0xFF; output_array.push(new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({ id_block: { tag_class: 3, // CONTEXT-SPECIFIC tag_number: 2 // [2] }, value_hex: buffer })); } if("onlySomeReasons" in this) { var buffer = new ArrayBuffer(1); var view = new Uint8Array(buffer); view[0] = this.onlySomeReasons; output_array.push(new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({ id_block: { tag_class: 3, // CONTEXT-SPECIFIC tag_number: 3 // [3] }, value_hex: buffer })); } if("indirectCRL" in this) { var buffer = new ArrayBuffer(1); var view = new Uint8Array(buffer); view[0] = (this.indirectCRL === false) ? 0x00 : 0xFF; output_array.push(new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({ id_block: { tag_class: 3, // CONTEXT-SPECIFIC tag_number: 4 // [4] }, value_hex: buffer })); } if("onlyContainsAttributeCerts" in this) { var buffer = new ArrayBuffer(1); var view = new Uint8Array(buffer); view[0] = (this.onlyContainsAttributeCerts === false) ? 0x00 : 0xFF; output_array.push(new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({ id_block: { tag_class: 3, // CONTEXT-SPECIFIC tag_number: 5 // [5] }, value_hex: buffer })); } // #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.x509.IssuingDistributionPoint.prototype.toJSON = function() { var _object = {}; if("distributionPoint" in this) { if(this.distributionPoint instanceof Array) { _object.distributionPoint = new Array(); for(var i = 0; i < this.distributionPoint.length; i++) _object.distributionPoint.push(this.distributionPoint[i].toJSON()); } else _object.distributionPoint = this.distributionPoint.toJSON(); } if("onlyContainsUserCerts" in this) _object.onlyContainsUserCerts = this.onlyContainsUserCerts; if("onlyContainsCACerts" in this) _object.onlyContainsCACerts = this.onlyContainsCACerts; if("onlySomeReasons" in this) _object.onlySomeReasons = this.onlySomeReasons.toJSON(); if("indirectCRL" in this) _object.indirectCRL = this.indirectCRL; if("onlyContainsAttributeCerts" in this) _object.onlyContainsAttributeCerts = this.onlyContainsAttributeCerts; return _object; }; //************************************************************************************** // #endregion //************************************************************************************** // #region Simplified structure for "Extension" type //************************************************************************************** in_window.org.pkijs.simpl.EXTENSION = function() { // #region Internal properties of the object this.extnID = ""; this.critical = false; this.extnValue = new in_window.org.pkijs.asn1.OCTETSTRING(); // OPTIONAL this.parsedValue - Parsed "extnValue" in case of well-known "extnID" // #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.EXTENSION.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.extnID = (arguments[0].extnID || ""); this.critical = (arguments[0].critical || false); if("extnValue" in arguments[0]) this.extnValue = new in_window.org.pkijs.asn1.OCTETSTRING({ value_hex: arguments[0].extnValue }); else this.extnValue = new in_window.org.pkijs.asn1.OCTETSTRING(); if("parsedValue" in arguments[0]) this.parsedValue = arguments[0].parsedValue; } } // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.EXTENSION.prototype.fromSchema = function(schema) { // #region Check the schema is valid var asn1 = in_window.org.pkijs.compareSchema(schema, schema, in_window.org.pkijs.schema.EXTENSION({ names: { extnID: "extnID", critical: "critical", extnValue: "extnValue" } }) ); if(asn1.verified === false) throw new Error("Object's schema was not verified against input data for EXTENSION"); // #endregion // #region Get internal properties from parsed schema this.extnID = asn1.result.extnID.value_block.toString(); if("critical" in asn1.result) this.critical = asn1.result.critical.value_block.value; this.extnValue = asn1.result.extnValue; // #region Get "parsedValue" for well-known extensions var asn1 = in_window.org.pkijs.fromBER(this.extnValue.value_block.value_hex); if(asn1.offset === (-1)) return; switch(this.extnID) { case "2.5.29.9": // SubjectDirectoryAttributes this.parsedValue = new in_window.org.pkijs.simpl.x509.SubjectDirectoryAttributes({ schema: asn1.result }); break; case "2.5.29.14": // SubjectKeyIdentifier this.parsedValue = asn1.result; // Should be just a simple OCTETSTRING break; case "2.5.29.15": // KeyUsage this.parsedValue = asn1.result; // Should be just a simple BITSTRING break; case "2.5.29.16": // PrivateKeyUsagePeriod this.parsedValue = new in_window.org.pkijs.simpl.x509.PrivateKeyUsagePeriod({ schema: asn1.result }); break; case "2.5.29.17": // SubjectAltName case "2.5.29.18": // IssuerAltName this.parsedValue = new in_window.org.pkijs.simpl.x509.AltName({ schema: asn1.result }); break; case "2.5.29.19": // BasicConstraints this.parsedValue = new in_window.org.pkijs.simpl.x509.BasicConstraints({ schema: asn1.result }); break; case "2.5.29.20": // CRLNumber case "2.5.29.27": // BaseCRLNumber (delta CRL indicator) this.parsedValue = asn1.result; // Should be just a simple INTEGER break; case "2.5.29.21": // CRLReason this.parsedValue = asn1.result; // Should be just a simple ENUMERATED break; case "2.5.29.24": // InvalidityDate this.parsedValue = asn1.result; // Should be just a simple GeneralizedTime break; case "2.5.29.28": // IssuingDistributionPoint this.parsedValue = new in_window.org.pkijs.simpl.x509.IssuingDistributionPoint({ schema: asn1.result }); break; case "2.5.29.29": // CertificateIssuer this.parsedValue = new in_window.org.pkijs.simpl.GENERAL_NAMES({ schema: asn1.result }); // Should be just a simple break; case "2.5.29.30": // NameConstraints this.parsedValue = new in_window.org.pkijs.simpl.x509.NameConstraints({ schema: asn1.result }); break; case "2.5.29.31": // CRLDistributionPoints case "2.5.29.46": // FreshestCRL this.parsedValue = new in_window.org.pkijs.simpl.x509.CRLDistributionPoints({ schema: asn1.result }); break; case "2.5.29.32": // CertificatePolicies this.parsedValue = new in_window.org.pkijs.simpl.x509.CertificatePolicies({ schema: asn1.result }); break; case "2.5.29.33": // PolicyMappings this.parsedValue = new in_window.org.pkijs.simpl.x509.PolicyMappings({ schema: asn1.result }); break; case "2.5.29.35": // AuthorityKeyIdentifier this.parsedValue = new in_window.org.pkijs.simpl.x509.AuthorityKeyIdentifier({ schema: asn1.result }); break; case "2.5.29.36": // PolicyConstraints this.parsedValue = new in_window.org.pkijs.simpl.x509.PolicyConstraints({ schema: asn1.result }); break; case "2.5.29.37": // ExtKeyUsage this.parsedValue = new in_window.org.pkijs.simpl.x509.ExtKeyUsage({ schema: asn1.result }); break; case "2.5.29.54": // InhibitAnyPolicy this.parsedValue = asn1.result; // Should be just a simple INTEGER break; case "1.3.6.1.5.5.7.1.1": // AuthorityInfoAccess case "1.3.6.1.5.5.7.1.11": // SubjectInfoAccess this.parsedValue = new in_window.org.pkijs.simpl.x509.InfoAccess({ schema: asn1.result }); break; default: } // #endregion // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.EXTENSION.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.extnID })); if(this.critical) output_array.push(new in_window.org.pkijs.asn1.BOOLEAN({ value: this.critical })); output_array.push(this.extnValue); // #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.EXTENSION.prototype.toJSON = function() { var _object = { extnID: this.extnID, critical: this.critical, extnValue: this.extnValue.toJSON() }; if("parsedValue" in this) _object.parsedValue = this.parsedValue.toJSON(); return _object; }; //************************************************************************************** // #endregion //************************************************************************************** // #region Simplified structure for "Extensions" type (sequence of many Extension) //************************************************************************************** in_window.org.pkijs.simpl.EXTENSIONS = function() { // #region Internal properties of the object this.extensions_array = new Array(); // #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.EXTENSIONS.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.extensions_array = (arguments[0].extensions_array || (new Array())); } // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.EXTENSIONS.prototype.fromSchema = function(schema) { // #region Check the schema is valid var asn1 = in_window.org.pkijs.compareSchema(schema, schema, in_window.org.pkijs.schema.EXTENSIONS({ names: { extensions: "extensions" } }) ); if(asn1.verified === false) throw new Error("Object's schema was not verified against input data for EXTENSIONS"); // #endregion // #region Get internal properties from parsed schema for(var i = 0; i < asn1.result.extensions.length; i++) this.extensions_array.push(new in_window.org.pkijs.simpl.EXTENSION({ schema: asn1.result.extensions[i] })); // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.EXTENSIONS.prototype.toSchema = function() { // #region Construct and return new ASN.1 schema for this object var extension_schemas = new Array(); for(var i = 0; i < this.extensions_array.length; i++) extension_schemas.push(this.extensions_array[i].toSchema()); return (new in_window.org.pkijs.asn1.SEQUENCE({ value: extension_schemas })); // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.EXTENSIONS.prototype.toJSON = function() { var _object = { extensions_array: new Array() }; for(var i = 0; i < this.extensions_array.length; i++) _object.extensions_array.push(this.extensions_array[i].toJSON()); return _object; }; //************************************************************************************** // #endregion //************************************************************************************** // #region Simplified structure for X.509 v3 certificate (RFC5280) //************************************************************************************** in_window.org.pkijs.simpl.CERT = function() { // #region Internal properties of the object // #region Properties from certificate TBS part this.tbs = new ArrayBuffer(0); // Encoded value of certificate TBS (need to have it for certificate validation) // OPTIONAL this.version = 0; this.serialNumber = new in_window.org.pkijs.asn1.INTEGER(); // Might be a very long integer value this.signature = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); // Signature algorithm from certificate TBS part this.issuer = new in_window.org.pkijs.simpl.RDN(); this.notBefore = new in_window.org.pkijs.simpl.TIME(); this.notAfter = new in_window.org.pkijs.simpl.TIME(); this.subject = new in_window.org.pkijs.simpl.RDN(); this.subjectPublicKeyInfo = new in_window.org.pkijs.simpl.PUBLIC_KEY_INFO(); // OPTIONAL this.issuerUniqueID = new ArrayBuffer(0); // IMPLICIT bistring value // OPTIONAL this.subjectUniqueID = new ArrayBuffer(0); // IMPLICIT bistring value // OPTIONAL this.extensions = new Array(); // Array of "simpl.EXTENSION" // #endregion // #region Properties from certificate major part this.signatureAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); // Signature algorithm from certificate major part this.signatureValue = new in_window.org.pkijs.asn1.BITSTRING(); // #endregion // #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.CERT.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) { // #region Properties from certificate TBS part this.tbs = arguments[0].tbs || new ArrayBuffer(0); if("version" in arguments[0]) this.version = arguments[0].version; this.serialNumber = arguments[0].serialNumber || new in_window.org.pkijs.asn1.INTEGER(); // Might be a very long integer value this.signature = arguments[0].signature || new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); // Signature algorithm from certificate TBS part this.issuer = arguments[0].issuer || new in_window.org.pkijs.simpl.RDN(); this.notBefore = arguments[0].not_before || new in_window.org.pkijs.simpl.TIME(); this.notAfter = arguments[0].not_after || new in_window.org.pkijs.simpl.TIME(); this.subject = arguments[0].subject || new in_window.org.pkijs.simpl.RDN(); this.subjectPublicKeyInfo = arguments[0].subjectPublicKeyInfo || new in_window.org.pkijs.simpl.PUBLIC_KEY_INFO(); if("issuerUniqueID" in arguments[0]) this.issuerUniqueID = arguments[0].issuerUniqueID; if("subjectUniqueID" in arguments[0]) this.subjectUniqueID = arguments[0].subjectUniqueID; if("extensions" in arguments[0]) this.extensions = arguments[0].extensions; // #endregion // #region Properties from certificate major part this.signatureAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); // Signature algorithm from certificate major part this.signatureValue = new in_window.org.pkijs.asn1.BITSTRING(); // #endregion } } // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.CERT.prototype.fromSchema = function(schema) { // #region Check the schema is valid var asn1 = in_window.org.pkijs.compareSchema(schema, schema, in_window.org.pkijs.schema.CERT({ names: { tbsCertificate: { names: { extensions: { names: { extensions: "tbsCertificate.extensions" } } } } } }) ); if(asn1.verified === false) throw new Error("Object's schema was not verified against input data for CERT"); // #endregion // #region Get internal properties from parsed schema this.tbs = asn1.result["tbsCertificate"].value_before_decode; if("tbsCertificate.version" in asn1.result) this.version = asn1.result["tbsCertificate.version"].value_block.value_dec; this.serialNumber = asn1.result["tbsCertificate.serialNumber"]; this.signature = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ schema: asn1.result["tbsCertificate.signature"] }); this.issuer = new in_window.org.pkijs.simpl.RDN({ schema: asn1.result["tbsCertificate.issuer"] }); this.notBefore = new in_window.org.pkijs.simpl.TIME({ schema: asn1.result["tbsCertificate.notBefore"] }); this.notAfter = new in_window.org.pkijs.simpl.TIME({ schema: asn1.result["tbsCertificate.notAfter"] }); this.subject = new in_window.org.pkijs.simpl.RDN({ schema: asn1.result["tbsCertificate.subject"] }); this.subjectPublicKeyInfo = new in_window.org.pkijs.simpl.PUBLIC_KEY_INFO({ schema: asn1.result["tbsCertificate.subjectPublicKeyInfo"] }); if("tbsCertificate.issuerUniqueID" in asn1.result) this.issuerUniqueID = asn1.result["tbsCertificate.issuerUniqueID"].value_block.value_hex; if("tbsCertificate.subjectUniqueID" in asn1.result) this.issuerUniqueID = asn1.result["tbsCertificate.subjectUniqueID"].value_block.value_hex; if("tbsCertificate.extensions" in asn1.result) { this.extensions = new Array(); var extensions = asn1.result["tbsCertificate.extensions"]; for(var i = 0; i < extensions.length; i++) this.extensions.push(new in_window.org.pkijs.simpl.EXTENSION({ schema: extensions[i] })); } this.signatureAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ schema: asn1.result["signatureAlgorithm"] }); this.signatureValue = asn1.result["signatureValue"]; // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.CERT.prototype.encodeTBS = function() { /// Create ASN.1 schema for existing values of TBS part for the certificate // #region Create array for output sequence var output_array = new Array(); if("version" in this) output_array.push(new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ optional: true, id_block: { tag_class: 3, // CONTEXT-SPECIFIC tag_number: 0 // [0] }, value: [ new in_window.org.pkijs.asn1.INTEGER({ value: this.version }) // EXPLICIT integer value ] })); output_array.push(this.serialNumber); output_array.push(this.signature.toSchema()); output_array.push(this.issuer.toSchema()); output_array.push(new in_window.org.pkijs.asn1.SEQUENCE({ value: [ this.notBefore.toSchema(), this.notAfter.toSchema() ] })); output_array.push(this.subject.toSchema()); output_array.push(this.subjectPublicKeyInfo.toSchema()); if("issuerUniqueID" in this) output_array.push(new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({ optional: true, id_block: { tag_class: 3, // CONTEXT-SPECIFIC tag_number: 1 // [1] }, value_hex: this.issuerUniqueID })); if("subjectUniqueID" in this) output_array.push(new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({ optional: true, id_block: { tag_class: 3, // CONTEXT-SPECIFIC tag_number: 2 // [2] }, value_hex: this.subjectUniqueID })); if("subjectUniqueID" in this) output_array.push(new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ optional: true, id_block: { tag_class: 3, // CONTEXT-SPECIFIC tag_number: 3 // [3] }, value: [this.extensions.toSchema()] })); if("extensions" in this) { var extensions = new Array(); for(var i = 0; i < this.extensions.length; i++) extensions.push(this.extensions[i].toSchema()); output_array.push(new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ optional: true, id_block: { tag_class: 3, // CONTEXT-SPECIFIC tag_number: 3 // [3] }, value: [new in_window.org.pkijs.asn1.SEQUENCE({ value: extensions })] })); } // #endregion // #region Create and return output sequence return (new in_window.org.pkijs.asn1.SEQUENCE({ value: output_array })); // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.CERT.prototype.toSchema = function(encodeFlag) { /// If param equal to false then create TBS schema via decoding stored value. In othe case create TBS schema via assembling from TBS parts. if(typeof encodeFlag === "undefined") encodeFlag = false; var tbs_schema = {}; // #region Decode stored TBS value if(encodeFlag === false) { if(this.tbs.length === 0) // No stored certificate TBS part return in_window.org.pkijs.schema.CERT().value[0]; var tbs_asn1 = in_window.org.pkijs.fromBER(this.tbs); tbs_schema = tbs_asn1.result; } // #endregion // #region Create TBS schema via assembling from TBS parts else tbs_schema = in_window.org.pkijs.simpl.CERT.prototype.encodeTBS.call(this); // #endregion // #region Construct and return new ASN.1 schema for this object return (new in_window.org.pkijs.asn1.SEQUENCE({ value: [ tbs_schema, this.signatureAlgorithm.toSchema(), this.signatureValue ] })); // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.CERT.prototype.verify = function() { /// !!! Works well in Chrome dev versions only (April 2014th) !!! /// Returns a new Promise object (in case of error), or a result of "crypto.subtle.veryfy" function // #region Global variables var sequence = Promise.resolve(); var subjectPublicKeyInfo = {}; var signature = this.signatureValue; var tbs = this.tbs; var _this = this; // #endregion // #region Set correct "subjectPublicKeyInfo" value if(arguments[0] instanceof Object) { if("issuerCertificate" in arguments[0]) // Must be of type "simpl.CERT" subjectPublicKeyInfo = arguments[0].issuerCertificate.subjectPublicKeyInfo; } else { if(this.issuer.isEqual(this.subject)) // Self-signed certificate subjectPublicKeyInfo = this.subjectPublicKeyInfo; } if((subjectPublicKeyInfo instanceof in_window.org.pkijs.simpl.PUBLIC_KEY_INFO) === false) return new Promise(function(resolve, reject) { reject("Please provide issuer certificate as a 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 Find signer's hashing algorithm var sha_algorithm = in_window.org.pkijs.getHashAlgorithm(this.signatureAlgorithm); if(sha_algorithm === "") return new Promise(function(resolve, reject) { reject("Unsupported signature algorithm: " + _this.signatureAlgorithm.algorithm_id); }); // #endregion // #region Importing public key sequence = sequence.then( function() { // #region Get information about public key algorithm and default parameters for import var algorithmObject = in_window.org.pkijs.getAlgorithmByOID(_this.signatureAlgorithm.algorithm_id); if(("name" in algorithmObject) === false) return new Promise(function(resolve, reject) { reject("Unsupported public key algorithm: " + _this.signatureAlgorithm.algorithm_id); }); var algorithm_name = algorithmObject.name; var algorithm = in_window.org.pkijs.getAlgorithmParameters(algorithm_name, "importkey"); if("hash" in algorithm.algorithm) algorithm.algorithm.hash.name = sha_algorithm; // #endregion var publicKeyInfo_schema = subjectPublicKeyInfo.toSchema(); var publicKeyInfo_buffer = publicKeyInfo_schema.toBER(false); var publicKeyInfo_view = new Uint8Array(publicKeyInfo_buffer); return crypto.importKey("spki", publicKeyInfo_view, algorithm.algorithm, true, algorithm.usages); } ); // #endregion // #region Verify signature for the certificate sequence = sequence.then( function(publicKey) { // #region Get default algorithm parameters for verification var algorithm = in_window.org.pkijs.getAlgorithmParameters(publicKey.algorithm.name, "verify"); if("hash" in algorithm.algorithm) algorithm.algorithm.hash.name = sha_algorithm; // #endregion // #region Special case for ECDSA signatures var signature_value = signature.value_block.value_hex; if(publicKey.algorithm.name === "ECDSA") { var asn1 = in_window.org.pkijs.fromBER(signature_value); signature_value = in_window.org.pkijs.createECDSASignatureFromCMS(asn1.result); } // #endregion // #region Special case for RSA-PSS if(publicKey.algorithm.name === "RSA-PSS") { var pssParameters; try { pssParameters = new in_window.org.pkijs.simpl.x509.RSASSA_PSS_params({ schema: _this.signatureAlgorithm.algorithm_params }); } catch(ex) { return new Promise(function(resolve, reject) { reject(ex); }); } if("saltLength" in pssParameters) algorithm.algorithm.saltLength = pssParameters.saltLength; else algorithm.algorithm.saltLength = 20; var hash_algo = "SHA-1"; if("hashAlgorithm" in pssParameters) { var hashAlgorithm = in_window.org.pkijs.getAlgorithmByOID(pssParameters.hashAlgorithm.algorithm_id); if(("name" in hashAlgorithm) === false) return new Promise(function(resolve, reject) { reject("Unrecognized hash algorithm: " + pssParameters.hashAlgorithm.algorithm_id); }); hash_algo = hashAlgorithm.name; } algorithm.algorithm.hash.name = hash_algo; } // #endregion return crypto.verify(algorithm.algorithm, publicKey, new Uint8Array(signature_value), new Uint8Array(tbs)); } ); // #endregion return sequence; }; //************************************************************************************** in_window.org.pkijs.simpl.CERT.prototype.sign = function(privateKey, hashAlgorithm) { /// Private key for "subjectPublicKeyInfo" structure /// Hashing algorithm. Default SHA-1 // #region Initial variables var _this = this; // #endregion // #region Get a private key from function parameter if(typeof privateKey === "undefined") return new Promise(function(resolve, reject) { reject("Need to provide a private key for signing"); }); // #endregion // #region Get hashing algorithm if(typeof hashAlgorithm === "undefined") hashAlgorithm = "SHA-1"; else { // #region Simple check for supported algorithm var oid = in_window.org.pkijs.getOIDByAlgorithm({ name: hashAlgorithm }); if(oid === "") return new Promise(function(resolve, reject) { reject("Unsupported hash algorithm: " + hashAlgorithm); }); // #endregion } // #endregion // #region Get a "default parameters" for current algorithm var defParams = in_window.org.pkijs.getAlgorithmParameters(privateKey.algorithm.name, "sign"); defParams.algorithm.hash.name = hashAlgorithm; // #endregion // #region Fill internal structures base on "privateKey" and "hashAlgorithm" switch(privateKey.algorithm.name.toUpperCase()) { case "RSASSA-PKCS1-V1_5": case "ECDSA": _this.signature.algorithm_id = in_window.org.pkijs.getOIDByAlgorithm(defParams.algorithm); _this.signatureAlgorithm.algorithm_id = _this.signature.algorithm_id; break; case "RSA-PSS": { // #region Set "saltLength" as a length (in octets) of hash function result switch(hashAlgorithm.toUpperCase()) { case "SHA-256": defParams.algorithm.saltLength = 32; break; case "SHA-384": defParams.algorithm.saltLength = 48; break; case "SHA-512": defParams.algorithm.saltLength = 64; break; default: } // #endregion // #region Fill "RSASSA_PSS_params" object var paramsObject = {}; if(hashAlgorithm.toUpperCase() !== "SHA-1") { var hashAlgorithmOID = in_window.org.pkijs.getOIDByAlgorithm({ name: hashAlgorithm }); if(hashAlgorithmOID === "") return new Promise(function(resolve, reject) { reject("Unsupported hash algorithm: " + hashAlgorithm); }); paramsObject.hashAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ algorithm_id: hashAlgorithmOID, algorithm_params: new in_window.org.pkijs.asn1.NULL() }); paramsObject.maskGenAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ algorithm_id: "1.2.840.113549.1.1.8", // MGF1 algorithm_params: paramsObject.hashAlgorithm.toSchema() }) } if(defParams.algorithm.saltLength !== 20) paramsObject.saltLength = defParams.algorithm.saltLength; var pssParameters = new in_window.org.pkijs.simpl.x509.RSASSA_PSS_params(paramsObject); // #endregion // #region Automatically set signature algorithm _this.signature = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ algorithm_id: "1.2.840.113549.1.1.10", algorithm_params: pssParameters.toSchema() }); _this.signatureAlgorithm = _this.signature; // Must be the same // #endregion } break; default: return new Promise(function(resolve, reject) { reject("Unsupported signature algorithm: " + privateKey.algorithm.name); }); } // #endregion // #region Create TBS data for signing _this.tbs = in_window.org.pkijs.simpl.CERT.prototype.encodeTBS.call(this).toBER(false); // #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 Signing TBS data on provided private key return crypto.sign(defParams.algorithm, privateKey, new Uint8Array(_this.tbs)).then( function(result) { // #region Special case for ECDSA algorithm if(defParams.algorithm.name === "ECDSA") result = in_window.org.pkijs.createCMSECDSASignature(result); // #endregion _this.signatureValue = new in_window.org.pkijs.asn1.BITSTRING({ value_hex: result }); }, function(error) { return new Promise(function(resolve, reject) { reject("Signing error: " + error); }); } ); // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.CERT.prototype.getPublicKey = function() { /// Importing public key for current certificate // #region Initial variables var algorithm; // #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 Find correct algorithm for imported public key if(arguments[0] instanceof Object) { if("algorithm" in arguments[0]) algorithm = arguments[0].algorithm; else return new Promise(function(resolve, reject) { reject("Absent mandatory parameter \"algorithm\""); }); } else { // #region Find signer's hashing algorithm var sha_algorithm = in_window.org.pkijs.getHashAlgorithm(this.signatureAlgorithm); if(sha_algorithm === "") return new Promise(function(resolve, reject) { reject("Unsupported signature algorithm: " + _this.signatureAlgorithm.algorithm_id); }); // #endregion // #region Get information about public key algorithm and default parameters for import var algorithmObject = in_window.org.pkijs.getAlgorithmByOID(this.signatureAlgorithm.algorithm_id); if(("name" in algorithmObject) === false) return new Promise(function(resolve, reject) { reject("Unsupported public key algorithm: " + _this.signatureAlgorithm.algorithm_id); }); var algorithm_name = algorithmObject.name; algorithm = in_window.org.pkijs.getAlgorithmParameters(algorithm_name, "importkey"); if("hash" in algorithm.algorithm) algorithm.algorithm.hash.name = sha_algorithm; // #endregion } // #endregion // #region Get neccessary values from internal fields for current certificate var publicKeyInfo_schema = this.subjectPublicKeyInfo.toSchema(); var publicKeyInfo_buffer = publicKeyInfo_schema.toBER(false); var publicKeyInfo_view = new Uint8Array(publicKeyInfo_buffer); // #endregion return crypto.importKey("spki", publicKeyInfo_view, algorithm.algorithm, true, algorithm.usages); }; //************************************************************************************** in_window.org.pkijs.simpl.CERT.prototype.getKeyHash = function() { /// Get SHA-1 hash value for subject public key // #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 return crypto.digest({ name: "sha-1" }, new Uint8Array(this.subjectPublicKeyInfo.subjectPublicKey.value_block.value_hex)); }; //************************************************************************************** in_window.org.pkijs.simpl.CERT.prototype.toJSON = function() { var _object = { tbs: in_window.org.pkijs.bufferToHexCodes(this.tbs, 0, this.tbs.byteLength), serialNumber: this.serialNumber.toJSON(), signature: this.signature.toJSON(), issuer: this.issuer.toJSON(), notBefore: this.notBefore.toJSON(), notAfter: this.notAfter.toJSON(), subject: this.subject.toJSON(), subjectPublicKeyInfo: this.subjectPublicKeyInfo.toJSON(), signatureAlgorithm: this.signatureAlgorithm.toJSON(), signatureValue: this.signatureValue.toJSON() }; if("version" in this) _object.version = this.version; if("issuerUniqueID" in this) _object.issuerUniqueID = in_window.org.pkijs.bufferToHexCodes(this.issuerUniqueID, 0, this.issuerUniqueID.byteLength); if("subjectUniqueID" in this) _object.subjectUniqueID = in_window.org.pkijs.bufferToHexCodes(this.subjectUniqueID, 0, this.subjectUniqueID.byteLength); if("extensions" in this) { _object.extensions = new Array(); for(var i = 0; i < this.extensions.length; i++) _object.extensions.push(this.extensions[i].toJSON()); } return _object; }; //************************************************************************************** // #endregion //************************************************************************************** // #region Simplified structure for "revoked certificate" type (to use in CRL) //************************************************************************************** in_window.org.pkijs.simpl.REV_CERT = function() { // #region Internal properties of the object this.userCertificate = new in_window.org.pkijs.asn1.INTEGER(); this.revocationDate = new in_window.org.pkijs.simpl.TIME(); // OPTIONAL this.crlEntryExtensions = new Array(); // Array of "in_window.org.pkijs.simpl.EXTENSION"); // #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.REV_CERT.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.userCertificate = arguments[0].userCertificate || new in_window.org.pkijs.asn1.INTEGER(); this.revocationDate = arguments[0].revocationDate || new in_window.org.pkijs.simpl.TIME(); if("crlEntryExtensions" in arguments[0]) this.crlEntryExtensions = arguments[0].crlEntryExtensions; } } // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.REV_CERT.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: [ new in_window.org.pkijs.asn1.INTEGER({ name: "userCertificate" }), in_window.org.pkijs.schema.TIME({ names: { utcTimeName: "revocationDate", generalTimeName: "revocationDate" } }), in_window.org.pkijs.schema.EXTENSIONS({ names: { block_name: "crlEntryExtensions" } }, true) ] }) ); if(asn1.verified === false) throw new Error("Object's schema was not verified against input data for REV_CERT"); // #endregion // #region Get internal properties from parsed schema this.userCertificate = asn1.result["userCertificate"]; this.revocationDate = new in_window.org.pkijs.simpl.TIME({ schema: asn1.result["revocationDate"] }); if("crlEntryExtensions" in asn1.result) { this.crlEntryExtensions = new Array(); var exts = asn1.result["crlEntryExtensions"].value_block.value; for(var i = 0; i < exts.length; i++) this.crlEntryExtensions.push(new in_window.org.pkijs.simpl.EXTENSION({ schema: exts[i] })); } // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.REV_CERT.prototype.toSchema = function() { // #region Create array for output sequence var sequence_array = new Array(); sequence_array.push(this.userCertificate); sequence_array.push(this.revocationDate.toSchema()); if("crlEntryExtensions" in this) { var exts = new Array(); for(var i = 0; i < this.crlEntryExtensions.length; i++) exts.push(this.crlEntryExtensions[i].toSchema()); sequence_array.push(new in_window.org.pkijs.asn1.SEQUENCE({ value: exts })); } // #endregion // #region Construct and return new ASN.1 schema for this object return (new in_window.org.pkijs.asn1.SEQUENCE({ value: sequence_array })); // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.REV_CERT.prototype.toJSON = function() { var _object = { userCertificate: this.userCertificate.toJSON(), revocationDate: this.revocationDate.toJSON }; if("crlEntryExtensions" in this) { _object.crlEntryExtensions = new Array(); for(var i = 0; i < this.crlEntryExtensions.length; i++) _object.crlEntryExtensions.push(this.crlEntryExtensions[i].toJSON()); } return _object; }; //************************************************************************************** // #endregion //************************************************************************************** // #region Simplified structure for X.509 CRL (Certificate Revocation List)(RFC5280) //************************************************************************************** in_window.org.pkijs.simpl.CRL = function() { // #region Internal properties of the object // #region Properties from CRL TBS part this.tbs = new ArrayBuffer(0); // OPTIONAL this.version = 1; this.signature = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); this.issuer = new in_window.org.pkijs.simpl.RDN(); this.thisUpdate = new in_window.org.pkijs.simpl.TIME(); // OPTIONAL this.nextUpdate = new in_window.org.pkijs.simpl.TIME(); // OPTIONAL this.revokedCertificates = new Array(); // Array of REV_CERT objects // OPTIONAL this.crlExtensions = new Array(); // Array of in_window.org.pkijs.simpl.EXTENSION(); // #endregion // #region Properties from CRL major part this.signatureAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); this.signatureValue = new in_window.org.pkijs.asn1.BITSTRING(); // #endregion // #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.CRL.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) { // #region Properties from CRL TBS part this.tbs = arguments[0].tbs || new ArrayBuffer(0); if("version" in arguments[0]) this.version = arguments[0].version; this.signature = arguments[0].signature || new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); this.issuer = arguments[0].issuer || new in_window.org.pkijs.simpl.RDN(); this.thisUpdate = arguments[0].thisUpdate || new in_window.org.pkijs.simpl.TIME(); if("nextUpdate" in arguments[0]) this.nextUpdate = arguments[0].nextUpdate; if("revokedCertificates" in arguments[0]) this.revokedCertificates = arguments[0].revokedCertificates; if("crlExtensions" in arguments[0]) this.crlExtensions = arguments[0].crlExtensions; // #endregion // #region Properties from CRL major part this.signatureAlgorithm = arguments[0].signatureAlgorithm || new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); this.signatureValue = arguments[0].signatureValue || new in_window.org.pkijs.asn1.BITSTRING(); // #endregion } } // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.CRL.prototype.fromSchema = function(schema) { // #region Check the schema is valid var asn1 = in_window.org.pkijs.compareSchema(schema, schema, in_window.org.pkijs.schema.CRL() ); if(asn1.verified === false) throw new Error("Object's schema was not verified against input data for CRL"); // #endregion // #region Get internal properties from parsed schema this.tbs = asn1.result["tbsCertList"].value_before_decode; if("tbsCertList.version" in asn1.result) this.version = asn1.result["tbsCertList.version"].value_block.value_dec; this.signature = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ schema: asn1.result["tbsCertList.signature"] }); this.issuer = new in_window.org.pkijs.simpl.RDN({ schema: asn1.result["tbsCertList.issuer"] }); this.thisUpdate = new in_window.org.pkijs.simpl.TIME({ schema: asn1.result["tbsCertList.thisUpdate"] }); if("tbsCertList.nextUpdate" in asn1.result) this.nextUpdate = new in_window.org.pkijs.simpl.TIME({ schema: asn1.result["tbsCertList.nextUpdate"] }); if("tbsCertList.revokedCertificates" in asn1.result) { this.revokedCertificates = new Array(); var rev_certs = asn1.result["tbsCertList.revokedCertificates"]; for(var i = 0; i < rev_certs.length; i++) this.revokedCertificates.push(new in_window.org.pkijs.simpl.REV_CERT({ schema: rev_certs[i] })); } if("tbsCertList.extensions" in asn1.result) { this.crlExtensions = new Array(); var exts = asn1.result["tbsCertList.extensions"].value_block.value; for(var i = 0; i < exts.length; i++) this.crlExtensions.push(new in_window.org.pkijs.simpl.EXTENSION({ schema: exts[i] })); } this.signatureAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ schema: asn1.result["signatureAlgorithm"] }); this.signatureValue = asn1.result["signatureValue"]; // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.CRL.prototype.encodeTBS = function() { // #region Create array for output sequence var output_array = new Array(); if("version" in this) output_array.push(new in_window.org.pkijs.asn1.INTEGER({ value: this.version })); output_array.push(this.signature.toSchema()); output_array.push(this.issuer.toSchema()); output_array.push(this.thisUpdate.toSchema()); if("nextUpdate" in this) output_array.push(this.nextUpdate.toSchema()); if("revokedCertificates" in this) { var rev_certificates = new Array(); for(var i = 0; i < this.revokedCertificates.length; i++) rev_certificates.push(this.revokedCertificates[i].toSchema()); output_array.push(new in_window.org.pkijs.asn1.SEQUENCE({ value: rev_certificates })); } if("crlExtensions" in this) { var extensions = new Array(); for(var j = 0; j < this.crlExtensions.length; j++) extensions.push(this.crlExtensions[j].toSchema()); output_array.push(new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ optional: true, id_block: { tag_class: 3, // CONTEXT-SPECIFIC tag_number: 0 // [0] }, value: [ new in_window.org.pkijs.asn1.SEQUENCE({ value: extensions }) ] })); } // #endregion return (new in_window.org.pkijs.asn1.SEQUENCE({ value: output_array })); }; //************************************************************************************** in_window.org.pkijs.simpl.CRL.prototype.toSchema = function(encodeFlag) { /// If param equal to false then create TBS schema via decoding stored value. In othe case create TBS schema via assembling from TBS parts. // #region Check "encodeFlag" if(typeof encodeFlag === "undefined") encodeFlag = false; // #endregion // #region Decode stored TBS value var tbs_schema; if(encodeFlag === false) { if(this.tbs.length === 0) // No stored TBS part return in_window.org.pkijs.schema.CRL(); tbs_schema = in_window.org.pkijs.fromBER(this.tbs).result; } // #endregion // #region Create TBS schema via assembling from TBS parts else tbs_schema = in_window.org.pkijs.simpl.CRL.prototype.encodeTBS.call(this); // #endregion // #region Construct and return new ASN.1 schema for this object return (new in_window.org.pkijs.asn1.SEQUENCE({ value: [ tbs_schema, this.signatureAlgorithm.toSchema(), this.signatureValue ] })); // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.CRL.prototype.verify = function() { // #region Global variables var sequence = Promise.resolve(); var signature = this.signatureValue; var tbs = this.tbs; var subjectPublicKeyInfo = -1; var _this = this; // #endregion // #region Get information about CRL issuer certificate if(arguments[0] instanceof Object) { if("issuerCertificate" in arguments[0]) // "issuerCertificate" must be of type "simpl.CERT" { subjectPublicKeyInfo = arguments[0].issuerCertificate.subjectPublicKeyInfo; // The CRL issuer name and "issuerCertificate" subject name are not equal if(this.issuer.isEqual(arguments[0].issuerCertificate.subject) == false) return new Promise(function(resolve, reject) { resolve(false); }); } // #region In case if there is only public key during verification if("publicKeyInfo" in arguments[0]) subjectPublicKeyInfo = arguments[0].publicKeyInfo; // Must be of type "org.pkijs.simpl.PUBLIC_KEY_INFO" // #endregion } if((subjectPublicKeyInfo instanceof in_window.org.pkijs.simpl.PUBLIC_KEY_INFO) === false) return new Promise(function(resolve, reject) { reject("Issuer's certificate must be provided as an input parameter"); }); // #endregion // #region Check the CRL for unknown critical extensions if("crlExtensions" in this) { for(var i = 0; i < this.crlExtensions.length; i++) { if(this.crlExtensions[i].critical) { // We can not be sure that unknown extension has no value for CRL signature if(("parsedValue" in this.crlExtensions[i]) == false) return new Promise(function(resolve, reject) { resolve(false); }); } } } // #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 Find signer's hashing algorithm var sha_algorithm = in_window.org.pkijs.getHashAlgorithm(this.signatureAlgorithm); if(sha_algorithm === "") return new Promise(function(resolve, reject) { reject("Unsupported signature algorithm: " + _this.signatureAlgorithm.algorithm_id); }); // #endregion // #region Import public key sequence = sequence.then( function() { // #region Get information about public key algorithm and default parameters for import var algorithmObject = in_window.org.pkijs.getAlgorithmByOID(_this.signature.algorithm_id); if(("name" in algorithmObject) === "") return new Promise(function(resolve, reject) { reject("Unsupported public key algorithm: " + _this.signature.algorithm_id); }); var algorithm_name = algorithmObject.name; var algorithm = in_window.org.pkijs.getAlgorithmParameters(algorithm_name, "importkey"); if("hash" in algorithm.algorithm) algorithm.algorithm.hash.name = sha_algorithm; // #endregion var publicKeyInfo_schema = subjectPublicKeyInfo.toSchema(); var publicKeyInfo_buffer = publicKeyInfo_schema.toBER(false); var publicKeyInfo_view = new Uint8Array(publicKeyInfo_buffer); return crypto.importKey("spki", publicKeyInfo_view, algorithm.algorithm, true, algorithm.usages); } ); // #endregion // #region Verify signature for the certificate sequence = sequence.then( function(publicKey) { // #region Get default algorithm parameters for verification var algorithm = in_window.org.pkijs.getAlgorithmParameters(publicKey.algorithm.name, "verify"); if("hash" in algorithm.algorithm) algorithm.algorithm.hash.name = sha_algorithm; // #endregion // #region Special case for ECDSA signatures var signature_value = signature.value_block.value_hex; if(publicKey.algorithm.name === "ECDSA") { var asn1 = in_window.org.pkijs.fromBER(signature_value); signature_value = in_window.org.pkijs.createECDSASignatureFromCMS(asn1.result); } // #endregion // #region Special case for RSA-PSS if(publicKey.algorithm.name === "RSA-PSS") { var pssParameters; try { pssParameters = new in_window.org.pkijs.simpl.x509.RSASSA_PSS_params({ schema: _this.signatureAlgorithm.algorithm_params }); } catch(ex) { return new Promise(function(resolve, reject) { reject(ex); }); } if("saltLength" in pssParameters) algorithm.algorithm.saltLength = pssParameters.saltLength; else algorithm.algorithm.saltLength = 20; var hash_algo = "SHA-1"; if("hashAlgorithm" in pssParameters) { var hashAlgorithm = in_window.org.pkijs.getAlgorithmByOID(pssParameters.hashAlgorithm.algorithm_id); if(("name" in hashAlgorithm) === false) return new Promise(function(resolve, reject) { reject("Unrecognized hash algorithm: " + pssParameters.hashAlgorithm.algorithm_id); }); hash_algo = hashAlgorithm.name; } algorithm.algorithm.hash.name = hash_algo; } // #endregion return crypto.verify(algorithm.algorithm, publicKey, new Uint8Array(signature_value), new Uint8Array(tbs)); } ); // #endregion return sequence; }; //************************************************************************************** in_window.org.pkijs.simpl.CRL.prototype.sign = function(privateKey, hashAlgorithm) { /// Private key for "subjectPublicKeyInfo" structure /// Hashing algorithm. Default SHA-1 // #region Initial variables var _this = this; // #endregion // #region Get a private key from function parameter if(typeof privateKey === "undefined") return new Promise(function(resolve, reject) { reject("Need to provide a private key for signing"); }); // #endregion // #region Get hashing algorithm if(typeof hashAlgorithm === "undefined") hashAlgorithm = "SHA-1"; else { // #region Simple check for supported algorithm var oid = in_window.org.pkijs.getOIDByAlgorithm({ name: hashAlgorithm }); if(oid === "") return new Promise(function(resolve, reject) { reject("Unsupported hash algorithm: " + hashAlgorithm); }); // #endregion } // #endregion // #region Get a "default parameters" for current algorithm var defParams = in_window.org.pkijs.getAlgorithmParameters(privateKey.algorithm.name, "sign"); defParams.algorithm.hash.name = hashAlgorithm; // #endregion // #region Fill internal structures base on "privateKey" and "hashAlgorithm" switch(privateKey.algorithm.name.toUpperCase()) { case "RSASSA-PKCS1-V1_5": case "ECDSA": _this.signature.algorithm_id = in_window.org.pkijs.getOIDByAlgorithm(defParams.algorithm); _this.signatureAlgorithm.algorithm_id = _this.signature.algorithm_id; break; case "RSA-PSS": { // #region Set "saltLength" as a length (in octets) of hash function result switch(hashAlgorithm.toUpperCase()) { case "SHA-256": defParams.algorithm.saltLength = 32; break; case "SHA-384": defParams.algorithm.saltLength = 48; break; case "SHA-512": defParams.algorithm.saltLength = 64; break; default: } // #endregion // #region Fill "RSASSA_PSS_params" object var paramsObject = {}; if(hashAlgorithm.toUpperCase() !== "SHA-1") { var hashAlgorithmOID = in_window.org.pkijs.getOIDByAlgorithm({ name: hashAlgorithm }); if(hashAlgorithmOID === "") return new Promise(function(resolve, reject) { reject("Unsupported hash algorithm: " + hashAlgorithm); }); paramsObject.hashAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ algorithm_id: hashAlgorithmOID, algorithm_params: new in_window.org.pkijs.asn1.NULL() }); paramsObject.maskGenAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ algorithm_id: "1.2.840.113549.1.1.8", // MGF1 algorithm_params: paramsObject.hashAlgorithm.toSchema() }) } if(defParams.algorithm.saltLength !== 20) paramsObject.saltLength = defParams.algorithm.saltLength; var pssParameters = new in_window.org.pkijs.simpl.x509.RSASSA_PSS_params(paramsObject); // #endregion // #region Automatically set signature algorithm _this.signature = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ algorithm_id: "1.2.840.113549.1.1.10", algorithm_params: pssParameters.toSchema() }); _this.signatureAlgorithm = _this.signature; // Must be the same // #endregion } break; default: return new Promise(function(resolve, reject) { reject("Unsupported signature algorithm: " + privateKey.algorithm.name); }); } // #endregion // #region Create TBS data for signing _this.tbs = in_window.org.pkijs.simpl.CRL.prototype.encodeTBS.call(this).toBER(false); // #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 Signing TBS data on provided private key return crypto.sign( defParams.algorithm, privateKey, new Uint8Array(_this.tbs)). then( function(result) { // #region Special case for ECDSA algorithm if(defParams.algorithm.name === "ECDSA") result = in_window.org.pkijs.createCMSECDSASignature(result); // #endregion _this.signatureValue = new in_window.org.pkijs.asn1.BITSTRING({ value_hex: result }); }, function(error) { return new Promise(function(resolve, reject) { reject("Signing error: " + error); }); } ); // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.CRL.prototype.isCertificateRevoked = function() { // #region Get input certificate var certificate = {}; if(arguments[0] instanceof Object) { if("certificate" in arguments[0]) certificate = arguments[0].certificate; } if((certificate instanceof in_window.org.pkijs.simpl.CERT) === false) return false; // #endregion // #region Check that issuer of the input certificate is the same with issuer of this CRL if(this.issuer.isEqual(certificate.issuer) === false) return false; // #endregion // #region Check that there are revoked certificates in this CRL if(("revokedCertificates" in this) === false) return false; // #endregion // #region Search for input certificate in revoked certificates array for(var i = 0; i < this.revokedCertificates.length; i++) { if(this.revokedCertificates[i].userCertificate.isEqual(certificate.serialNumber)) return true; } // #endregion return false; }; //************************************************************************************** in_window.org.pkijs.simpl.CRL.prototype.toJSON = function() { var _object = { tbs: in_window.org.pkijs.bufferToHexCodes(this.tbs, 0, this.tbs.byteLength), signature: this.signature.toJSON(), issuer: this.issuer.toJSON(), thisUpdate: this.thisUpdate.toJSON(), signatureAlgorithm: this.signatureAlgorithm.toJSON(), signatureValue: this.signatureValue.toJSON() }; if("version" in this) _object.version = this.version; if("nextUpdate" in this) _object.nextUpdate = this.nextUpdate.toJSON(); if("revokedCertificates" in this) { _object.revokedCertificates = new Array(); for(var i = 0; i < this.revokedCertificates.length; i++) _object.revokedCertificates.push(this.revokedCertificates[i].toJSON()); } if("crlExtensions" in this) { _object.crlExtensions = new Array(); for(var i = 0; i < this.crlExtensions.length; i++) _object.crlExtensions.push(this.crlExtensions[i].toJSON()); } return _object; }; //************************************************************************************** // #endregion //************************************************************************************** // #region Simplified structure for "Attribute" type //************************************************************************************** in_window.org.pkijs.simpl.ATTRIBUTE = function() { // #region Internal properties of the object this.type = ""; this.values = new Array(); // #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.ATTRIBUTE.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.values = arguments[0].values || new Array(); } } // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.ATTRIBUTE.prototype.fromSchema = function(schema) { // #region Check the schema is valid var asn1 = in_window.org.pkijs.compareSchema(schema, schema, in_window.org.pkijs.schema.ATTRIBUTE({ names: { type: "type", values: "values" } }) ); if(asn1.verified === false) throw new Error("Object's schema was not verified against input data for ATTRIBUTE"); // #endregion // #region Get internal properties from parsed schema this.type = asn1.result["type"].value_block.toString(); this.values = asn1.result["values"]; // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.ATTRIBUTE.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 }), new in_window.org.pkijs.asn1.SET({ value: this.values }) ] })); // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.ATTRIBUTE.prototype.toJSON = function() { var _object = { type: this.type, values: new Array() }; for(var i = 0; i < this.values.length; i++) _object.values.push(this.values[i].toJSON()); return _object; }; //************************************************************************************** // #endregion //************************************************************************************** // #region Simplified structure for PKCS#10 certificate request //************************************************************************************** in_window.org.pkijs.simpl.PKCS10 = function() { // #region Internal properties of the object this.tbs = new ArrayBuffer(0); this.version = 0; this.subject = new in_window.org.pkijs.simpl.RDN(); this.subjectPublicKeyInfo = new in_window.org.pkijs.simpl.PUBLIC_KEY_INFO(); // OPTIONAL this.attributes = new Array(); // Array of simpl.ATTRIBUTE objects this.signatureAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); // Signature algorithm from certificate major part this.signatureValue = 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.PKCS10.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.tbs = arguments[0].tbs || new ArrayBuffer(0); this.version = arguments[0].version || 0; this.subject = arguments[0].subject || new in_window.org.pkijs.simpl.RDN(); this.subjectPublicKeyInfo = arguments[0].subjectPublicKeyInfo || new in_window.org.pkijs.simpl.PUBLIC_KEY_INFO(); if("attributes" in arguments[0]) this.attributes = arguments[0].attributes; this.signatureAlgorithm = arguments[0].signatureAlgorithm || new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); // Signature algorithm from certificate major part this.signatureValue = arguments[0].signatureValue || new in_window.org.pkijs.asn1.BITSTRING(); } } // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.PKCS10.prototype.fromSchema = function(schema) { // #region Check the schema is valid var asn1 = in_window.org.pkijs.compareSchema(schema, schema, in_window.org.pkijs.schema.PKCS10() ); if(asn1.verified === false) throw new Error("Object's schema was not verified against input data for PKCS10"); // #endregion // #region Get internal properties from parsed schema this.tbs = asn1.result["CertificationRequestInfo"].value_before_decode; this.version = asn1.result["CertificationRequestInfo.version"].value_block.value_dec; this.subject = new in_window.org.pkijs.simpl.RDN({ schema: asn1.result["CertificationRequestInfo.subject"] }); this.subjectPublicKeyInfo = new in_window.org.pkijs.simpl.PUBLIC_KEY_INFO({ schema: asn1.result["CertificationRequestInfo.subjectPublicKeyInfo"] }); if("CertificationRequestInfo.attributes" in asn1.result) { this.attributes = new Array(); var attrs = asn1.result["CertificationRequestInfo.attributes"]; for(var i = 0; i < attrs.length; i++) this.attributes.push(new in_window.org.pkijs.simpl.ATTRIBUTE({ schema: attrs[i] })); } this.signatureAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ schema: asn1.result["signatureAlgorithm"] }); this.signatureValue = asn1.result["signatureValue"]; // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.PKCS10.prototype.encodeTBS = 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.subject.toSchema()); output_array.push(this.subjectPublicKeyInfo.toSchema()); if("attributes" in this) { var attributes = new Array(); for(var i = 0; i < this.attributes.length; i++) attributes.push(this.attributes[i].toSchema()); output_array.push(new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ id_block: { tag_class: 3, // CONTEXT-SPECIFIC tag_number: 0 // [0] }, value: attributes })); } // #endregion return (new in_window.org.pkijs.asn1.SEQUENCE({ value: output_array })); }; //************************************************************************************** in_window.org.pkijs.simpl.PKCS10.prototype.toSchema = function(encodeFlag) { /// If param equal to false then create TBS schema via decoding stored value. In othe case create TBS schema via assembling from TBS parts. // #region Check "encodeFlag" if(typeof encodeFlag === "undefined") encodeFlag = false; // #endregion // #region Decode stored TBS value var tbs_schema; if(encodeFlag === false) { if(this.tbs.length === 0) // No stored TBS part return in_window.org.pkijs.schema.PKCS10(); tbs_schema = in_window.org.pkijs.fromBER(this.tbs).result; } // #endregion // #region Create TBS schema via assembling from TBS parts else tbs_schema = in_window.org.pkijs.simpl.PKCS10.prototype.encodeTBS.call(this); // #endregion // #region Construct and return new ASN.1 schema for this object return (new in_window.org.pkijs.asn1.SEQUENCE({ value: [ tbs_schema, this.signatureAlgorithm.toSchema(), this.signatureValue ] })); // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.PKCS10.prototype.verify = function() { /// !!! Works well in Chrome dev versions only (April 2014th) !!! /// Returns a new Promise object (in case of error), or a result of "crypto.subtle.veryfy" function // #region Global variables var _this = this; var sha_algorithm = ""; var sequence = Promise.resolve(); var subjectPublicKeyInfo = this.subjectPublicKeyInfo; var signature = this.signatureValue; var tbs = this.tbs; // #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 Find a correct hashing algorithm sha_algorithm = in_window.org.pkijs.getHashAlgorithm(this.signatureAlgorithm); if(sha_algorithm === "") return new Promise(function(resolve, reject) { reject("Unsupported signature algorithm: " + _this.signatureAlgorithm.algorithm_id); }); // #endregion // #region Importing public key sequence = sequence.then( function() { // #region Get information about public key algorithm and default parameters for import var algorithmObject = in_window.org.pkijs.getAlgorithmByOID(_this.signatureAlgorithm.algorithm_id); if(("name" in algorithmObject) === false) return new Promise(function(resolve, reject) { reject("Unsupported public key algorithm: " + _this.signatureAlgorithm.algorithm_id); }); var algorithm_name = algorithmObject.name; var algorithm = in_window.org.pkijs.getAlgorithmParameters(algorithm_name, "importkey"); if("hash" in algorithm.algorithm) algorithm.algorithm.hash.name = sha_algorithm; // #endregion var publicKeyInfo_schema = subjectPublicKeyInfo.toSchema(); var publicKeyInfo_buffer = publicKeyInfo_schema.toBER(false); var publicKeyInfo_view = new Uint8Array(publicKeyInfo_buffer); return crypto.importKey("spki", publicKeyInfo_view, algorithm.algorithm, true, algorithm.usages); } ); // #endregion // #region Verify signature sequence = sequence.then( function(publicKey) { // #region Get default algorithm parameters for verification var algorithm = in_window.org.pkijs.getAlgorithmParameters(publicKey.algorithm.name, "verify"); if("hash" in algorithm.algorithm) algorithm.algorithm.hash.name = sha_algorithm; // #endregion // #region Special case for ECDSA signatures var signature_value = signature.value_block.value_hex; if(publicKey.algorithm.name === "ECDSA") { var asn1 = in_window.org.pkijs.fromBER(signature_value); signature_value = in_window.org.pkijs.createECDSASignatureFromCMS(asn1.result); } // #endregion // #region Special case for RSA-PSS if(publicKey.algorithm.name === "RSA-PSS") { var pssParameters; try { pssParameters = new in_window.org.pkijs.simpl.x509.RSASSA_PSS_params({ schema: _this.signatureAlgorithm.algorithm_params }); } catch(ex) { return new Promise(function(resolve, reject) { reject(ex); }); } if("saltLength" in pssParameters) algorithm.algorithm.saltLength = pssParameters.saltLength; else algorithm.algorithm.saltLength = 20; var hash_algo = "SHA-1"; if("hashAlgorithm" in pssParameters) { var hashAlgorithm = in_window.org.pkijs.getAlgorithmByOID(pssParameters.hashAlgorithm.algorithm_id); if(("name" in hashAlgorithm) === false) return new Promise(function(resolve, reject) { reject("Unrecognized hash algorithm: " + pssParameters.hashAlgorithm.algorithm_id); }); hash_algo = hashAlgorithm.name; } algorithm.algorithm.hash.name = hash_algo; } // #endregion return crypto.verify(algorithm.algorithm, publicKey, new Uint8Array(signature_value), new Uint8Array(tbs)); } ); // #endregion return sequence; }; //************************************************************************************** in_window.org.pkijs.simpl.PKCS10.prototype.sign = function(privateKey, hashAlgorithm) { /// Private key for "subjectPublicKeyInfo" structure /// Hashing algorithm. Default SHA-1 // #region Initial variables var _this = this; // #endregion // #region Get a private key from function parameter if(typeof privateKey === "undefined") return new Promise(function(resolve, reject) { reject("Need to provide a private key for signing"); }); // #endregion // #region Get hashing algorithm if(typeof hashAlgorithm === "undefined") hashAlgorithm = "SHA-1"; else { // #region Simple check for supported algorithm var oid = in_window.org.pkijs.getOIDByAlgorithm({ name: hashAlgorithm }); if(oid === "") return new Promise(function(resolve, reject) { reject("Unsupported hash algorithm: " + hashAlgorithm); }); // #endregion } // #endregion // #region Get a "default parameters" for current algorithm var defParams = in_window.org.pkijs.getAlgorithmParameters(privateKey.algorithm.name, "sign"); defParams.algorithm.hash.name = hashAlgorithm; // #endregion // #region Fill internal structures base on "privateKey" and "hashAlgorithm" switch(privateKey.algorithm.name.toUpperCase()) { case "RSASSA-PKCS1-V1_5": case "ECDSA": _this.signatureAlgorithm.algorithm_id = in_window.org.pkijs.getOIDByAlgorithm(defParams.algorithm); break; case "RSA-PSS": { // #region Set "saltLength" as a length (in octets) of hash function result switch(hashAlgorithm.toUpperCase()) { case "SHA-256": defParams.algorithm.saltLength = 32; break; case "SHA-384": defParams.algorithm.saltLength = 48; break; case "SHA-512": defParams.algorithm.saltLength = 64; break; default: } // #endregion // #region Fill "RSASSA_PSS_params" object var paramsObject = {}; if(hashAlgorithm.toUpperCase() !== "SHA-1") { var hashAlgorithmOID = in_window.org.pkijs.getOIDByAlgorithm({ name: hashAlgorithm }); if(hashAlgorithmOID === "") return new Promise(function(resolve, reject) { reject("Unsupported hash algorithm: " + hashAlgorithm); }); paramsObject.hashAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ algorithm_id: hashAlgorithmOID, algorithm_params: new in_window.org.pkijs.asn1.NULL() }); paramsObject.maskGenAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ algorithm_id: "1.2.840.113549.1.1.8", // MGF1 algorithm_params: paramsObject.hashAlgorithm.toSchema() }) } if(defParams.algorithm.saltLength !== 20) paramsObject.saltLength = defParams.algorithm.saltLength; var pssParameters = new in_window.org.pkijs.simpl.x509.RSASSA_PSS_params(paramsObject); // #endregion // #region Automatically set signature algorithm _this.signatureAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ algorithm_id: "1.2.840.113549.1.1.10", algorithm_params: pssParameters.toSchema() }); // #endregion } break; default: return new Promise(function(resolve, reject) { reject("Unsupported signature algorithm: " + privateKey.algorithm.name); }); } // #endregion // #region Create TBS data for signing _this.tbs = in_window.org.pkijs.simpl.PKCS10.prototype.encodeTBS.call(this).toBER(false); // #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 Signing TBS data on provided private key return crypto.sign(defParams.algorithm, privateKey, new Uint8Array(_this.tbs)).then( function(result) { // #region Special case for ECDSA algorithm if(defParams.algorithm.name === "ECDSA") result = in_window.org.pkijs.createCMSECDSASignature(result); // #endregion _this.signatureValue = new in_window.org.pkijs.asn1.BITSTRING({ value_hex: result }); }, function(error) { return new Promise(function(resolve, reject) { reject("Signing error: " + error); }); } ); // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.PKCS10.prototype.toJSON = function() { var _object = { tbs: in_window.org.pkijs.bufferToHexCodes(this.tbs, 0, this.tbs.byteLength), version: this.version, subject: this.subject.toJSON(), subjectPublicKeyInfo: this.subjectPublicKeyInfo.toJSON(), signatureAlgorithm: this.signatureAlgorithm.toJSON(), signatureValue: this.signatureValue.toJSON() }; if("attributes" in this) { _object.attributes = new Array(); for(var i = 0; i < this.attributes.length; i++) _object.attributes.push(this.attributes[i].toJSON()); } return _object; }; //************************************************************************************** // #endregion //************************************************************************************** // #region Simplified structure for PKCS#8 private key bag //************************************************************************************** in_window.org.pkijs.simpl.PKCS8 = function() { // #region Internal properties of the object this.version = 0; this.privateKeyAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); this.privateKey = new in_window.org.pkijs.asn1.OCTETSTRING(); // OPTIONAL this.attributes // Array of "in_window.org.pkijs.simpl.ATTRIBUTE" // #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.PKCS8.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.privateKeyAlgorithm = arguments[0].privateKeyAlgorithm || new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); this.privateKey = arguments[0].privateKey || new in_window.org.pkijs.asn1.OCTETSTRING(); if("attributes" in arguments[0]) this.attributes = arguments[0].attributes; } } // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.PKCS8.prototype.fromSchema = function(schema) { // #region Check the schema is valid var asn1 = in_window.org.pkijs.compareSchema(schema, schema, in_window.org.pkijs.schema.PKCS8({ names: { version: "version", privateKeyAlgorithm: { names: { block_name: "privateKeyAlgorithm" } }, privateKey: "privateKey", attributes: "attributes" } }) ); if(asn1.verified === false) throw new Error("Object's schema was not verified against input data for PKCS8"); // #endregion // #region Get internal properties from parsed schema this.version = asn1.result["version"].value_block.value_dec; this.privateKeyAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ schema: asn1.result["privateKeyAlgorithm"] }); this.privateKey = asn1.result["privateKey"]; if("attributes" in asn1.result) { this.attributes = new Array(); var attrs = asn1.result["attributes"]; for(var i = 0; i < attrs.length; i++) this.attributes.push(new in_window.org.pkijs.simpl.ATTRIBUTE({ schema: attrs[i] })); } // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.PKCS8.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.privateKeyAlgorithm.toSchema()); output_array.push(this.privateKey); if("attributes" in this) { var attrs = new Array(); for(var i = 0; i < this.attributes.length; i++) attrs.push(this.attributes[i].toSchema()); output_array.push(new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ optional: true, id_block: { tag_class: 3, // CONTEXT-SPECIFIC tag_number: 0 // [0] }, value: attrs })); } // #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.PKCS8.prototype.toJSON = function() { var _object = { version: this.version, privateKeyAlgorithm: this.privateKeyAlgorithm.toJSON(), privateKey: this.privateKey.toJSON() }; if("attributes" in this) { _object.attributes = new Array(); for(var i = 0; i < this.attributes.length; i++) _object.attributes.push(this.attributes[i].toJSON()); } return _object; }; //************************************************************************************** // #endregion //************************************************************************************** // #region Simplified structure for working with X.509 certificate chains //************************************************************************************** in_window.org.pkijs.simpl.CERT_CHAIN = function() { // #region Internal properties of the object /// Array of pre-defined trusted (by user) certificates this.trusted_certs = new Array(); /// Array with certificate chain. Could be only one end-user certificate in there! this.certs = new Array(); /// Array of all CRLs for all certificates from certificate chain this.crls = new Array(); // #endregion // #region Initialize internal properties by input values if(arguments[0] instanceof Object) { this.trusted_certs = arguments[0].trusted_certs || new Array(); this.certs = arguments[0].certs || new Array(); this.crls = arguments[0].crls || new Array(); } // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.CERT_CHAIN.prototype.sort = function() { // #region Initial variables /// Array of sorted certificates var sorted_certs = new Array(); /// Initial array of certificates var certs = this.certs.slice(0); // Explicity copy "this.certs" /// Date for checking certificate validity period var check_date = new Date(); var _this = this; // #endregion // #region Initial checks if(certs.length === 0) return new Promise(function(resolve, reject) { reject({ result: false, result_code: 2, result_message: "Certificate's array can not be empty" }); }); // #endregion // #region Find end-user certificate var end_user_index = -1; for(var i = 0; i < certs.length; i++) { var isCA = false; if("extensions" in certs[i]) { var mustBeCA = false; var keyUsagePresent = false; var cRLSign = false; for(var j = 0; j < certs[i].extensions.length; j++) { if((certs[i].extensions[j].critical === true) && (("parsedValue" in certs[i].extensions[j]) === false)) { return new Promise(function(resolve, reject) { reject({ result: false, result_code: 6, result_message: "Unable to parse critical certificate extension: " + certs[i].extensions[j].extnID }); }); } if(certs[i].extensions[j].extnID === "2.5.29.15") // KeyUsage { keyUsagePresent = true; var view = new Uint8Array(certs[i].extensions[j].parsedValue.value_block.value_hex); if((view[0] & 0x04) === 0x04) // Set flag "keyCertSign" mustBeCA = true; if((view[0] & 0x02) === 0x02) // Set flag "cRLSign" cRLSign = true; } if(certs[i].extensions[j].extnID === "2.5.29.19") // BasicConstraints { if("cA" in certs[i].extensions[j].parsedValue) { if(certs[i].extensions[j].parsedValue.cA === true) isCA = true; } } } if((mustBeCA === true) && (isCA === false)) return new Promise(function(resolve, reject) { reject({ result: false, result_code: 3, result_message: "Unable to build certificate chain - using \"keyCertSign\" flag set without BasicConstaints" }); }); if((keyUsagePresent === true) && (isCA === true) && (mustBeCA === false)) return new Promise(function(resolve, reject) { reject({ result: false, result_code: 4, result_message: "Unable to build certificate chain - \"keyCertSign\" flag was not set" }); }); if((isCA === true) && (keyUsagePresent === true) && (cRLSign === false)) return new Promise(function(resolve, reject) { reject({ result: false, result_code: 5, result_message: "Unable to build certificate chain - intermediate certificate must have \"cRLSign\" key usage flag" }); }); } if(isCA === false) { if(sorted_certs.length !== 0) return new Promise(function(resolve, reject) { reject({ result: false, result_code: 7, result_message: "Unable to build certificate chain - more than one possible end-user certificate" }); }); sorted_certs.push(certs[i]); end_user_index = i; } } certs.splice(end_user_index, 1); // #endregion // #region Check that end-user certificate was found if(sorted_certs.length === 0) return new Promise(function(resolve, reject) { reject({ result: false, result_code: 1, result_message: "Can't find end-user certificate" }); }); // #endregion // #region Return if there is only one certificate in certificate's array if(certs.length === 0) { if(sorted_certs[0].issuer.isEqual(sorted_certs[0].subject) === true) return new Promise(function(resolve, reject) { resolve(sorted_certs); }); else { if(this.trusted_certs.length === 0) { return new Promise(function(resolve, reject) { reject({ result: false, result_code: 70, result_message: "Can't find root certificate" }); }); } else { certs = _this.trusted_certs.splice(0); } } } // #endregion /// Current certificate (to find issuer for) var current_certificate = sorted_certs[0]; // #region Auxiliary functions working with Promises function basic(subject_certificate, issuer_certificate) { /// Basic certificate checks /// Certificate for testing (subject) /// Certificate for issuer of subject certificate // #region Initial variables var sequence = Promise.resolve(); // #endregion // #region Check validity period for subject certificate sequence = sequence.then( function() { if((subject_certificate.notBefore.value > check_date) || (subject_certificate.notAfter.value < check_date)) { return new Promise(function(resolve, reject) { reject({ result: false, result_code: 8, result_message: "Certificate validity period is out of checking date" }); }); } } ); // #endregion // #region Give ability to not provide CRLs (all certificates assume to be valid) if(_this.crls.length === 0) return sequence.then( function() { return new Promise(function(resolve, reject) { resolve(); }); } ); // #endregion // #region Find correct CRL for "issuer_certificate" function find_crl(index) { return _this.crls[index].verify({ issuerCertificate: issuer_certificate }).then( function(result) { if(result === true) return new Promise(function(resolve, reject) { resolve(_this.crls[index]); }); else { index++; if(index < _this.crls.length) return find_crl(index); else return new Promise(function(resolve, reject) { reject({ result: false, result_code: 9, result_message: "Unable to find CRL for issuer's certificate" }); }); } }, function(error) { return new Promise(function(resolve, reject) { reject({ result: false, result_code: 10, result_message: "Unable to find CRL for issuer's certificate" }); }); } ); } sequence = sequence.then( function() { return find_crl(0); } ); // #endregion // #region Check that subject certificate is not in the CRL sequence = sequence.then( function(crl) { /// CRL for issuer's certificate if(crl.isCertificateRevoked({ certificate: subject_certificate }) === true) return new Promise(function(resolve, reject) { reject({ result: false, result_code: 11, result_message: "Subject certificate was revoked" }); }); else return new Promise(function(resolve, reject) { resolve(); }); }, function(error) { /// Not for all certificates we have a CRL. So, this "stub" is for handling such situation - assiming we have a valid, non-revoked certificate return new Promise(function(resolve, reject) { resolve(); }); } ); // #endregion return sequence; } function outer() { return inner(current_certificate, 0).then( function(index) { sorted_certs.push(certs[index]); current_certificate = certs[index]; certs.splice(index, 1); if(current_certificate.issuer.isEqual(current_certificate.subject) === true) { // #region Check that the "self-signed" certificate there is in "trusted_certs" array var found = (_this.trusted_certs.length === 0); // If user did not set "trusted_certs" then we have an option to trust any self-signed certificate as root for(var i = 0; i < _this.trusted_certs.length; i++) { if((current_certificate.issuer.isEqual(_this.trusted_certs[i].issuer) === true) && (current_certificate.subject.isEqual(_this.trusted_certs[i].subject) === true) && (current_certificate.serialNumber.isEqual(_this.trusted_certs[i].serialNumber) === true)) { found = true; break; } } if(found === false) return new Promise(function(resolve, reject) { reject({ result: false, result_code: 22, result_message: "Self-signed root certificate not in \"trusted certificates\" array" }); }); // #endregion return (current_certificate.verify()).then( // Verifing last, self-signed certificate function(result) { if(result === true) return basic(current_certificate, current_certificate).then( function() { return new Promise(function(resolve, reject) { resolve(sorted_certs); }); }, function(error) { return new Promise(function(resolve, reject) { reject({ result: false, result_code: 12, result_message: error }); }); } ); else return new Promise(function(resolve, reject) { reject({ result: false, result_code: 13, result_message: "Unable to build certificate chain - signature of root certificate is invalid" }); }); }, function(error) { return new Promise(function(resolve, reject) { reject({ result: false, result_code: 14, result_message: error }); }); } ); } else // In case if self-signed cert for the chain in the "trusted_certs" array { if(certs.length > 0) return outer(); else { if(_this.trusted_certs.length !== 0) { certs = _this.trusted_certs.splice(0); return outer(); } else return new Promise(function(resolve, reject) { reject({ result: false, result_code: 23, result_message: "Root certificate not found" }); }); } } }, function(error) { return new Promise(function(resolve, reject) { reject(error); }); } ); } function inner(current_certificate, index) { if(certs[index].subject.isEqual(current_certificate.issuer) === true) { return current_certificate.verify({ issuerCertificate: certs[index] }).then( function(result) { if(result === true) { return basic(current_certificate, certs[index]).then( function() { return new Promise(function(resolve, reject) { resolve(index); }); }, function(error) { return new Promise(function(resolve, reject) { reject({ result: false, result_code: 16, result_message: error }); }); } ); } else { if(index < (certs.length - 1)) return inner(current_certificate, index + 1); else return new Promise(function(resolve, reject) { reject({ result: false, result_code: 17, result_message: "Unable to build certificate chain - incomplete certificate chain or signature of some certificate is invalid" }); }); } }, function(error) { return new Promise(function(resolve, reject) { reject({ result: false, result_code: 18, result_message: "Unable to build certificate chain - error during certificate signature verification" }); }); } ); } else { if(index < (certs.length - 1)) return inner(current_certificate, index + 1); else return new Promise(function(resolve, reject) { reject({ result: false, result_code: 19, result_message: "Unable to build certificate chain - incomplete certificate chain" }); }); } } // #endregion // #region Find certificates for all issuers return outer(); // #endregion }; //************************************************************************************** in_window.org.pkijs.simpl.CERT_CHAIN.prototype.verify = function() { // #region Initial checks if(this.certs.length === 0) return new Promise(function(resolve, reject) { reject("Empty certificate array"); }); // #endregion // #region Initial variables var sequence = Promise.resolve(); var _this = this; // #endregion // #region Get input variables var initial_policy_set = new Array(); initial_policy_set.push("2.5.29.32.0"); // "anyPolicy" var initial_explicit_policy = false; var initial_policy_mapping_inhibit = false; var initial_inhibit_policy = false; var initial_permitted_subtrees_set = new Array(); // Array of "simpl.x509.GeneralSubtree" var initial_excluded_subtrees_set = new Array(); // Array of "simpl.x509.GeneralSubtree" var initial_required_name_forms = new Array(); // Array of "simpl.x509.GeneralSubtree" var verification_time = new Date(); if(arguments[0] instanceof Object) { if("initial_policy_set" in arguments[0]) initial_policy_set = arguments[0].initial_policy_set; if("initial_explicit_policy" in arguments[0]) initial_explicit_policy = arguments[0].initial_explicit_policy; if("initial_policy_mapping_inhibit" in arguments[0]) initial_policy_mapping_inhibit = arguments[0].initial_policy_mapping_inhibit; if("initial_inhibit_policy" in arguments[0]) initial_inhibit_policy = arguments[0].initial_inhibit_policy; if("initial_permitted_subtrees_set" in arguments[0]) initial_permitted_subtrees_set = arguments[0].initial_permitted_subtrees_set; if("initial_excluded_subtrees_set" in arguments[0]) initial_excluded_subtrees_set = arguments[0].initial_excluded_subtrees_set; if("initial_required_name_forms" in arguments[0]) initial_required_name_forms = arguments[0].initial_required_name_forms; } var explicit_policy_indicator = initial_explicit_policy; var policy_mapping_inhibit_indicator = initial_policy_mapping_inhibit; var inhibit_any_policy_indicator = initial_inhibit_policy; var pending_constraints = new Array(3); pending_constraints[0] = false; // For "explicit_policy_pending" pending_constraints[1] = false; // For "policy_mapping_inhibit_pending" pending_constraints[2] = false; // For "inhibit_any_policy_pending" var explicit_policy_pending = 0; var policy_mapping_inhibit_pending = 0; var inhibit_any_policy_pending = 0; var permitted_subtrees = initial_permitted_subtrees_set; var excluded_subtrees = initial_excluded_subtrees_set; var required_name_forms = initial_required_name_forms; var path_depth = 1; // #endregion // #region Sorting certificates in the chain array sequence = (in_window.org.pkijs.simpl.CERT_CHAIN.prototype.sort.call(this)).then( function(sorted_certs) { _this.certs = sorted_certs; } ); // #endregion // #region Work with policies sequence = sequence.then( function() { // #region Support variables var all_policies = new Array(); // Array of all policies (string values) all_policies.push("2.5.29.32.0"); // Put "anyPolicy" at first place var policies_and_certs = new Array(); // In fact "array of array" where rows are for each specific policy, column for each certificate and value is "true/false" var any_policy_array = new Array(_this.certs.length - 1); // Minus "trusted anchor" for(var ii = 0; ii < (_this.certs.length - 1) ; ii++) any_policy_array[ii] = true; policies_and_certs.push(any_policy_array); var policy_mappings = new Array(_this.certs.length - 1); // Array of "PolicyMappings" for each certificate var cert_policies = new Array(_this.certs.length - 1); // Array of "CertificatePolicies" for each certificate // #endregion for(var i = (_this.certs.length - 2) ; i >= 0 ; i--, path_depth++) { if("extensions" in _this.certs[i]) { for(var j = 0; j < _this.certs[i].extensions.length; j++) { // #region CertificatePolicies if(_this.certs[i].extensions[j].extnID === "2.5.29.32") { cert_policies[i] = _this.certs[i].extensions[j].parsedValue; for(var k = 0; k < _this.certs[i].extensions[j].parsedValue.certificatePolicies.length; k++) { var policy_index = (-1); // #region Try to find extension in "all_policies" array for(var s = 0; s < all_policies.length; s++) { if(_this.certs[i].extensions[j].parsedValue.certificatePolicies[k].policyIdentifier === all_policies[s]) { policy_index = s; break; } } // #endregion if(policy_index === (-1)) { all_policies.push(_this.certs[i].extensions[j].parsedValue.certificatePolicies[k].policyIdentifier); var cert_array = new Array(_this.certs.length - 1); cert_array[i] = true; policies_and_certs.push(cert_array); } else(policies_and_certs[policy_index])[i] = true; } } // #endregion // #region PolicyMappings if(_this.certs[i].extensions[j].extnID === "2.5.29.33") policy_mappings[i] = _this.certs[i].extensions[j].parsedValue; // #endregion // #region PolicyConstraints if(_this.certs[i].extensions[j].extnID === "2.5.29.36") { if(explicit_policy_indicator == false) { // #region requireExplicitPolicy if(_this.certs[i].extensions[j].parsedValue.requireExplicitPolicy === 0) explicit_policy_indicator = true; else { if(pending_constraints[0] === false) { pending_constraints[0] = true; explicit_policy_pending = _this.certs[i].extensions[j].parsedValue.requireExplicitPolicy; } else { explicit_policy_pending = (explicit_policy_pending > _this.certs[i].extensions[j].parsedValue.requireExplicitPolicy) ? _this.certs[i].extensions[j].parsedValue.requireExplicitPolicy : explicit_policy_pending; } } // #endregion // #region inhibitPolicyMapping if(_this.certs[i].extensions[j].parsedValue.inhibitPolicyMapping === 0) policy_mapping_inhibit_indicator = true; else { if(pending_constraints[1] === false) { pending_constraints[1] = true; policy_mapping_inhibit_pending = _this.certs[i].extensions[j].parsedValue.requireExplicitPolicy; } else { policy_mapping_inhibit_pending = (policy_mapping_inhibit_pending > _this.certs[i].extensions[j].parsedValue.requireExplicitPolicy) ? _this.certs[i].extensions[j].parsedValue.requireExplicitPolicy : policy_mapping_inhibit_pending; } } // #endregion } } // #endregion // #region InhibitAnyPolicy if(_this.certs[i].extensions[j].extnID === "2.5.29.54") { if(inhibit_any_policy_indicator === false) { if(_this.certs[i].extensions[j].parsedValue.value_block.value_dec === 0) inhibit_any_policy_indicator = true; else { if(pending_constraints[2] === false) { pending_constraints[2] = true; inhibit_any_policy_pending = _this.certs[i].extensions[j].parsedValue.value_block.value_dec; } else { inhibit_any_policy_pending = (inhibit_any_policy_pending > _this.certs[i].extensions[j].parsedValue.value_block.value_dec) ? _this.certs[i].extensions[j].parsedValue.value_block.value_dec : inhibit_any_policy_pending; } } } } // #endregion } // #region Check "inhibit_any_policy_indicator" if(inhibit_any_policy_indicator === true) delete (policies_and_certs[0])[i]; // Unset value to "undefined" for "anyPolicies" value for current certificate // #endregion // #region Combine information from certificate policies and policy mappings if((typeof cert_policies[i] !== "undefined") && (typeof policy_mappings[i] !== "undefined") && (policy_mapping_inhibit_indicator === false)) { for(var m = 0; m < cert_policies[i].certificatePolicies.length; m++) { var domainPolicy = ""; // #region Find if current policy is in "mappings" array for(var n = 0; n < policy_mappings[i].mappings.length; n++) { if(policy_mappings[i].mappings[n].subjectDomainPolicy === cert_policies[i].certificatePolicies[m].policyIdentifier) { domainPolicy = policy_mappings[i].mappings[n].issuerDomainPolicy; break; } // #region Could be the case for some reasons if(policy_mappings[i].mappings[n].issuerDomainPolicy === cert_policies[i].certificatePolicies[m].policyIdentifier) { domainPolicy = policy_mappings[i].mappings[n].subjectDomainPolicy; break; } // #endregion } if(domainPolicy === "") continue; // #endregion // #region Find the index of "domainPolicy" var domainPolicy_index = (-1); for(var p = 0; p < all_policies.length; p++) { if(all_policies[p] === domainPolicy) { domainPolicy_index = p; break; } } // #endregion // #region Change array value for "domainPolicy" if(domainPolicy_index !== (-1)) (policies_and_certs[domainPolicy_index])[i] = true; // Put "set" in "domainPolicy" cell for specific certificate // #endregion } } // #endregion // #region Process with "pending constraints" if(explicit_policy_indicator === false) { if(pending_constraints[0] === true) { explicit_policy_pending--; if(explicit_policy_pending === 0) { explicit_policy_indicator = true; pending_constraints[0] = false; } } } if(policy_mapping_inhibit_indicator === false) { if(pending_constraints[1] === true) { policy_mapping_inhibit_pending--; if(policy_mapping_inhibit_pending === 0) { policy_mapping_inhibit_indicator = true; pending_constraints[1] = false; } } } if(inhibit_any_policy_indicator === false) { if(pending_constraints[2] === true) { inhibit_any_policy_pending--; if(inhibit_any_policy_pending === 0) { inhibit_any_policy_indicator = true; pending_constraints[2] = false; } } } // #endregion } } // #region Create "set of authorities-constrained policies" var auth_constr_policies = new Array(); for(var i = 0; i < policies_and_certs.length; i++) { var found = true; for(var j = 0; j < (_this.certs.length - 1) ; j++) { if(typeof (policies_and_certs[i])[j] === "undefined") { found = false; break; } } if(found === true) auth_constr_policies.push(all_policies[i]); } // #endregion // #region Create "set of user-constrained policies" var user_constr_policies = new Array(); for(var i = 0; i < auth_constr_policies.length; i++) { for(var j = 0; j < initial_policy_set.length; j++) { if(initial_policy_set[j] === auth_constr_policies[i]) { user_constr_policies.push(initial_policy_set[j]); break; } } } // #endregion // #region Combine output object return { result: (user_constr_policies.length > 0), result_code: 0, result_message: (user_constr_policies.length > 0) ? "" : "Zero \"user_constr_policies\" array, no intersections with \"auth_constr_policies\"", auth_constr_policies: auth_constr_policies, user_constr_policies: user_constr_policies, explicit_policy_indicator: explicit_policy_indicator, policy_mappings: policy_mappings }; // #endregion } ); // #endregion // #region Work with name constraints sequence = sequence.then( function(policy_result) { // #region Auxiliary functions for name constraints checking function compare_dNSName(name, constraint) { /// Compare two dNSName values /// DNS from name /// Constraint for DNS from name /// Boolean result - valid or invalid the "name" against the "constraint" // #region Make a "string preparation" for both name and constrain var name_prepared = in_window.org.pkijs.stringPrep(name); var constraint_prepared = in_window.org.pkijs.stringPrep(constraint); // #endregion // #region Make a "splitted" versions of "constraint" and "name" var name_splitted = name_prepared.split("."); var constraint_splitted = constraint_prepared.split("."); // #endregion // #region Length calculation and additional check var name_len = name_splitted.length; var constr_len = constraint_splitted.length; if((name_len === 0) || (constr_len === 0) || (name_len < constr_len)) return false; // #endregion // #region Check that no part of "name" has zero length for(var i = 0; i < name_len; i++) { if(name_splitted[i].length === 0) return false; } // #endregion // #region Check that no part of "constraint" has zero length for(var i = 0; i < constr_len; i++) { if(constraint_splitted[i].length === 0) { if(i === 0) { if(constr_len === 1) return false; else continue; } return false; } } // #endregion // #region Check that "name" has a tail as "constraint" for(var i = 0; i < constr_len; i++) { if(constraint_splitted[constr_len - 1 - i].length === 0) continue; if(name_splitted[name_len - 1 - i].localeCompare(constraint_splitted[constr_len - 1 - i]) !== 0) return false; } // #endregion return true; } function compare_rfc822Name(name, constraint) { /// Compare two rfc822Name values /// E-mail address from name /// Constraint for e-mail address from name /// Boolean result - valid or invalid the "name" against the "constraint" // #region Make a "string preparation" for both name and constrain var name_prepared = in_window.org.pkijs.stringPrep(name); var constraint_prepared = in_window.org.pkijs.stringPrep(constraint); // #endregion // #region Make a "splitted" versions of "constraint" and "name" var name_splitted = name_prepared.split("@"); var constraint_splitted = constraint_prepared.split("@"); // #endregion // #region Splitted array length checking if((name_splitted.length === 0) || (constraint_splitted.length === 0) || (name_splitted.length < constraint_splitted.length)) return false; // #endregion if(constraint_splitted.length === 1) { var result = compare_dNSName(name_splitted[1], constraint_splitted[0]); if(result) { // #region Make a "splitted" versions of domain name from "constraint" and "name" var ns = name_splitted[1].split("."); var cs = constraint_splitted[0].split("."); // #endregion if(cs[0].length === 0) return true; return ns.length === cs.length; } else return false; } else return (name_prepared.localeCompare(constraint_prepared) === 0); return false; } function compare_uniformResourceIdentifier(name, constraint) { /// Compare two uniformResourceIdentifier values /// uniformResourceIdentifier from name /// Constraint for uniformResourceIdentifier from name /// Boolean result - valid or invalid the "name" against the "constraint" // #region Make a "string preparation" for both name and constrain var name_prepared = in_window.org.pkijs.stringPrep(name); var constraint_prepared = in_window.org.pkijs.stringPrep(constraint); // #endregion // #region Find out a major URI part to compare with var ns = name_prepared.split("/"); var cs = constraint_prepared.split("/"); if(cs.length > 1) // Malformed constraint return false; if(ns.length > 1) // Full URI string { for(var i = 0; i < ns.length; i++) { if((ns[i].length > 0) && (ns[i].charAt(ns[i].length - 1) !== ':')) { var ns_port = ns[i].split(":"); name_prepared = ns_port[0]; break; } } } // #endregion var result = compare_dNSName(name_prepared, constraint_prepared); if(result) { // #region Make a "splitted" versions of "constraint" and "name" var name_splitted = name_prepared.split("."); var constraint_splitted = constraint_prepared.split("."); // #endregion if(constraint_splitted[0].length === 0) return true; return name_splitted.length === constraint_splitted.length; } else return false; return false; } function compare_iPAddress(name, constraint) { /// Compare two iPAddress values /// iPAddress from name /// Constraint for iPAddress from name /// Boolean result - valid or invalid the "name" against the "constraint" // #region Common variables var name_view = new Uint8Array(name.value_block.value_hex); var constraint_view = new Uint8Array(constraint.value_block.value_hex); // #endregion // #region Work with IPv4 addresses if((name_view.length === 4) && (constraint_view.length === 8)) { for(var i = 0; i < 4; i++) { if((name_view[i] ^ constraint_view[i]) & constraint_view[i + 4]) return false; } return true; } // #endregion // #region Work with IPv6 addresses if((name_view.length === 16) && (constraint_view.length === 32)) { for(var i = 0; i < 16; i++) { if((name_view[i] ^ constraint_view[i]) & constraint_view[i + 16]) return false; } return true; } // #endregion return false; } function compare_directoryName(name, constraint) { /// Compare two directoryName values /// directoryName from name /// Constraint for directoryName from name /// Boolean flag - should be comparision interrupted after first match or we need to match all "constraints" parts /// Boolean result - valid or invalid the "name" against the "constraint" // #region Initial check if((name.types_and_values.length === 0) || (constraint.types_and_values.length === 0)) return true; if(name.types_and_values.length < constraint.types_and_values.length) return false; // #endregion // #region Initial variables var result = true; var name_start = 0; // #endregion for(var i = 0; i < constraint.types_and_values.length; i++) { var local_result = false; for(var j = name_start; j < name.types_and_values.length; j++) { local_result = name.types_and_values[j].isEqual(constraint.types_and_values[i]); if(name.types_and_values[j].type === constraint.types_and_values[i].type) result = result && local_result; if(local_result === true) { if((name_start === 0) || (name_start === j)) { name_start = j + 1; break; } else // Structure of "name" must be the same with "constraint" return false; } } if(local_result === false) return false; } return (name_start === 0) ? false : result; } // #endregion // #region Check a result from "policy checking" part if(policy_result.result === false) return policy_result; // #endregion // #region Check all certificates, excluding "trust anchor" path_depth = 1; for(var i = (_this.certs.length - 2) ; i >= 0 ; i--, path_depth++) { // #region Support variables var subject_alt_names = new Array(); var cert_permitted_subtrees = new Array(); var cert_excluded_subtrees = new Array(); // #endregion if("extensions" in _this.certs[i]) { for(var j = 0; j < _this.certs[i].extensions.length; j++) { // #region NameConstraints if(_this.certs[i].extensions[j].extnID === "2.5.29.30") { if("permittedSubtrees" in _this.certs[i].extensions[j].parsedValue) cert_permitted_subtrees = cert_permitted_subtrees.concat(_this.certs[i].extensions[j].parsedValue.permittedSubtrees); if("excludedSubtrees" in _this.certs[i].extensions[j].parsedValue) cert_excluded_subtrees = cert_excluded_subtrees.concat(_this.certs[i].extensions[j].parsedValue.excludedSubtrees); } // #endregion // #region SubjectAltName if(_this.certs[i].extensions[j].extnID === "2.5.29.17") subject_alt_names = subject_alt_names.concat(_this.certs[i].extensions[j].parsedValue.altNames); // #endregion } } // #region Checking for "required name forms" var form_found = (required_name_forms.length <= 0); for(var j = 0; j < required_name_forms.length; j++) { switch(required_name_forms[j].base.NameType) { case 4: // directoryName { if(required_name_forms[j].base.Name.types_and_values.length !== _this.certs[i].subject.types_and_values.length) continue; form_found = true; for(var k = 0; k < _this.certs[i].subject.types_and_values.length; k++) { if(_this.certs[i].subject.types_and_values[k].type !== required_name_forms[j].base.Name.types_and_values[k].type) { form_found = false; break; } } if(form_found === true) break; } break; default: // ??? Probably here we should reject the certificate ??? } } if(form_found === false) { policy_result.result = false; policy_result.result_code = 21; policy_result.result_message = "No neccessary name form found"; return new Promise(function(resolve, reject) { reject(policy_result); }); } // #endregion // #region Checking for "permited sub-trees" // #region Make groups for all types of constraints var constr_groups = new Array(); // Array of array for groupped constraints constr_groups[0] = new Array(); // rfc822Name constr_groups[1] = new Array(); // dNSName constr_groups[2] = new Array(); // directoryName constr_groups[3] = new Array(); // uniformResourceIdentifier constr_groups[4] = new Array(); // iPAddress for(var j = 0; j < permitted_subtrees.length; j++) { switch(permitted_subtrees[j].base.NameType) { // #region rfc822Name case 1: constr_groups[0].push(permitted_subtrees[j]); break; // #endregion // #region dNSName case 2: constr_groups[1].push(permitted_subtrees[j]); break; // #endregion // #region directoryName case 4: constr_groups[2].push(permitted_subtrees[j]); break; // #endregion // #region uniformResourceIdentifier case 6: constr_groups[3].push(permitted_subtrees[j]); break; // #endregion // #region iPAddress case 7: constr_groups[4].push(permitted_subtrees[j]); break; // #endregion // #region default default: // #endregion } } // #endregion // #region Check name constraints groupped by type, one-by-one for(var p = 0; p < 5; p++) { var group_permitted = false; var valueExists = false; var group = constr_groups[p]; for(var j = 0; j < group.length; j++) { switch(p) { // #region rfc822Name case 0: if(subject_alt_names.length > 0) { for(var k = 0; k < subject_alt_names.length; k++) { if(subject_alt_names[k].NameType === 1) // rfc822Name { valueExists = true; group_permitted = group_permitted || compare_rfc822Name(subject_alt_names[k].Name, group[j].base.Name); } } } else // Try to find out "emailAddress" inside "subject" { for(var k = 0; k < _this.certs[i].subject.types_and_values.length; k++) { if((_this.certs[i].subject.types_and_values[k].type === "1.2.840.113549.1.9.1") || // PKCS#9 e-mail address (_this.certs[i].subject.types_and_values[k].type === "0.9.2342.19200300.100.1.3")) // RFC1274 "rfc822Mailbox" e-mail address { valueExists = true; group_permitted = group_permitted || compare_rfc822Name(_this.certs[i].subject.types_and_values[k].value.value_block.value, group[j].base.Name); } } } break; // #endregion // #region dNSName case 1: if(subject_alt_names.length > 0) { for(var k = 0; k < subject_alt_names.length; k++) { if(subject_alt_names[k].NameType === 2) // dNSName { valueExists = true; group_permitted = group_permitted || compare_dNSName(subject_alt_names[k].Name, group[j].base.Name); } } } break; // #endregion // #region directoryName case 2: valueExists = true; group_permitted = compare_directoryName(_this.certs[i].subject, group[j].base.Name); break; // #endregion // #region uniformResourceIdentifier case 3: if(subject_alt_names.length > 0) { for(var k = 0; k < subject_alt_names.length; k++) { if(subject_alt_names[k].NameType === 6) // uniformResourceIdentifier { valueExists = true; group_permitted = group_permitted || compare_uniformResourceIdentifier(subject_alt_names[k].Name, group[j].base.Name); } } } break; // #endregion // #region iPAddress case 4: if(subject_alt_names.length > 0) { for(var k = 0; k < subject_alt_names.length; k++) { if(subject_alt_names[k].NameType === 7) // iPAddress { valueExists = true; group_permitted = group_permitted || compare_iPAddress(subject_alt_names[k].Name, group[j].base.Name); } } } break; // #endregion // #region default default: // #endregion } if(group_permitted) break; } if((group_permitted === false) && (group.length > 0) && valueExists) { policy_result.result = false; policy_result.result_code = 41; policy_result.result_message = "Failed to meet \"permitted sub-trees\" name constraint"; return new Promise(function(resolve, reject) { reject(policy_result); }); } } // #endregion // #endregion // #region Checking for "excluded sub-trees" var excluded = false; for(var j = 0; j < excluded_subtrees.length; j++) { switch(excluded_subtrees[j].base.NameType) { // #region rfc822Name case 1: if(subject_alt_names.length >= 0) { for(var k = 0; k < subject_alt_names.length; k++) { if(subject_alt_names[k].NameType === 1) // rfc822Name excluded = excluded || compare_rfc822Name(subject_alt_names[k].Name, excluded_subtrees[j].base.Name); } } else // Try to find out "emailAddress" inside "subject" { for(var k = 0; k < _this.subject.types_and_values.length; k++) { if((_this.subject.types_and_values[k].type === "1.2.840.113549.1.9.1") || // PKCS#9 e-mail address (_this.subject.types_and_values[k].type === "0.9.2342.19200300.100.1.3")) // RFC1274 "rfc822Mailbox" e-mail address { excluded = excluded || compare_rfc822Name(_this.subject.types_and_values[k].value.value_block.value, excluded_subtrees[j].base.Name); } } } break; // #endregion // #region dNSName case 2: if(subject_alt_names.length > 0) { for(var k = 0; k < subject_alt_names.length; k++) { if(subject_alt_names[k].NameType === 2) // dNSName excluded = excluded || compare_dNSName(subject_alt_names[k].Name, excluded_subtrees[j].base.Name); } } break; // #endregion // #region directoryName case 4: excluded = excluded || compare_directoryName(_this.certs[i].subject, excluded_subtrees[j].base.Name); break; // #endregion // #region uniformResourceIdentifier case 6: if(subject_alt_names.length > 0) { for(var k = 0; k < subject_alt_names.length; k++) { if(subject_alt_names[k].NameType === 6) // uniformResourceIdentifier excluded = excluded || compare_uniformResourceIdentifier(subject_alt_names[k].Name, excluded_subtrees[j].base.Name); } } break; // #endregion // #region iPAddress case 7: if(subject_alt_names.length > 0) { for(var k = 0; k < subject_alt_names.length; k++) { if(subject_alt_names[k].NameType === 7) // iPAddress excluded = excluded || compare_iPAddress(subject_alt_names[k].Name, excluded_subtrees[j].base.Name); } } break; // #endregion // #region default default: // No action, but probably here we need to create a warning for "malformed constraint" // #endregion } if(excluded) break; } if(excluded === true) { policy_result.result = false; policy_result.result_code = 42; policy_result.result_message = "Failed to meet \"excluded sub-trees\" name constraint"; return new Promise(function(resolve, reject) { reject(policy_result); }); } // #endregion // #region Append "cert_..._subtrees" to "..._subtrees" permitted_subtrees = permitted_subtrees.concat(cert_permitted_subtrees); excluded_subtrees = excluded_subtrees.concat(cert_excluded_subtrees); // #endregion } // #endregion return policy_result; } ); // #endregion return sequence; }; //************************************************************************************** // #endregion //************************************************************************************** } )(typeof exports !== "undefined" ? exports : window);