UNPKG

pkijs

Version:

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

1,126 lines (1,023 loc) 132 kB
/* * Copyright (c) 2014, GMO GlobalSign * All rights reserved. * * Author 2014, Yury Strozhevsky <www.strozhevsky.com>. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * 3. Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. * */ ( function(in_window) { //************************************************************************************** // #region Declaration of global variables //************************************************************************************** // #region "org" namespace if(typeof in_window.org === "undefined") in_window.org = {}; else { if(typeof in_window.org !== "object") throw new Error("Name org already exists and it's not an object"); } // #endregion // #region "org.pkijs" namespace if(typeof in_window.org.pkijs === "undefined") in_window.org.pkijs = {}; else { if(typeof in_window.org.pkijs !== "object") throw new Error("Name org.pkijs already exists and it's not an object" + " but " + (typeof in_window.org.pkijs)); } // #endregion // #region "org.pkijs.simpl" namespace if(typeof in_window.org.pkijs.simpl === "undefined") in_window.org.pkijs.simpl = {}; else { if(typeof in_window.org.pkijs.simpl !== "object") throw new Error("Name org.pkijs.simpl already exists and it's not an object" + " but " + (typeof in_window.org.pkijs.simpl)); } // #endregion // #region "org.pkijs.simpl.cms" namespace if(typeof in_window.org.pkijs.simpl.cms === "undefined") in_window.org.pkijs.simpl.cms = {}; else { if(typeof in_window.org.pkijs.simpl.cms !== "object") throw new Error("Name org.pkijs.simpl.cms already exists and it's not an object" + " but " + (typeof in_window.org.pkijs.simpl.cms)); } // #endregion // #region "local" namespace var local = {}; // #endregion //************************************************************************************** // #endregion //************************************************************************************** // #region Simplified structure for "CMS_CONTENT_INFO" type //************************************************************************************** in_window.org.pkijs.simpl.CMS_CONTENT_INFO = function() { // #region Internal properties of the object this.contentType = ""; this.content = new in_window.org.pkijs.asn1.ANY(); // Just to make a stub // #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.CMS_CONTENT_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.contentType = arguments[0].contentType || ""; this.content = arguments[0].content || new in_window.org.pkijs.asn1.ANY(); // Just to make a stub } } // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.CMS_CONTENT_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.CMS_CONTENT_INFO() ); if(asn1.verified === false) throw new Error("Object's schema was not verified against input data for CMS_CONTENT_INFO"); // #endregion // #region Get internal properties from parsed schema this.contentType = asn1.result["contentType"].value_block.toString(); this.content = asn1.result["content"]; // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.CMS_CONTENT_INFO.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.contentType }), new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ id_block: { tag_class: 3, // CONTEXT-SPECIFIC tag_number: 0 // [0] }, value: [this.content] // EXPLICIT ANY value }) ] })); // #endregion } //************************************************************************************** // #endregion //************************************************************************************** // #region Simplified structure for "OtherCertificateFormat" type //************************************************************************************** in_window.org.pkijs.simpl.cms.OtherCertificateFormat = function() { // #region Internal properties of the object this.otherCertFormat = ""; this.otherCert = new in_window.org.pkijs.asn1.ANY(); // Just to make a stub // #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.cms.OtherCertificateFormat.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.otherCertFormat = arguments[0].contentType || ""; this.otherCert = arguments[0].content || new in_window.org.pkijs.asn1.ANY(); // Just to make a stub } } // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.cms.OtherCertificateFormat.prototype.fromSchema = function(schema) { // #region Check the schema is valid var asn1 = in_window.org.pkijs.compareSchema(schema, schema, in_window.org.pkijs.schema.cms.OtherCertificateFormat() ); if(asn1.verified === false) throw new Error("Object's schema was not verified against input data for OtherCertificateFormat"); // #endregion // #region Get internal properties from parsed schema this.otherCertFormat = asn1.result["otherCertFormat"].value_block.toString(); this.otherCert = asn1.result["otherCert"]; // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.cms.OtherCertificateFormat.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.otherCertFormat }), this.otherCert ] })); // #endregion } //************************************************************************************** // #endregion //************************************************************************************** // #region Simplified structure for "OtherRevocationInfoFormat" type //************************************************************************************** in_window.org.pkijs.simpl.cms.OtherRevocationInfoFormat = function() { // #region Internal properties of the object this.otherRevInfoFormat = ""; this.otherRevInfo = new in_window.org.pkijs.asn1.ANY(); // Just to make a stub // #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.cms.OtherRevocationInfoFormat.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.otherRevInfoFormat = arguments[0].contentType || ""; this.otherRevInfo = arguments[0].content || new in_window.org.pkijs.asn1.ANY(); // Just to make a stub } } // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.cms.OtherRevocationInfoFormat.prototype.fromSchema = function(schema) { // #region Check the schema is valid var asn1 = in_window.org.pkijs.compareSchema(schema, schema, in_window.org.pkijs.schema.cms.OtherRevocationInfoFormat() ); if(asn1.verified === false) throw new Error("Object's schema was not verified against input data for OtherRevocationInfoFormat"); // #endregion // #region Get internal properties from parsed schema this.otherRevInfoFormat = asn1.result["otherRevInfoFormat"].value_block.toString(); this.otherRevInfo = asn1.result["otherRevInfo"]; // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.cms.OtherRevocationInfoFormat.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.otherRevInfoFormat }), this.otherRevInfo ] })); // #endregion } //************************************************************************************** // #endregion //************************************************************************************** // #region Simplified structure for "CMS_CERTIFICATE_SET" type //************************************************************************************** in_window.org.pkijs.simpl.CMS_CERTIFICATE_SET = function() { // #region Internal properties of the object this.certificates = new Array(); // Array of "CertificateChoices" // #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.CMS_CERTIFICATE_SET.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.certificates = arguments[0].certificates || new Array(); // Array of "CertificateChoices" } } // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.CMS_CERTIFICATE_SET.prototype.fromSchema = function(schema) { // #region Check the schema is valid var asn1 = in_window.org.pkijs.compareSchema(schema, schema, in_window.org.pkijs.schema.CMS_CERTIFICATE_SET() ); if(asn1.verified === false) throw new Error("Object's schema was not verified against input data for CMS_CERTIFICATE_SET"); // #endregion // #region Get internal properties from parsed schema var certificates_array = asn1.result["certificates"]; for(var i = 0; i < certificates_array; i++) { if(certificates_array.id_block.tag_class === 1) this.certificates.push(new in_window.org.pkijs.simpl.CERT({ schema: certificates_array[i] })); else this.certificates.push(certificates_array[i]); } // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.CMS_CERTIFICATE_SET.prototype.toSchema = function() { // #region Create array for output set var output_array = new Array(); for(var i = 0; i < this.certificates; i++) { if(this.certificates[i] instanceof in_window.org.pkijs.simpl.CERT) output_array.push(this.certificates[i].toSchema()); else output_array.push(this.certificates[i]); } // #endregion // #region Construct and return new ASN.1 schema for this object return (new in_window.org.pkijs.asn1.SET({ value: output_array })); // #endregion } //************************************************************************************** // #endregion //************************************************************************************** // #region Simplified structure for "CSM_REVOCATION_INFO_CHOICES" type //************************************************************************************** in_window.org.pkijs.simpl.CSM_REVOCATION_INFO_CHOICES = function() { // #region Internal properties of the object this.crls = new Array(); // Array of "RevocationInfoChoices" // #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.CSM_REVOCATION_INFO_CHOICES.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.crls = arguments[0].crls || new Array(); // Array of "RevocationInfoChoices" } } // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.CSM_REVOCATION_INFO_CHOICES.prototype.fromSchema = function(schema) { // #region Check the schema is valid var asn1 = in_window.org.pkijs.compareSchema(schema, schema, in_window.org.pkijs.schema.CSM_REVOCATION_INFO_CHOICES() ); if(asn1.verified === false) throw new Error("Object's schema was not verified against input data for CSM_REVOCATION_INFO_CHOICES"); // #endregion // #region Get internal properties from parsed schema var crls_array = asn1.result["crls"]; for(var i = 0; i < crls_array; i++) { if(crls_array.id_block.tag_class === 1) this.crls.push(new in_window.org.pkijs.simpl.CRL({ schema: crls_array[i] })); else this.crls.push(crls_array[i]); } // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.CSM_REVOCATION_INFO_CHOICES.prototype.toSchema = function() { // #region Create array for output set var output_array = new Array(); for(var i = 0; i < this.crls; i++) { if(this.crls[i] instanceof in_window.org.pkijs.simpl.CRL) output_array.push(this.crls[i].toSchema()); else output_array.push(this.crls[i]); } // #endregion // #region Construct and return new ASN.1 schema for this object return (new in_window.org.pkijs.asn1.SET({ value: output_array })); // #endregion } //************************************************************************************** // #endregion //************************************************************************************** // #region Simplified structure for "IssuerAndSerialNumber" type //************************************************************************************** in_window.org.pkijs.simpl.cms.IssuerAndSerialNumber = function() { // #region Internal properties of the object this.issuer = new in_window.org.pkijs.simpl.RDN(); this.serialNumber = new in_window.org.pkijs.asn1.INTEGER(); // Might be a very long 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.cms.IssuerAndSerialNumber.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.issuer = arguments[0].issuer || new in_window.org.pkijs.simpl.RDN(); this.serialNumber = arguments[0].serialNumber || new in_window.org.pkijs.asn1.INTEGER(); // Might be a very long integer value } } // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.cms.IssuerAndSerialNumber.prototype.fromSchema = function(schema) { // #region Check the schema is valid var asn1 = in_window.org.pkijs.compareSchema(schema, schema, in_window.org.pkijs.schema.cms.IssuerAndSerialNumber({ names: { issuer: { names: { block_name: "issuer" } }, serialNumber: "serialNumber" } }) ); if(asn1.verified === false) throw new Error("Object's schema was not verified against input data for IssuerAndSerialNumber"); // #endregion // #region Get internal properties from parsed schema this.issuer = new in_window.org.pkijs.simpl.RDN({ schema: asn1.result["issuer"] }); this.serialNumber = asn1.result["serialNumber"]; // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.cms.IssuerAndSerialNumber.prototype.toSchema = function() { // #region Construct and return new ASN.1 schema for this object return (new in_window.org.pkijs.asn1.SEQUENCE({ value: [ this.issuer.toSchema(), this.serialNumber ] })); // #endregion } //************************************************************************************** // #endregion //************************************************************************************** // #region Simplified structure for "Attribute" type //************************************************************************************** in_window.org.pkijs.simpl.cms.Attribute = function() { // #region Internal properties of the object this.attrType = ""; this.attrValues = new Array(); // Array of any attribute values // #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.cms.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.attrType = arguments[0].attrType || ""; this.attrValues = arguments[0].attrValues || new Array(); // Array of any attribute values } } // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.cms.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.cms.Attribute({ names: { attrType: "attrType", attrValues: "attrValues" } }) ); 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.attrType = asn1.result["attrType"].value_block.toString(); this.attrValues = asn1.result["attrValues"]; // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.cms.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.attrType }), new in_window.org.pkijs.asn1.SET({ value: this.attrValues }) ] })); // #endregion } //************************************************************************************** // #endregion //************************************************************************************** // #region Simplified structure for "SignedUnsignedAttributes" type //************************************************************************************** in_window.org.pkijs.simpl.cms.SignedUnsignedAttributes = function() { // #region Internal properties of the object this.type = 0; // "SignedAttributes" = 0, "UnsignedAttributes" = 1 this.attributes = new Array(); // Array of Attribute objects this.encoded_value = new ArrayBuffer(0); // Need to have it in order to successfully process with signature verification // #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.cms.SignedUnsignedAttributes.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; // "SignedAttributes" = 0, "UnsignedAttributes" = 1 this.attributes = arguments[0].attributes || new Array(); // Array of Attribute objects } } // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.cms.SignedUnsignedAttributes.prototype.fromSchema = function(schema) { // #region Check the schema is valid var asn1 = in_window.org.pkijs.compareSchema(schema, schema, in_window.org.pkijs.schema.cms.SignedUnsignedAttributes({ names: { attributes: "attributes" } }, this.type) ); if(asn1.verified === false) throw new Error("Object's schema was not verified against input data for SignedUnsignedAttributes"); // #endregion // #region Get internal properties from parsed schema this.type = asn1.result.id_block.tag_number; this.encoded_value = asn1.result.value_before_decode; // #region Change type from "[0]" to "SET" accordingly to standard var encoded_view = new Uint8Array(this.encoded_value); encoded_view[0] = 0x31; // #endregion if(("attributes" in asn1.result) === false) { if(this.type === 0) throw new Error("Wrong structure of SignedUnsignedAttributes"); else return; // Not so important in case of "UnsignedAttributes" } var attributes_array = asn1.result["attributes"]; for(var i = 0; i < attributes_array.length; i++) this.attributes.push(new in_window.org.pkijs.simpl.cms.Attribute({ schema: attributes_array[i] })); // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.cms.SignedUnsignedAttributes.prototype.toSchema = function() { // #region Create array of attributes var attributes_array = new Array(); for(var i = 0; i < this.attributes.length; i++) attributes_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.ASN1_CONSTRUCTED({ optional: true, id_block: { tag_class: 3, // CONTEXT-SPECIFIC tag_number: this.type, // "SignedAttributes" = 0, "UnsignedAttributes" = 1 }, value: attributes_array })); // #endregion } //************************************************************************************** // #endregion //************************************************************************************** // #region Simplified structure for "CMS_SIGNER_INFO" type //************************************************************************************** in_window.org.pkijs.simpl.CMS_SIGNER_INFO = function() { // #region Internal properties of the object this.version = 0; this.sid = new in_window.org.pkijs.asn1.ANY(); // Just for making stub this.digestAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); // OPTIONAL this.signedAttrs = new in_window.org.pkijs.simpl.cms.SignedUnsignedAttributes(); this.signatureAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); this.signature = new in_window.org.pkijs.asn1.OCTETSTRING(); // OPTIONAL this.unsignedAttrs = new in_window.org.pkijs.simpl.cms.SignedUnsignedAttributes(); // #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.CMS_SIGNER_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.version = arguments[0].version || 0; this.sid = arguments[0].sid || new in_window.org.pkijs.asn1.ANY(); // Just for making stub this.digestAlgorithm = arguments[0].digestAlgorithm || new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); if("signedAttrs" in arguments[0]) this.signedAttrs = arguments[0].signedAttrs; this.signatureAlgorithm = arguments[0].signatureAlgorithm || new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); this.signature = arguments[0].signature || new in_window.org.pkijs.asn1.OCTETSTRING(); if("unsignedAttrs" in arguments[0]) this.unsignedAttrs = arguments[0].unsignedAttrs; } } // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.CMS_SIGNER_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.CMS_SIGNER_INFO() ); if(asn1.verified === false) throw new Error("Object's schema was not verified against input data for CMS_SIGNER_INFO"); // #endregion // #region Get internal properties from parsed schema this.version = asn1.result["SignerInfo.version"].value_block.value_dec; var current_sid = asn1.result["SignerInfo.sid"]; if(current_sid.id_block.tag_class === 1) this.sid = new in_window.org.pkijs.simpl.cms.IssuerAndSerialNumber({ schema: current_sid }); else this.sid = current_sid; this.digestAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ schema: asn1.result["SignerInfo.digestAlgorithm"] }); if("SignerInfo.signedAttrs" in asn1.result) this.signedAttrs = new in_window.org.pkijs.simpl.cms.SignedUnsignedAttributes({ schema: asn1.result["SignerInfo.signedAttrs"] }); this.signatureAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ schema: asn1.result["SignerInfo.signatureAlgorithm"] }); this.signature = asn1.result["SignerInfo.signature"]; if("SignerInfo.unsignedAttrs" in asn1.result) { this.unsignedAttrs = new in_window.org.pkijs.simpl.cms.SignedUnsignedAttributes(); this.unsignedAttrs.type = 1; // Unsigned attributes this.unsignedAttrs.fromSchema(asn1.result["SignerInfo.unsignedAttrs"]); } // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.CMS_SIGNER_INFO.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 })); if(this.sid instanceof in_window.org.pkijs.simpl.cms.IssuerAndSerialNumber) output_array.push(this.sid.toSchema()); else output_array.push(this.sid); output_array.push(this.digestAlgorithm.toSchema()); if("signedAttrs" in this) output_array.push(this.signedAttrs.toSchema()); output_array.push(this.signatureAlgorithm.toSchema()); output_array.push(this.signature); if("unsignedAttrs" in this) output_array.push(this.unsignedAttrs.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 } //************************************************************************************** // #endregion //************************************************************************************** // #region Simplified structure for "EncapsulatedContentInfo" type //************************************************************************************** in_window.org.pkijs.simpl.cms.EncapsulatedContentInfo = function() { // #region Internal properties of the object this.eContentType = ""; // OPTIONAL this.eContent = new in_window.org.pkijs.asn1.OCTETSTRING(); // #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.cms.EncapsulatedContentInfo.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.eContentType = arguments[0].eContentType || ""; if("eContent" in arguments[0]) { this.eContent = arguments[0].eContent; if((this.eContent.id_block.tag_class === 1) && (this.eContent.id_block.tag_number === 4)) { // #region Divide OCTETSTRING value down to small pieces if(this.eContent.id_block.is_constructed === false) { var constr_string = new in_window.org.pkijs.asn1.OCTETSTRING({ id_block: { is_constructed: true }, is_constructed: true }); var offset = 0; var length = this.eContent.value_block.value_hex.byteLength; while(length > 0) { var piece_view = new Uint8Array(this.eContent.value_block.value_hex, offset, ((offset + 65536) > this.eContent.value_block.value_hex.byteLength) ? (this.eContent.value_block.value_hex.byteLength - offset) : 65536); var _array = new ArrayBuffer(piece_view.length); var _view = new Uint8Array(_array); for(var i = 0; i < _view.length; i++) _view[i] = piece_view[i]; constr_string.value_block.value.push(new in_window.org.pkijs.asn1.OCTETSTRING({ value_hex: _array })); length -= piece_view.length; offset += piece_view.length; } this.eContent = constr_string; } // #endregion } } } } // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.cms.EncapsulatedContentInfo.prototype.fromSchema = function(schema) { // #region Check the schema is valid var asn1 = in_window.org.pkijs.compareSchema(schema, schema, in_window.org.pkijs.schema.cms.EncapsulatedContentInfo({ names: { eContentType: "eContentType", eContent: "eContent" } }) ); if(asn1.verified === false) throw new Error("Object's schema was not verified against input data for EncapsulatedContentInfo"); // #endregion // #region Get internal properties from parsed schema this.eContentType = asn1.result["eContentType"].value_block.toString(); if("eContent" in asn1.result) this.eContent = asn1.result["eContent"]; // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.cms.EncapsulatedContentInfo.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.eContentType })); if("eContent" 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: [this.eContent] })); // #endregion // #region Construct and return new ASN.1 schema for this object return (new in_window.org.pkijs.asn1.SEQUENCE({ value: output_array })); // #endregion } //************************************************************************************** // #endregion //************************************************************************************** // #region Simplified structure for "CMS_SIGNED_DATA" type //************************************************************************************** in_window.org.pkijs.simpl.CMS_SIGNED_DATA = function() { // #region Internal properties of the object this.version = 0; this.digestAlgorithms = new Array(); // Array of AlgorithmIdentifier this.encapContentInfo = new in_window.org.pkijs.simpl.cms.EncapsulatedContentInfo(); //this.certificates - OPTIONAL //this.crls - OPTIONAL this.signerInfos = new Array(); // Array of CMS_SIGNER_INFO // #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.CMS_SIGNED_DATA.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.digestAlgorithms = arguments[0].digestAlgorithms || new Array(); // Array of AlgorithmIdentifier this.encapContentInfo = arguments[0].encapContentInfo || new in_window.org.pkijs.simpl.cms.EncapsulatedContentInfo(); if("certificates" in arguments[0]) this.certificates = arguments[0].certificates; if("crls" in arguments[0]) this.crls = arguments[0].crls; this.signerInfos = arguments[0].signerInfos || new Array(); // Array of CMS_SIGNER_INFO } } // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.CMS_SIGNED_DATA.prototype.fromSchema = function(schema) { // #region Check the schema is valid var asn1 = in_window.org.pkijs.compareSchema(schema, schema, in_window.org.pkijs.schema.CMS_SIGNED_DATA() ); if(asn1.verified === false) throw new Error("Object's schema was not verified against input data for CMS_SIGNED_DATA"); // #endregion // #region Get internal properties from parsed schema this.version = asn1.result["SignedData.version"].value_block.value_dec; var algorithms_array = asn1.result["SignedData.digestAlgorithms"]; for(var i = 0; i < algorithms_array.length; i++) this.digestAlgorithms.push(new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ schema: algorithms_array[i] })); this.encapContentInfo = new in_window.org.pkijs.simpl.cms.EncapsulatedContentInfo({ schema: asn1.result["SignedData.encapContentInfo"] }); if("SignedData.certificates" in asn1.result) { this.certificates = new Array(); var current_certificates = asn1.result["SignedData.certificates"]; for(var k = 0; k < current_certificates.length; k++) { if(current_certificates[k].id_block.tag_class === 1) this.certificates.push(new in_window.org.pkijs.simpl.CERT({ schema: current_certificates[k] })); else this.certificates.push(new in_window.org.pkijs.simpl.cms.OtherCertificateFormat({ schema: current_certificates[k] })); } } if("SignedData.crls" in asn1.result) { this.crls = new Array(); var current_crls = asn1.result["SignedData.crls"]; for(var l = 0; l < current_crls.length; l++) { if(current_crls[l].id_block.tag_class === 1) this.crls.push(new in_window.org.pkijs.simpl.CRL({ schema: current_crls[l] })); else this.crls.push(new in_window.org.pkijs.simpl.cms.OtherRevocationInfoFormat({ schema: current_crls[l] })); } } var signer_infos = asn1.result["SignedData.signerInfos"]; for(var j = 0; j < signer_infos.length; j++) this.signerInfos.push(new in_window.org.pkijs.simpl.CMS_SIGNER_INFO({ schema: signer_infos[j] })); // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.CMS_SIGNED_DATA.prototype.toSchema = function(encodeFlag) { /// <param name="encodeFlag" type="Boolean">If param equal to false then create TBS schema via decoding stored value. In othe case create TBS schema via assembling from TBS parts.</param> if(typeof encodeFlag === "undefined") encodeFlag = false; // #region Create array for output sequence var output_array = new Array(); output_array.push(new in_window.org.pkijs.asn1.INTEGER({ value: this.version })); // #region Create array of digest algorithms var digest_algorithms = new Array(); for(var i = 0; i < this.digestAlgorithms.length; i++) digest_algorithms.push(this.digestAlgorithms[i].toSchema(encodeFlag)); output_array.push(new in_window.org.pkijs.asn1.SET({ value: digest_algorithms })); // #endregion output_array.push(this.encapContentInfo.toSchema()); if("certificates" in this) { var current_certificates = new Array(); for(var j = 0; j < this.certificates.length; j++) current_certificates.push(this.certificates[j].toSchema(encodeFlag)); 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: current_certificates })); } if("crls" in this) { var current_crls = new Array(); for(var k = 0; k < this.crls.length; k++) current_crls.push(this.crls[k].toSchema(encodeFlag)); 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: current_crls })); } // #region Create array of signer infos var signer_infos = new Array(); for(var l = 0; l < this.signerInfos.length; l++) signer_infos.push(this.signerInfos[l].toSchema(encodeFlag)); output_array.push(new in_window.org.pkijs.asn1.SET({ value: signer_infos })); // #endregion // #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.CMS_SIGNED_DATA.prototype.verify = function() { // #region Global variables var sequence = Promise.resolve(); var certificates = this.certificates; var signerInfos = this.signerInfos; var encapContentInfo = this.encapContentInfo; var data = new ArrayBuffer(0); var sha_algorithm = ""; var signerIndex = -1; var cert_index = -1; var signer_cert = {}; var trusted_certs = new Array(); var _this = this; // #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 Get a signer number if(arguments[0] instanceof Object) { if("signer" in arguments[0]) signerIndex = arguments[0].signer; if("data" in arguments[0]) // Detached data data = arguments[0].data; if("trusted_certs" in arguments[0]) trusted_certs = arguments[0].trusted_certs; } if(signerIndex === (-1)) return new Promise(function(resolve, reject) { reject("Unable to get signer index from input parameters"); }); // #endregion // #region Check that certificates field was included in signed data if(("certificates" in this) === false) return new Promise(function(resolve, reject) { reject("No certificates attached to this signed data"); }); // #endregion // #region Find a certificate for specified signer if(this.signerInfos[signerIndex].sid instanceof in_window.org.pkijs.simpl.cms.IssuerAndSerialNumber) { sequence = sequence.then( function() { for(var i = 0; certificates.length; i++) { if((certificates[i].issuer.isEqual(signerInfos[signerIndex].sid.issuer)) && (certificates[i].serialNumber.isEqual(signerInfos[signerIndex].sid.serialNumber))) { signer_cert = certificates[i]; return new Promise(function(resolve, reject) { resolve(); }); } } return new Promise(function(resolve, reject) { reject("Unable to find signer certificate"); }); } ); } else // Find by SubjectKeyIdentifier { sequence = sequence.then( function() { var digest_promises = new Array(); for(var i = 0; i < certificates.length; i++) digest_promises.push(crypto.digest({ name: "sha-1" }, new Uint8Array(certificates[i].subjectPublicKeyInfo.subjectPublicKey.value_block.value_hex))); return Promise.all(digest_promises).then( function(results) { for(var i = 0; i < certificates.length; i++) { if(in_window.org.pkijs.isEqual_buffer(results[i], signerInfos[signerIndex].sid.value_block.value_hex)) { signer_cert = certificates[i]; return new Promise(function(re