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,143 lines (1,034 loc) 99.1 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.ocsp" namespace if(typeof in_window.org.pkijs.simpl.ocsp === "undefined") in_window.org.pkijs.simpl.ocsp = {}; else { if(typeof in_window.org.pkijs.simpl.ocsp !== "object") throw new Error("Name org.pkijs.simpl.ocsp already exists and it's not an object" + " but " + (typeof in_window.org.pkijs.simpl.ocsp)); } // #endregion // #region "org.pkijs.simpl.tsp" namespace if(typeof in_window.org.pkijs.simpl.tsp === "undefined") in_window.org.pkijs.simpl.tsp = {}; else { if(typeof in_window.org.pkijs.simpl.tsp !== "object") throw new Error("Name org.pkijs.simpl.tsp already exists and it's not an object" + " but " + (typeof in_window.org.pkijs.simpl.tsp)); } // #endregion // #region "local" namespace var local = {}; // #endregion //************************************************************************************** // #endregion //************************************************************************************** // #region Simplified structure for "CertID" type //************************************************************************************** in_window.org.pkijs.simpl.ocsp.CertID = function() { // #region Internal properties of the object this.hashAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); this.issuerNameHash = new in_window.org.pkijs.asn1.OCTETSTRING(); this.issuerKeyHash = new in_window.org.pkijs.asn1.OCTETSTRING(); this.serialNumber = 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.ocsp.CertID.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.hashAlgorithm = arguments[0].hashAlgorithm || new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); this.issuerNameHash = arguments[0].issuerNameHash || new in_window.org.pkijs.asn1.OCTETSTRING(); this.issuerKeyHash = arguments[0].issuerKeyHash || new in_window.org.pkijs.asn1.OCTETSTRING(); this.serialNumber = arguments[0].serialNumber || new in_window.org.pkijs.asn1.INTEGER(); } } // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.ocsp.CertID.prototype.fromSchema = function(schema) { // #region Check the schema is valid var asn1 = in_window.org.pkijs.compareSchema(schema, schema, in_window.org.pkijs.schema.ocsp.CertID({ names: { hashAlgorithm: "hashAlgorithm", issuerNameHash: "issuerNameHash", issuerKeyHash: "issuerKeyHash", serialNumber: "serialNumber" } }) ); if(asn1.verified === false) throw new Error("Object's schema was not verified against input data for CertID"); // #endregion // #region Get internal properties from parsed schema this.hashAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ schema: asn1.result["hashAlgorithm"] }); this.issuerNameHash = asn1.result["issuerNameHash"]; this.issuerKeyHash = asn1.result["issuerKeyHash"]; this.serialNumber = asn1.result["serialNumber"];; // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.ocsp.CertID.prototype.toSchema = function() { // #region Construct and return new ASN.1 schema for this object return (new in_window.org.pkijs.asn1.SEQUENCE({ value: [ this.hashAlgorithm.toSchema(), this.issuerNameHash, this.issuerKeyHash, this.serialNumber ] })); // #endregion } //************************************************************************************** // #endregion //************************************************************************************** // #region Simplified structure for "Request" type //************************************************************************************** in_window.org.pkijs.simpl.ocsp.Request = function() { // #region Internal properties of the object this.reqCert = new in_window.org.pkijs.simpl.ocsp.CertID(); // OPTIONAL this.singleRequestExtensions = 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.ocsp.Request.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.reqCert = arguments[0].reqCert || new in_window.org.pkijs.simpl.ocsp.CertID(); if("singleRequestExtensions" in arguments[0]) this.singleRequestExtensions = arguments[0].singleRequestExtensions; } } // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.ocsp.Request.prototype.fromSchema = function(schema) { // #region Check the schema is valid var asn1 = in_window.org.pkijs.compareSchema(schema, schema, in_window.org.pkijs.schema.ocsp.Request({ names: { reqCert: { names: { block_name: "reqCert" } }, singleRequestExtensions: { names: { block_name: "singleRequestExtensions" } } } }) ); if(asn1.verified === false) throw new Error("Object's schema was not verified against input data for Request"); // #endregion // #region Get internal properties from parsed schema this.reqCert = new in_window.org.pkijs.simpl.ocsp.CertID({ schema: asn1.result["reqCert"] }); if("singleRequestExtensions" in asn1.result) { this.singleRequestExtensions = new Array(); var exts = asn1.result["singleRequestExtensions"].value_block.value; for(var i = 0; i < exts.length; i++) this.singleRequestExtensions.push(new in_window.org.pkijs.simpl.EXTENSION({ schema: exts[i] })); } // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.ocsp.Request.prototype.toSchema = function() { // #region Create array for output sequence var output_array = new Array(); output_array.push(this.reqCert.toSchema()); if("singleRequestExtensions" in this) { var extensions = new Array(); for(var j = 0; j < this.singleRequestExtensions.length; j++) extensions.push(this.singleRequestExtensions[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 // #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 "TBSRequest" type //************************************************************************************** in_window.org.pkijs.simpl.ocsp.TBSRequest = function() { // #region Internal properties of the object this.tbs = new ArrayBuffer(0); // Value of TBS part before decode // OPTIONAL this.version = 0; // OPTIONAL this.requestorName = new in_window.org.pkijs.simpl.GENERAL_NAME(); this.requestList = new Array(); // Array of "Request" objects // OPTIONAL this.requestExtensions = 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.ocsp.TBSRequest.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); // Value of TBS part before decode if("version" in arguments[0]) this.version = arguments[0].version; if("requestorName" in arguments[0]) this.requestorName = arguments[0].requestorName; this.requestList = arguments[0].requestList || new Array(); // Array of "Request" objects if("requestExtensions" in arguments[0]) this.requestExtensions = arguments[0].requestExtensions; } } // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.ocsp.TBSRequest.prototype.fromSchema = function(schema) { // #region Check the schema is valid var asn1 = in_window.org.pkijs.compareSchema(schema, schema, in_window.org.pkijs.schema.ocsp.TBSRequest() ); if(asn1.verified === false) throw new Error("Object's schema was not verified against input data for TBSRequest"); // #endregion // #region Get internal properties from parsed schema this.tbs = asn1.result["TBSRequest"].value_before_decode; if("TBSRequest.version" in asn1.result) this.version = asn1.result["TBSRequest.version"].value_block.value_dec; if("TBSRequest.requestorName" in asn1.result) this.requestorName = new in_window.org.pkijs.simpl.GENERAL_NAME({ schema: asn1.result["TBSRequest.requestorName"] }); var requests = asn1.result["TBSRequest.requests"]; for(var i = 0; i < requests.length; i++) this.requestList.push(new in_window.org.pkijs.simpl.ocsp.Request({ schema: requests[i] })); if("TBSRequest.requestExtensions" in asn1.result) { this.requestExtensions = new Array(); var exts = asn1.result["TBSRequest.requestExtensions"].value_block.value; for(var i = 0; i < exts.length; i++) this.requestExtensions.push(new in_window.org.pkijs.simpl.EXTENSION({ schema: exts[i] })); } // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.ocsp.TBSRequest.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> // #region Check "encodeFlag" if(typeof encodeFlag === "undefined") encodeFlag = false; // #endregion // #region Decode stored TBS value var tbs_schema; if(encodeFlag === false) { if(this.tbs.byteLength === 0) // No stored TBS part return in_window.org.pkijs.schema.ocsp.TBSRequest(); tbs_schema = in_window.org.pkijs.fromBER(this.tbs).result; } // #endregion // #region Create TBS schema via assembling from TBS parts else { 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 })] })); if("requestorName" in this) 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: [this.requestorName.toSchema()] })); var requests = new Array(); for(var i = 0; i < this.requestList.length; i++) requests.push(this.requestList[i].toSchema()); output_array.push(new in_window.org.pkijs.asn1.SEQUENCE({ value: requests })); if("requestExtensions" in this) { var extensions = new Array(); for(var j = 0; j < this.requestExtensions.length; j++) extensions.push(this.requestExtensions[j].toSchema()); output_array.push(new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ optional: true, id_block: { tag_class: 3, // CONTEXT-SPECIFIC tag_number: 2 // [2] }, value: [ new in_window.org.pkijs.asn1.SEQUENCE({ value: extensions }) ] })); } tbs_schema = new in_window.org.pkijs.asn1.SEQUENCE({ value: output_array }); } // #endregion // #region Construct and return new ASN.1 schema for this object return tbs_schema; // #endregion } //************************************************************************************** // #endregion //************************************************************************************** // #region Simplified structure for "Signature" type //************************************************************************************** in_window.org.pkijs.simpl.ocsp.Signature = function() { // #region Internal properties of the object this.signatureAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); this.signature = new in_window.org.pkijs.asn1.BITSTRING(); // OPTIONAL this.certs = new Array(); // Array of X.509 certificates // #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.ocsp.Signature.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.signatureAlgorithm = arguments[0].signatureAlgorithm || new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); this.signature = arguments[0].signature || new in_window.org.pkijs.asn1.BITSTRING(); if("certs" in arguments[0]) this.certs = arguments[0].certs; // Array of X.509 certificates } } // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.ocsp.Signature.prototype.fromSchema = function(schema) { // #region Check the schema is valid var asn1 = in_window.org.pkijs.compareSchema(schema, schema, in_window.org.pkijs.schema.ocsp.Signature({ names: { signatureAlgorithm: { names: { block_name: "signatureAlgorithm" } }, signature: "signature", certs: "certs" } }) ); if(asn1.verified === false) throw new Error("Object's schema was not verified against input data for ocsp.Signature"); // #endregion // #region Get internal properties from parsed schema this.signatureAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ schema: asn1.result["signatureAlgorithm"] }); this.signature = asn1.result["signature"]; if("certs" in asn1.result) { this.certs = new Array(); var certs_array = asn1.result["certs"]; for(var i = 0; i < certs_array; i++) this.certs.push(new in_window.org.pkijs.simpl.CERT({ schema: certs_array[i] })); } // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.ocsp.Signature.prototype.toSchema = function() { // #region Create array of output sequence var output_array = new Array(); output_array.push(this.signatureAlgorithm.toSchema()); output_array.push(this.signature); if("certs" in this) { // #region Create certificate array var cert_array = new Array(); for(var i = 0; i < this.certs; i++) cert_array.push(this.certs[i].toSchema()); // #endregion 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: cert_array }) ] })); } // #endregion // #region Construct and return new ASN.1 schema for this object return (new in_window.org.pkijs.asn1.SEQUENCE({ value: output_array })); // #endregion } //************************************************************************************** // #endregion //************************************************************************************** // #region Simplified structure for "OCSP_REQUEST" type //************************************************************************************** in_window.org.pkijs.simpl.OCSP_REQUEST = function() { // #region Internal properties of the object // OPTIONAL this.version = 0; // OPTIONAL this.requestorName = new in_window.org.pkijs.simpl.GENERAL_NAME(); this.requestList = new Array(); // Array of "Request" objects // OPTIONAL this.requestExtensions = new Array(); // Array of in_window.org.pkijs.simpl.EXTENSION(); // OPTIONAL this.optionalSignature = new in_window.org.pkijs.simpl.ocsp.Signature(); // #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.OCSP_REQUEST.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.tbsRequest = arguments[0].tbsRequest || new in_window.org.pkijs.simpl.ocsp.TBSRequest(); if("optionalSignature" in arguments[0]) this.optionalSignature = arguments[0].optionalSignature; } } // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.OCSP_REQUEST.prototype.fromSchema = function(schema) { // #region Check the schema is valid var asn1 = in_window.org.pkijs.compareSchema(schema, schema, in_window.org.pkijs.schema.OCSP_REQUEST() ); if(asn1.verified === false) throw new Error("Object's schema was not verified against input data for OCSP_REQUEST"); // #endregion // #region Get internal properties from parsed schema if("TBSRequest.version" in asn1.result) this.version = asn1.result["TBSRequest.version"].value_block.value_dec; if("TBSRequest.requestorName" in asn1.result) this.requestorName = new in_window.org.pkijs.simpl.GENERAL_NAME({ schema: asn1.result["TBSRequest.requestorName"] }); var requests = asn1.result["TBSRequest.requests"]; for(var i = 0; i < requests.length; i++) this.requestList.push(new in_window.org.pkijs.simpl.ocsp.Request({ schema: requests[i] })); if("TBSRequest.requestExtensions" in asn1.result) { this.requestExtensions = new Array(); var exts = asn1.result["TBSRequest.requestExtensions"].value_block.value; for(var i = 0; i < exts.length; i++) this.requestExtensions.push(new in_window.org.pkijs.simpl.EXTENSION({ schema: exts[i] })); } if("optionalSignature" in asn1.result) this.optionalSignature = new in_window.org.pkijs.simpl.ocsp.Signature({ schema: asn1.result["optionalSignature"] }); // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.OCSP_REQUEST.prototype.toSchema = function() { // #region Create array for output sequence var output_array = new Array(); // #region Create TBSRequest var tbs_array = new Array(); if("version" in this) tbs_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 })] })); if("requestorName" in this) tbs_array.push(new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ optional: true, id_block: { tag_class: 3, // CONTEXT-SPECIFIC tag_number: 1 // [1] }, value: [this.requestorName.toSchema()] })); var requests = new Array(); for(var i = 0; i < this.requestList.length; i++) requests.push(this.requestList[i].toSchema()); tbs_array.push(new in_window.org.pkijs.asn1.SEQUENCE({ value: requests })); if("requestExtensions" in this) { var extensions = new Array(); for(var j = 0; j < this.requestExtensions.length; j++) extensions.push(this.requestExtensions[j].toSchema()); tbs_array.push(new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ optional: true, id_block: { tag_class: 3, // CONTEXT-SPECIFIC tag_number: 2 // [2] }, value: [ new in_window.org.pkijs.asn1.SEQUENCE({ value: extensions }) ] })); } output_array.push(new in_window.org.pkijs.asn1.SEQUENCE({ value: tbs_array })); // #endregion if("optionalSignature" in this) output_array.push(this.optionalSignature.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.OCSP_REQUEST.prototype.sign = function(privateKey) { /// <param name="privateKey" type="Key">Private key for "subjectPublicKeyInfo" structure</param> // #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 Check that "optionalSignature" exists in the current request if(("optionalSignature" in this) === false) return new Promise(function(resolve, reject) { reject("Need to create \"optionalSignature\" field before signing"); }); // #endregion // #region Find a correct hashing algorithm var sha_algorithm = ""; switch(this.optionalSignature.signatureAlgorithm.algorithm_id) { case "1.2.840.113549.1.1.5": sha_algorithm = "sha-1"; break; case "1.2.840.113549.1.1.11": sha_algorithm = "sha-256"; break; case "1.2.840.113549.1.1.12": sha_algorithm = "sha-384"; break; case "1.2.840.113549.1.1.13": sha_algorithm = "sha-512"; break; default: return new Promise(function(resolve, reject) { reject("Unsupported signature algorithm: " + this.signature.signatureAlgorithm.algorithm_id); }); }; // #endregion // #region Create TBS data for signing var tbs = this.tbsRequest.toSchema(true).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({ name: privateKey.algorithm.name, hash: { name: sha_algorithm } }, privateKey, new Uint8Array(tbs)).then( function(result) { _this.optionalSignature.signature = new in_window.org.pkijs.asn1.BITSTRING({ value_hex: result }); }, function(error) { return new Promise(function(resolve, reject) { reject("Signing error: " + error); }); } ); // #endregion } //************************************************************************************** // #endregion //************************************************************************************** // #region Simplified structure for "ResponseBytes" type //************************************************************************************** in_window.org.pkijs.simpl.ocsp.ResponseBytes = function() { // #region Internal properties of the object this.responseType = ""; this.response = 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.ocsp.ResponseBytes.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.responseType = arguments[0].responseType || ""; this.response = arguments[0].response || new in_window.org.pkijs.asn1.OCTETSTRING(); } } // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.ocsp.ResponseBytes.prototype.fromSchema = function(schema) { // #region Check the schema is valid var asn1 = in_window.org.pkijs.compareSchema(schema, schema, in_window.org.pkijs.schema.ocsp.ResponseBytes({ names: { responseType: "responseType", response: "response" } }) ); if(asn1.verified === false) throw new Error("Object's schema was not verified against input data for ResponseBytes"); // #endregion // #region Get internal properties from parsed schema this.responseType = asn1.result["responseType"].value_block.toString(); this.response = asn1.result["response"]; // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.ocsp.ResponseBytes.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.responseType }), this.response ] })); // #endregion } //************************************************************************************** // #endregion //************************************************************************************** // #region Simplified structure for "OCSP_RESPONSE" type //************************************************************************************** in_window.org.pkijs.simpl.OCSP_RESPONSE = function() { // #region Internal properties of the object this.responseStatus = new in_window.org.pkijs.asn1.ENUMERATED(); // OPTIONAL this.responseBytes = new in_window.org.pkijs.simpl.ocsp.ResponseBytes(); // #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.OCSP_RESPONSE.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.responseStatus = arguments[0].responseStatus || new in_window.org.pkijs.asn1.ENUMERATED(); if("responseBytes" in arguments[0]) this.responseBytes = arguments[0].responseBytes; } } // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.OCSP_RESPONSE.prototype.fromSchema = function(schema) { // #region Check the schema is valid var asn1 = in_window.org.pkijs.compareSchema(schema, schema, in_window.org.pkijs.schema.OCSP_RESPONSE() ); if(asn1.verified === false) throw new Error("Object's schema was not verified against input data for OCSP_RESPONSE"); // #endregion // #region Get internal properties from parsed schema this.responseStatus = asn1.result["responseStatus"]; if("responseBytes" in asn1.result) this.responseBytes = new in_window.org.pkijs.simpl.ocsp.ResponseBytes({ schema: asn1.result["responseBytes"] }); // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.OCSP_RESPONSE.prototype.toSchema = function() { // #region Create array for output sequence var output_array = new Array(); output_array.push(this.responseStatus); if("responseBytes" 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.responseBytes.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.OCSP_RESPONSE.prototype.verify = function() { /// <summary>!!! Works well in Chrome dev versions only (April 2014th) !!!</summary> /// <returns type="Promise">Returns a new Promise object (in case of error), or a result of "crypto.subtle.veryfy" function</returns> // #region Check that ResponseBytes exists in the object if(("responseBytes" in this) === false) return new Promise(function(resolve, reject) { reject("Empty ResponseBytes field"); }); // #endregion // #region Check that ResponceData has type BasicOCSPResponse and verify it if(this.responseBytes.responseType === "1.3.6.1.5.5.7.48.1.1") { var asn1 = in_window.org.pkijs.fromBER(this.responseBytes.response.value_block.value_hex); var basic_resp_simpl = new in_window.org.pkijs.simpl.OCSP_BASIC_RESPONSE({ schema: asn1.result }); return basic_resp_simpl.verify(); } else return new Promise(function(resolve, reject) { reject("Unknown ResponseBytes type: " + this.responseBytes.responseType); }); // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.OCSP_RESPONSE.prototype.sign = function(privateKey) { /// <param name="privateKey" type="Key">Private key for "subjectPublicKeyInfo" structure</param> // #region Check that ResponceData has type BasicOCSPResponse and verify it if(this.responseBytes.responseType === "1.3.6.1.5.5.7.48.1.1") { var asn1 = in_window.org.pkijs.fromBER(this.responseBytes.response.value_block.value_hex); var basic_resp_simpl = new in_window.org.pkijs.simpl.OCSP_BASIC_RESPONSE({ schema: asn1.result }); return basic_resp_simpl.sign(privateKey); } else return new Promise(function(resolve, reject) { reject("Unknown ResponseBytes type: " + this.responseBytes.responseType); }); // #endregion } //************************************************************************************** // #endregion //************************************************************************************** // #region Simplified structure for "SingleResponse" type //************************************************************************************** in_window.org.pkijs.simpl.ocsp.SingleResponse = function() { // #region Internal properties of the object this.certID = new in_window.org.pkijs.simpl.ocsp.CertID(); this.certStatus = new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ id_block: { tag_class: 3, // CONTEXT-SPECIFIC tag_number: 3 // [3] }, value: [] }); // Fiction value this.thisUpdate = new Date(0, 0, 0); // OPTIONAL this.nextUpdate = new Date(0, 0, 0); // OPTIONAL this.singleExtensions = 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.ocsp.SingleResponse.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.certID = arguments[0].certID || new in_window.org.pkijs.simpl.ocsp.CertID(); this.certStatus = arguments[0].certStatus || new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ id_block: { tag_class: 3, // CONTEXT-SPECIFIC tag_number: 3 // [3] }, value: [] }); // Fiction value this.thisUpdate = arguments[0].thisUpdate || new Date(0, 0, 0); if("nextUpdate" in arguments[0]) this.nextUpdate = arguments[0].nextUpdate; if("singleExtensions" in arguments[0]) this.singleExtensions = arguments[0].singleExtensions; } } // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.ocsp.SingleResponse.prototype.fromSchema = function(schema) { // #region Check the schema is valid var asn1 = in_window.org.pkijs.compareSchema(schema, schema, in_window.org.pkijs.schema.ocsp.SingleResponse({ names: { certID: { names: { block_name: "certID" } }, certStatus: "certStatus", thisUpdate: "thisUpdate", nextUpdate: "nextUpdate", singleExtensions: "singleExtensions" } }) ); if(asn1.verified === false) throw new Error("Object's schema was not verified against input data for SingleResponse"); // #endregion // #region Get internal properties from parsed schema this.certID = new in_window.org.pkijs.simpl.ocsp.CertID({ schema: asn1.result["certID"] }); this.certStatus = asn1.result["certStatus"]; this.thisUpdate = asn1.result["thisUpdate"].toDate(); if("nextUpdate" in asn1.result) this.nextUpdate = asn1.result["nextUpdate"].toDate(); if("singleExtensions" in asn1.result) { this.singleExtensions = new Array(); var exts = asn1.result["singleExtensions"].value_block.value; for(var i = 0; i < exts.length; i++) this.singleExtensions.push(new in_window.org.pkijs.simpl.EXTENSION({ schema: exts[i] })); } // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.ocsp.SingleResponse.prototype.toSchema = function() { // #region Create value array for output sequence var output_array = new Array(); output_array.push(this.certID.toSchema()); output_array.push(this.certStatus); output_array.push(new in_window.org.pkijs.asn1.GENERALIZEDTIME({ value_date: this.thisUpdate })); if("nextUpdate" in this) output_array.push(new in_window.org.pkijs.asn1.GENERALIZEDTIME({ value_date: this.nextUpdate })); if("singleExtensions" in this) { var extensions = new Array(); for(var j = 0; j < this.singleExtensions.length; j++) extensions.push(this.singleExtensions[j].toSchema()); output_array.push(new in_window.org.pkijs.asn1.SEQUENCE({ value: extensions })); } // #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 "ResponseData" type //************************************************************************************** in_window.org.pkijs.simpl.ocsp.ResponseData = function() { // #region Internal properties of the object this.tbs = new ArrayBuffer(0); // OPTIONAL this.version = 0; this.responderID = new in_window.org.pkijs.simpl.RDN(); // Fake value this.producedAt = new Date(0, 0, 0); this.responses = new Array(); // Array of "SingleResponse" objects // OPTIONAL this.responseExtensions = 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.ocsp.ResponseData.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("version" in arguments[0]) this.version = arguments[0].version; this.responderID = arguments[0].responderID || new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ id_block: { tag_class: 3, // CONTEXT-SPECIFIC tag_number: 10 // [10] }, value: [] }); // Fake value this.producedAt = arguments[0].producedAt || new Date(0, 0, 0); this.responses = arguments[0].responses || new Array(); // Array of "SingleResponse" objects if("responseExtensions" in arguments[0]) this.responseExtensions = arguments[0].responseExtensions; } } // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.ocsp.ResponseData.prototype.fromSchema = function(schema) { // #region Check the schema is valid var asn1 = in_window.org.pkijs.compareSchema(schema, schema, in_window.org.pkijs.schema.ocsp.ResponseData() ); if(asn1.verified === false) throw new Error("Object's schema was not verified against input data for ocsp.ResponseData"); // #endregion // #region Get internal properties from parsed schema this.tbs = asn1.result["ResponseData"].value_before_decode; if("ResponseData.version" in asn1.result) this.version = asn1.result["ResponseData.version"].value_block.value_dec; if(asn1.result["ResponseData.responderID"].id_block.tag_number === 1) this.responderID = new in_window.org.pkijs.simpl.RDN({ schema: asn1.result["ResponseData.responderID"].value_block.value[0] }); else this.responderID = asn1.result["ResponseData.responderID"].value_block.value[0]; // OCTETSTRING this.producedAt = asn1.result["ResponseData.producedAt"].toDate(); var responses_array = asn1.result["ResponseData.responses"]; for(var i = 0; i < responses_array.length; i++) this.responses.push(new in_window.org.pkijs.simpl.ocsp.SingleResponse({ schema: responses_array[i] })); if("ResponseData.responseExtensions" in asn1.result) { this.responseExtensions = new Array(); var exts = asn1.result["ResponseData.responseExtensions"].value_block.value; for(var i = 0; i < exts.length; i++) this.responseExtensions.push(new in_window.org.pkijs.simpl.EXTENSION({ schema: exts[i] })); } // #endregion } //************************************************************************************** in_window.org.pkijs.simpl.ocsp.ResponseData.prototype.toSchema = function(encodeFlag) { /// <param name="encodeFlag" type="Boolean">If param equal to false then create TBS schema via decoding sto