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
JavaScript
/*
* 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