@penneo/asn1js
Version:
asn1js is a pure JavaScript library implementing this standard. ASN.1 is the basis of all X.509 related data structures and numerous other protocols used on the web
1,400 lines (1,140 loc) • 205 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.RawData = exports.Repeated = exports.Any = exports.Choice = exports.TIME = exports.Duration = exports.DateTime = exports.TimeOfDay = exports.DATE = exports.GeneralizedTime = exports.UTCTime = exports.CharacterString = exports.GeneralString = exports.VisibleString = exports.GraphicString = exports.IA5String = exports.VideotexString = exports.TeletexString = exports.PrintableString = exports.NumericString = exports.UniversalString = exports.BmpString = exports.Utf8String = exports.ObjectIdentifier = exports.Enumerated = exports.Integer = exports.BitString = exports.OctetString = exports.Null = exports.Set = exports.Sequence = exports.Boolean = exports.EndOfContent = exports.Constructed = exports.Primitive = exports.BaseBlock = undefined;
var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /* eslint-disable indent */
/*
* Copyright (c) 2016-2018, Peculiar Ventures
* All rights reserved.
*
* Author 2016-2018, 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.
*
*/
//**************************************************************************************
exports.fromBER = fromBER;
exports.compareSchema = compareSchema;
exports.verifySchema = verifySchema;
exports.fromJSON = fromJSON;
var _pvutils = require("@penneo/pvutils");
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
//**************************************************************************************
//region Declaration of global variables
//**************************************************************************************
var powers2 = [new Uint8Array([1])];
var digitsString = "0123456789";
//**************************************************************************************
//endregion
//**************************************************************************************
//region Declaration for "LocalBaseBlock" class
//**************************************************************************************
/**
* Class used as a base block for all remaining ASN.1 classes
* @typedef LocalBaseBlock
* @interface
* @property {number} blockLength
* @property {string} error
* @property {Array.<string>} warnings
* @property {ArrayBuffer} valueBeforeDecode
*/
var LocalBaseBlock = function () {
//**********************************************************************************
/**
* Constructor for "LocalBaseBlock" class
* @param {Object} [parameters={}]
* @property {ArrayBuffer} [valueBeforeDecode]
*/
function LocalBaseBlock() {
var parameters = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
_classCallCheck(this, LocalBaseBlock);
/**
* @type {number} blockLength
*/
this.blockLength = (0, _pvutils.getParametersValue)(parameters, "blockLength", 0);
/**
* @type {string} error
*/
this.error = (0, _pvutils.getParametersValue)(parameters, "error", "");
/**
* @type {Array.<string>} warnings
*/
this.warnings = (0, _pvutils.getParametersValue)(parameters, "warnings", []);
//noinspection JSCheckFunctionSignatures
/**
* @type {ArrayBuffer} valueBeforeDecode
*/
if ("valueBeforeDecode" in parameters) this.valueBeforeDecode = parameters.valueBeforeDecode.slice(0);else this.valueBeforeDecode = new ArrayBuffer(0);
}
//**********************************************************************************
/**
* Aux function, need to get a block name. Need to have it here for inhiritence
* @returns {string}
*/
_createClass(LocalBaseBlock, [{
key: "toJSON",
//**********************************************************************************
/**
* Convertion for the block to JSON object
* @returns {{blockName: string, blockLength: number, error: string, warnings: Array.<string>, valueBeforeDecode: string}}
*/
value: function toJSON() {
return {
blockName: this.constructor.blockName(),
blockLength: this.blockLength,
error: this.error,
warnings: this.warnings,
valueBeforeDecode: (0, _pvutils.bufferToHexCodes)(this.valueBeforeDecode, 0, this.valueBeforeDecode.byteLength)
};
}
//**********************************************************************************
}], [{
key: "blockName",
value: function blockName() {
return "baseBlock";
}
}]);
return LocalBaseBlock;
}();
//**************************************************************************************
//endregion
//**************************************************************************************
//region Description for "LocalHexBlock" class
//**************************************************************************************
/**
* Class used as a base block for all remaining ASN.1 classes
* @extends LocalBaseBlock
* @typedef LocalHexBlock
* @property {number} blockLength
* @property {string} error
* @property {Array.<string>} warnings
* @property {ArrayBuffer} valueBeforeDecode
* @property {boolean} isHexOnly
* @property {ArrayBuffer} valueHex
*/
//noinspection JSUnusedLocalSymbols
var LocalHexBlock = function LocalHexBlock(BaseClass) {
return function (_BaseClass) {
_inherits(LocalHexBlockMixin, _BaseClass);
//**********************************************************************************
//noinspection JSUnusedGlobalSymbols
/**
* Constructor for "LocalHexBlock" class
* @param {Object} [parameters={}]
* @property {ArrayBuffer} [valueHex]
*/
function LocalHexBlockMixin() {
var parameters = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
_classCallCheck(this, LocalHexBlockMixin);
/**
* @type {boolean}
*/
var _this = _possibleConstructorReturn(this, (LocalHexBlockMixin.__proto__ || Object.getPrototypeOf(LocalHexBlockMixin)).call(this, parameters));
_this.isHexOnly = (0, _pvutils.getParametersValue)(parameters, "isHexOnly", false);
/**
* @type {ArrayBuffer}
*/
if ("valueHex" in parameters) _this.valueHex = parameters.valueHex.slice(0);else _this.valueHex = new ArrayBuffer(0);
return _this;
}
//**********************************************************************************
/**
* Aux function, need to get a block name. Need to have it here for inhiritence
* @returns {string}
*/
_createClass(LocalHexBlockMixin, [{
key: "fromBER",
//**********************************************************************************
/**
* Base function for converting block from BER encoded array of bytes
* @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
* @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
* @param {!number} inputLength Maximum length of array of bytes which can be using in this function
* @returns {number} Offset after least decoded byte
*/
value: function fromBER(inputBuffer, inputOffset, inputLength) {
//region Basic check for parameters
//noinspection JSCheckFunctionSignatures
if ((0, _pvutils.checkBufferParams)(this, inputBuffer, inputOffset, inputLength) === false) return -1;
//endregion
//region Getting Uint8Array from ArrayBuffer
var intBuffer = new Uint8Array(inputBuffer, inputOffset, inputLength);
//endregion
//region Initial checks
if (intBuffer.length === 0) {
this.warnings.push("Zero buffer length");
return inputOffset;
}
//endregion
//region Copy input buffer to internal buffer
this.valueHex = inputBuffer.slice(inputOffset, inputOffset + inputLength);
//endregion
this.blockLength = inputLength;
return inputOffset + inputLength;
}
//**********************************************************************************
/**
* Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)
* @param {boolean} [sizeOnly=false] Flag that we need only a size of encoding, not a real array of bytes
* @returns {ArrayBuffer}
*/
}, {
key: "toBER",
value: function toBER() {
var sizeOnly = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
if (this.isHexOnly !== true) {
this.error = "Flag \"isHexOnly\" is not set, abort";
return new ArrayBuffer(0);
}
if (sizeOnly === true) return new ArrayBuffer(this.valueHex.byteLength);
//noinspection JSCheckFunctionSignatures
return this.valueHex.slice(0);
}
//**********************************************************************************
/**
* Convertion for the block to JSON object
* @returns {Object}
*/
}, {
key: "toJSON",
value: function toJSON() {
var object = {};
//region Seems at the moment (Sep 2016) there is no way how to check method is supported in "super" object
try {
object = _get(LocalHexBlockMixin.prototype.__proto__ || Object.getPrototypeOf(LocalHexBlockMixin.prototype), "toJSON", this).call(this);
} catch (ex) {}
//endregion
object.blockName = this.constructor.blockName();
object.isHexOnly = this.isHexOnly;
object.valueHex = (0, _pvutils.bufferToHexCodes)(this.valueHex, 0, this.valueHex.byteLength);
return object;
}
//**********************************************************************************
}], [{
key: "blockName",
value: function blockName() {
return "hexBlock";
}
}]);
return LocalHexBlockMixin;
}(BaseClass);
};
//**************************************************************************************
//endregion
//**************************************************************************************
//region Declaration of identification block class
//**************************************************************************************
var LocalIdentificationBlock = function (_LocalHexBlock) {
_inherits(LocalIdentificationBlock, _LocalHexBlock);
//**********************************************************************************
/**
* Constructor for "LocalBaseBlock" class
* @param {Object} [parameters={}]
* @property {Object} [idBlock]
*/
function LocalIdentificationBlock() {
var parameters = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
_classCallCheck(this, LocalIdentificationBlock);
var _this2 = _possibleConstructorReturn(this, (LocalIdentificationBlock.__proto__ || Object.getPrototypeOf(LocalIdentificationBlock)).call(this));
if ("idBlock" in parameters) {
//region Properties from hexBlock class
_this2.isHexOnly = (0, _pvutils.getParametersValue)(parameters.idBlock, "isHexOnly", false);
_this2.valueHex = (0, _pvutils.getParametersValue)(parameters.idBlock, "valueHex", new ArrayBuffer(0));
//endregion
_this2.tagClass = (0, _pvutils.getParametersValue)(parameters.idBlock, "tagClass", -1);
_this2.tagNumber = (0, _pvutils.getParametersValue)(parameters.idBlock, "tagNumber", -1);
_this2.isConstructed = (0, _pvutils.getParametersValue)(parameters.idBlock, "isConstructed", false);
} else {
_this2.tagClass = -1;
_this2.tagNumber = -1;
_this2.isConstructed = false;
}
return _this2;
}
//**********************************************************************************
/**
* Aux function, need to get a block name. Need to have it here for inhiritence
* @returns {string}
*/
_createClass(LocalIdentificationBlock, [{
key: "toBER",
//**********************************************************************************
/**
* Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)
* @param {boolean} [sizeOnly=false] Flag that we need only a size of encoding, not a real array of bytes
* @returns {ArrayBuffer}
*/
value: function toBER() {
var sizeOnly = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
//region Initial variables
var firstOctet = 0;
var retBuf = void 0;
var retView = void 0;
//endregion
switch (this.tagClass) {
case 1:
firstOctet |= 0x00; // UNIVERSAL
break;
case 2:
firstOctet |= 0x40; // APPLICATION
break;
case 3:
firstOctet |= 0x80; // CONTEXT-SPECIFIC
break;
case 4:
firstOctet |= 0xC0; // PRIVATE
break;
default:
this.error = "Unknown tag class";
return new ArrayBuffer(0);
}
if (this.isConstructed) firstOctet |= 0x20;
if (this.tagNumber < 31 && !this.isHexOnly) {
retBuf = new ArrayBuffer(1);
retView = new Uint8Array(retBuf);
if (!sizeOnly) {
var number = this.tagNumber;
number &= 0x1F;
firstOctet |= number;
retView[0] = firstOctet;
}
return retBuf;
}
if (this.isHexOnly === false) {
var encodedBuf = (0, _pvutils.utilToBase)(this.tagNumber, 7);
var encodedView = new Uint8Array(encodedBuf);
var size = encodedBuf.byteLength;
retBuf = new ArrayBuffer(size + 1);
retView = new Uint8Array(retBuf);
retView[0] = firstOctet | 0x1F;
if (!sizeOnly) {
for (var i = 0; i < size - 1; i++) {
retView[i + 1] = encodedView[i] | 0x80;
}retView[size] = encodedView[size - 1];
}
return retBuf;
}
retBuf = new ArrayBuffer(this.valueHex.byteLength + 1);
retView = new Uint8Array(retBuf);
retView[0] = firstOctet | 0x1F;
if (sizeOnly === false) {
var curView = new Uint8Array(this.valueHex);
for (var _i = 0; _i < curView.length - 1; _i++) {
retView[_i + 1] = curView[_i] | 0x80;
}retView[this.valueHex.byteLength] = curView[curView.length - 1];
}
return retBuf;
}
//**********************************************************************************
/**
* Base function for converting block from BER encoded array of bytes
* @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
* @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
* @param {!number} inputLength Maximum length of array of bytes which can be using in this function
* @returns {number}
*/
}, {
key: "fromBER",
value: function fromBER(inputBuffer, inputOffset, inputLength) {
//region Basic check for parameters
//noinspection JSCheckFunctionSignatures
if ((0, _pvutils.checkBufferParams)(this, inputBuffer, inputOffset, inputLength) === false) return -1;
//endregion
//region Getting Uint8Array from ArrayBuffer
var intBuffer = new Uint8Array(inputBuffer, inputOffset, inputLength);
//endregion
//region Initial checks
if (intBuffer.length === 0) {
this.error = "Zero buffer length";
return -1;
}
//endregion
//region Find tag class
var tagClassMask = intBuffer[0] & 0xC0;
switch (tagClassMask) {
case 0x00:
this.tagClass = 1; // UNIVERSAL
break;
case 0x40:
this.tagClass = 2; // APPLICATION
break;
case 0x80:
this.tagClass = 3; // CONTEXT-SPECIFIC
break;
case 0xC0:
this.tagClass = 4; // PRIVATE
break;
default:
this.error = "Unknown tag class";
return -1;
}
//endregion
//region Find it's constructed or not
this.isConstructed = (intBuffer[0] & 0x20) === 0x20;
//endregion
//region Find tag number
this.isHexOnly = false;
var tagNumberMask = intBuffer[0] & 0x1F;
//region Simple case (tag number < 31)
if (tagNumberMask !== 0x1F) {
this.tagNumber = tagNumberMask;
this.blockLength = 1;
}
//endregion
//region Tag number bigger or equal to 31
else {
var count = 1;
this.valueHex = new ArrayBuffer(255);
var tagNumberBufferMaxLength = 255;
var intTagNumberBuffer = new Uint8Array(this.valueHex);
//noinspection JSBitwiseOperatorUsage
while (intBuffer[count] & 0x80) {
intTagNumberBuffer[count - 1] = intBuffer[count] & 0x7F;
count++;
if (count >= intBuffer.length) {
this.error = "End of input reached before message was fully decoded";
return -1;
}
//region In case if tag number length is greater than 255 bytes (rare but possible case)
if (count === tagNumberBufferMaxLength) {
tagNumberBufferMaxLength += 255;
var _tempBuffer = new ArrayBuffer(tagNumberBufferMaxLength);
var _tempBufferView = new Uint8Array(_tempBuffer);
for (var i = 0; i < intTagNumberBuffer.length; i++) {
_tempBufferView[i] = intTagNumberBuffer[i];
}this.valueHex = new ArrayBuffer(tagNumberBufferMaxLength);
intTagNumberBuffer = new Uint8Array(this.valueHex);
}
//endregion
}
this.blockLength = count + 1;
intTagNumberBuffer[count - 1] = intBuffer[count] & 0x7F; // Write last byte to buffer
//region Cut buffer
var tempBuffer = new ArrayBuffer(count);
var tempBufferView = new Uint8Array(tempBuffer);
for (var _i2 = 0; _i2 < count; _i2++) {
tempBufferView[_i2] = intTagNumberBuffer[_i2];
}this.valueHex = new ArrayBuffer(count);
intTagNumberBuffer = new Uint8Array(this.valueHex);
intTagNumberBuffer.set(tempBufferView);
//endregion
//region Try to convert long tag number to short form
if (this.blockLength <= 9) this.tagNumber = (0, _pvutils.utilFromBase)(intTagNumberBuffer, 7);else {
this.isHexOnly = true;
this.warnings.push("Tag too long, represented as hex-coded");
}
//endregion
}
//endregion
//endregion
//region Check if constructed encoding was using for primitive type
if (this.tagClass === 1 && this.isConstructed) {
switch (this.tagNumber) {
case 1: // Boolean
case 2: // REAL
case 5: // Null
case 6: // OBJECT IDENTIFIER
case 9: // REAL
case 14: // Time
case 23:
case 24:
case 31:
case 32:
case 33:
case 34:
this.error = "Constructed encoding used for primitive type";
return -1;
default:
}
}
//endregion
return inputOffset + this.blockLength; // Return current offset in input buffer
}
//**********************************************************************************
/**
* Convertion for the block to JSON object
* @returns {{blockName: string,
* tagClass: number,
* tagNumber: number,
* isConstructed: boolean,
* isHexOnly: boolean,
* valueHex: ArrayBuffer,
* blockLength: number,
* error: string, warnings: Array.<string>,
* valueBeforeDecode: string}}
*/
}, {
key: "toJSON",
value: function toJSON() {
var object = {};
//region Seems at the moment (Sep 2016) there is no way how to check method is supported in "super" object
try {
object = _get(LocalIdentificationBlock.prototype.__proto__ || Object.getPrototypeOf(LocalIdentificationBlock.prototype), "toJSON", this).call(this);
} catch (ex) {}
//endregion
object.blockName = this.constructor.blockName();
object.tagClass = this.tagClass;
object.tagNumber = this.tagNumber;
object.isConstructed = this.isConstructed;
return object;
}
//**********************************************************************************
}], [{
key: "blockName",
value: function blockName() {
return "identificationBlock";
}
}]);
return LocalIdentificationBlock;
}(LocalHexBlock(LocalBaseBlock));
//**************************************************************************************
//endregion
//**************************************************************************************
//region Declaration of length block class
//**************************************************************************************
var LocalLengthBlock = function (_LocalBaseBlock) {
_inherits(LocalLengthBlock, _LocalBaseBlock);
//**********************************************************************************
/**
* Constructor for "LocalLengthBlock" class
* @param {Object} [parameters={}]
* @property {Object} [lenBlock]
*/
function LocalLengthBlock() {
var parameters = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
_classCallCheck(this, LocalLengthBlock);
var _this3 = _possibleConstructorReturn(this, (LocalLengthBlock.__proto__ || Object.getPrototypeOf(LocalLengthBlock)).call(this));
if ("lenBlock" in parameters) {
_this3.isIndefiniteForm = (0, _pvutils.getParametersValue)(parameters.lenBlock, "isIndefiniteForm", false);
_this3.longFormUsed = (0, _pvutils.getParametersValue)(parameters.lenBlock, "longFormUsed", false);
_this3.length = (0, _pvutils.getParametersValue)(parameters.lenBlock, "length", 0);
} else {
_this3.isIndefiniteForm = false;
_this3.longFormUsed = false;
_this3.length = 0;
}
return _this3;
}
//**********************************************************************************
/**
* Aux function, need to get a block name. Need to have it here for inhiritence
* @returns {string}
*/
_createClass(LocalLengthBlock, [{
key: "fromBER",
//**********************************************************************************
/**
* Base function for converting block from BER encoded array of bytes
* @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
* @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
* @param {!number} inputLength Maximum length of array of bytes which can be using in this function
* @returns {number}
*/
value: function fromBER(inputBuffer, inputOffset, inputLength) {
//region Basic check for parameters
//noinspection JSCheckFunctionSignatures
if ((0, _pvutils.checkBufferParams)(this, inputBuffer, inputOffset, inputLength) === false) return -1;
//endregion
//region Getting Uint8Array from ArrayBuffer
var intBuffer = new Uint8Array(inputBuffer, inputOffset, inputLength);
//endregion
//region Initial checks
if (intBuffer.length === 0) {
this.error = "Zero buffer length";
return -1;
}
if (intBuffer[0] === 0xFF) {
this.error = "Length block 0xFF is reserved by standard";
return -1;
}
//endregion
//region Check for length form type
this.isIndefiniteForm = intBuffer[0] === 0x80;
//endregion
//region Stop working in case of indefinite length form
if (this.isIndefiniteForm === true) {
this.blockLength = 1;
return inputOffset + this.blockLength;
}
//endregion
//region Check is long form of length encoding using
this.longFormUsed = !!(intBuffer[0] & 0x80);
//endregion
//region Stop working in case of short form of length value
if (this.longFormUsed === false) {
this.length = intBuffer[0];
this.blockLength = 1;
return inputOffset + this.blockLength;
}
//endregion
//region Calculate length value in case of long form
var count = intBuffer[0] & 0x7F;
if (count > 8) // Too big length value
{
this.error = "Too big integer";
return -1;
}
if (count + 1 > intBuffer.length) {
this.error = "End of input reached before message was fully decoded";
return -1;
}
var lengthBufferView = new Uint8Array(count);
for (var i = 0; i < count; i++) {
lengthBufferView[i] = intBuffer[i + 1];
}if (lengthBufferView[count - 1] === 0x00) this.warnings.push("Needlessly long encoded length");
this.length = (0, _pvutils.utilFromBase)(lengthBufferView, 8);
if (this.longFormUsed && this.length <= 127) this.warnings.push("Unneccesary usage of long length form");
this.blockLength = count + 1;
//endregion
return inputOffset + this.blockLength; // Return current offset in input buffer
}
//**********************************************************************************
/**
* Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)
* @param {boolean} [sizeOnly=false] Flag that we need only a size of encoding, not a real array of bytes
* @returns {ArrayBuffer}
*/
}, {
key: "toBER",
value: function toBER() {
var sizeOnly = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
//region Initial variables
var retBuf = void 0;
var retView = void 0;
//endregion
if (this.length > 127) this.longFormUsed = true;
if (this.isIndefiniteForm) {
retBuf = new ArrayBuffer(1);
if (sizeOnly === false) {
retView = new Uint8Array(retBuf);
retView[0] = 0x80;
}
return retBuf;
}
if (this.longFormUsed === true) {
var encodedBuf = (0, _pvutils.utilToBase)(this.length, 8);
if (encodedBuf.byteLength > 127) {
this.error = "Too big length";
return new ArrayBuffer(0);
}
retBuf = new ArrayBuffer(encodedBuf.byteLength + 1);
if (sizeOnly === true) return retBuf;
var encodedView = new Uint8Array(encodedBuf);
retView = new Uint8Array(retBuf);
retView[0] = encodedBuf.byteLength | 0x80;
for (var i = 0; i < encodedBuf.byteLength; i++) {
retView[i + 1] = encodedView[i];
}return retBuf;
}
retBuf = new ArrayBuffer(1);
if (sizeOnly === false) {
retView = new Uint8Array(retBuf);
retView[0] = this.length;
}
return retBuf;
}
//**********************************************************************************
/**
* Convertion for the block to JSON object
* @returns {{blockName, blockLength, error, warnings, valueBeforeDecode}|{blockName: string, blockLength: number, error: string, warnings: Array.<string>, valueBeforeDecode: string}}
*/
}, {
key: "toJSON",
value: function toJSON() {
var object = {};
//region Seems at the moment (Sep 2016) there is no way how to check method is supported in "super" object
try {
object = _get(LocalLengthBlock.prototype.__proto__ || Object.getPrototypeOf(LocalLengthBlock.prototype), "toJSON", this).call(this);
} catch (ex) {}
//endregion
object.blockName = this.constructor.blockName();
object.isIndefiniteForm = this.isIndefiniteForm;
object.longFormUsed = this.longFormUsed;
object.length = this.length;
return object;
}
//**********************************************************************************
}], [{
key: "blockName",
value: function blockName() {
return "lengthBlock";
}
}]);
return LocalLengthBlock;
}(LocalBaseBlock);
//**************************************************************************************
//endregion
//**************************************************************************************
//region Declaration of value block class
//**************************************************************************************
var LocalValueBlock = function (_LocalBaseBlock2) {
_inherits(LocalValueBlock, _LocalBaseBlock2);
//**********************************************************************************
/**
* Constructor for "LocalValueBlock" class
* @param {Object} [parameters={}]
*/
function LocalValueBlock() {
var parameters = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
_classCallCheck(this, LocalValueBlock);
return _possibleConstructorReturn(this, (LocalValueBlock.__proto__ || Object.getPrototypeOf(LocalValueBlock)).call(this, parameters));
}
//**********************************************************************************
/**
* Aux function, need to get a block name. Need to have it here for inhiritence
* @returns {string}
*/
_createClass(LocalValueBlock, [{
key: "fromBER",
//**********************************************************************************
//noinspection JSUnusedLocalSymbols,JSUnusedLocalSymbols,JSUnusedLocalSymbols
/**
* Base function for converting block from BER encoded array of bytes
* @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
* @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
* @param {!number} inputLength Maximum length of array of bytes which can be using in this function
* @returns {number}
*/
value: function fromBER(inputBuffer, inputOffset, inputLength) {
//region Throw an exception for a function which needs to be specified in extended classes
throw TypeError("User need to make a specific function in a class which extends \"LocalValueBlock\"");
//endregion
}
//**********************************************************************************
//noinspection JSUnusedLocalSymbols
/**
* Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)
* @param {boolean} [sizeOnly=false] Flag that we need only a size of encoding, not a real array of bytes
* @returns {ArrayBuffer}
*/
}, {
key: "toBER",
value: function toBER() {
var sizeOnly = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
//region Throw an exception for a function which needs to be specified in extended classes
throw TypeError("User need to make a specific function in a class which extends \"LocalValueBlock\"");
//endregion
}
//**********************************************************************************
}], [{
key: "blockName",
value: function blockName() {
return "valueBlock";
}
}]);
return LocalValueBlock;
}(LocalBaseBlock);
//**************************************************************************************
//endregion
//**************************************************************************************
//region Declaration of basic ASN.1 block class
//**************************************************************************************
var BaseBlock = exports.BaseBlock = function (_LocalBaseBlock3) {
_inherits(BaseBlock, _LocalBaseBlock3);
//**********************************************************************************
/**
* Constructor for "BaseBlock" class
* @param {Object} [parameters={}]
* @property {Object} [primitiveSchema]
* @property {string} [name]
* @property {boolean} [optional]
* @param valueBlockType Type of value block
*/
function BaseBlock() {
var parameters = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var valueBlockType = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : LocalValueBlock;
_classCallCheck(this, BaseBlock);
var _this5 = _possibleConstructorReturn(this, (BaseBlock.__proto__ || Object.getPrototypeOf(BaseBlock)).call(this, parameters));
if ("name" in parameters) _this5.name = parameters.name;
if ("optional" in parameters) _this5.optional = parameters.optional;
if ("primitiveSchema" in parameters) _this5.primitiveSchema = parameters.primitiveSchema;
_this5.idBlock = new LocalIdentificationBlock(parameters);
_this5.lenBlock = new LocalLengthBlock(parameters);
_this5.valueBlock = new valueBlockType(parameters);
return _this5;
}
//**********************************************************************************
/**
* Aux function, need to get a block name. Need to have it here for inhiritence
* @returns {string}
*/
_createClass(BaseBlock, [{
key: "fromBER",
//**********************************************************************************
/**
* Base function for converting block from BER encoded array of bytes
* @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
* @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
* @param {!number} inputLength Maximum length of array of bytes which can be using in this function
* @returns {number}
*/
value: function fromBER(inputBuffer, inputOffset, inputLength) {
var resultOffset = this.valueBlock.fromBER(inputBuffer, inputOffset, this.lenBlock.isIndefiniteForm === true ? inputLength : this.lenBlock.length);
if (resultOffset === -1) {
this.error = this.valueBlock.error;
return resultOffset;
}
if (this.idBlock.error.length === 0) this.blockLength += this.idBlock.blockLength;
if (this.lenBlock.error.length === 0) this.blockLength += this.lenBlock.blockLength;
if (this.valueBlock.error.length === 0) this.blockLength += this.valueBlock.blockLength;
return resultOffset;
}
//**********************************************************************************
/**
* Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)
* @param {boolean} [sizeOnly=false] Flag that we need only a size of encoding, not a real array of bytes
* @returns {ArrayBuffer}
*/
}, {
key: "toBER",
value: function toBER() {
var sizeOnly = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
var retBuf = void 0;
var idBlockBuf = this.idBlock.toBER(sizeOnly);
var valueBlockSizeBuf = this.valueBlock.toBER(true);
this.lenBlock.length = valueBlockSizeBuf.byteLength;
var lenBlockBuf = this.lenBlock.toBER(sizeOnly);
retBuf = (0, _pvutils.utilConcatBuf)(idBlockBuf, lenBlockBuf);
var valueBlockBuf = void 0;
if (sizeOnly === false) valueBlockBuf = this.valueBlock.toBER(sizeOnly);else valueBlockBuf = new ArrayBuffer(this.lenBlock.length);
retBuf = (0, _pvutils.utilConcatBuf)(retBuf, valueBlockBuf);
if (this.lenBlock.isIndefiniteForm === true) {
var indefBuf = new ArrayBuffer(2);
if (sizeOnly === false) {
var indefView = new Uint8Array(indefBuf);
indefView[0] = 0x00;
indefView[1] = 0x00;
}
retBuf = (0, _pvutils.utilConcatBuf)(retBuf, indefBuf);
}
return retBuf;
}
//**********************************************************************************
/**
* Convertion for the block to JSON object
* @returns {{blockName, blockLength, error, warnings, valueBeforeDecode}|{blockName: string, blockLength: number, error: string, warnings: Array.<string>, valueBeforeDecode: string}}
*/
}, {
key: "toJSON",
value: function toJSON() {
var object = {};
//region Seems at the moment (Sep 2016) there is no way how to check method is supported in "super" object
try {
object = _get(BaseBlock.prototype.__proto__ || Object.getPrototypeOf(BaseBlock.prototype), "toJSON", this).call(this);
} catch (ex) {}
//endregion
object.idBlock = this.idBlock.toJSON();
object.lenBlock = this.lenBlock.toJSON();
object.valueBlock = this.valueBlock.toJSON();
if ("name" in this) object.name = this.name;
if ("optional" in this) object.optional = this.optional;
if ("primitiveSchema" in this) object.primitiveSchema = this.primitiveSchema.toJSON();
return object;
}
//**********************************************************************************
}], [{
key: "blockName",
value: function blockName() {
return "BaseBlock";
}
}]);
return BaseBlock;
}(LocalBaseBlock);
//**************************************************************************************
//endregion
//**************************************************************************************
//region Declaration of basic block for all PRIMITIVE types
//**************************************************************************************
var LocalPrimitiveValueBlock = function (_LocalValueBlock) {
_inherits(LocalPrimitiveValueBlock, _LocalValueBlock);
//**********************************************************************************
/**
* Constructor for "LocalPrimitiveValueBlock" class
* @param {Object} [parameters={}]
* @property {ArrayBuffer} [valueBeforeDecode]
*/
function LocalPrimitiveValueBlock() {
var parameters = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
_classCallCheck(this, LocalPrimitiveValueBlock);
//region Variables from "hexBlock" class
var _this6 = _possibleConstructorReturn(this, (LocalPrimitiveValueBlock.__proto__ || Object.getPrototypeOf(LocalPrimitiveValueBlock)).call(this, parameters));
if ("valueHex" in parameters) _this6.valueHex = parameters.valueHex.slice(0);else _this6.valueHex = new ArrayBuffer(0);
_this6.isHexOnly = (0, _pvutils.getParametersValue)(parameters, "isHexOnly", true);
//endregion
return _this6;
}
//**********************************************************************************
/**
* Base function for converting block from BER encoded array of bytes
* @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
* @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
* @param {!number} inputLength Maximum length of array of bytes which can be using in this function
* @returns {number}
*/
_createClass(LocalPrimitiveValueBlock, [{
key: "fromBER",
value: function fromBER(inputBuffer, inputOffset, inputLength) {
//region Basic check for parameters
//noinspection JSCheckFunctionSignatures
if ((0, _pvutils.checkBufferParams)(this, inputBuffer, inputOffset, inputLength) === false) return -1;
//endregion
//region Getting Uint8Array from ArrayBuffer
var intBuffer = new Uint8Array(inputBuffer, inputOffset, inputLength);
//endregion
//region Initial checks
if (intBuffer.length === 0) {
this.warnings.push("Zero buffer length");
return inputOffset;
}
//endregion
//region Copy input buffer into internal buffer
this.valueHex = new ArrayBuffer(intBuffer.length);
var valueHexView = new Uint8Array(this.valueHex);
for (var i = 0; i < intBuffer.length; i++) {
valueHexView[i] = intBuffer[i];
} //endregion
this.blockLength = inputLength;
return inputOffset + inputLength;
}
//**********************************************************************************
//noinspection JSUnusedLocalSymbols
/**
* Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)
* @param {boolean} [sizeOnly=false] Flag that we need only a size of encoding, not a real array of bytes
* @returns {ArrayBuffer}
*/
}, {
key: "toBER",
value: function toBER() {
var sizeOnly = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
return this.valueHex.slice(0);
}
//**********************************************************************************
/**
* Aux function, need to get a block name. Need to have it here for inhiritence
* @returns {string}
*/
}, {
key: "toJSON",
//**********************************************************************************
/**
* Convertion for the block to JSON object
* @returns {{blockName, blockLength, error, warnings, valueBeforeDecode}|{blockName: string, blockLength: number, error: string, warnings: Array.<string>, valueBeforeDecode: string}}
*/
value: function toJSON() {
var object = {};
//region Seems at the moment (Sep 2016) there is no way how to check method is supported in "super" object
try {
object = _get(LocalPrimitiveValueBlock.prototype.__proto__ || Object.getPrototypeOf(LocalPrimitiveValueBlock.prototype), "toJSON", this).call(this);
} catch (ex) {}
//endregion
object.valueHex = (0, _pvutils.bufferToHexCodes)(this.valueHex, 0, this.valueHex.byteLength);
object.isHexOnly = this.isHexOnly;
return object;
}
//**********************************************************************************
}], [{
key: "blockName",
value: function blockName() {
return "PrimitiveValueBlock";
}
}]);
return LocalPrimitiveValueBlock;
}(LocalValueBlock);
//**************************************************************************************
var Primitive = exports.Primitive = function (_BaseBlock) {
_inherits(Primitive, _BaseBlock);
//**********************************************************************************
/**
* Constructor for "Primitive" class
* @param {Object} [parameters={}]
* @property {ArrayBuffer} [valueHex]
*/
function Primitive() {
var parameters = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
_classCallCheck(this, Primitive);
var _this7 = _possibleConstructorReturn(this, (Primitive.__proto__ || Object.getPrototypeOf(Primitive)).call(this, parameters, LocalPrimitiveValueBlock));
_this7.idBlock.isConstructed = false;
return _this7;
}
//**********************************************************************************
/**
* Aux function, need to get a block name. Need to have it here for inhiritence
* @returns {string}
*/
_createClass(Primitive, null, [{
key: "blockName",
value: function blockName() {
return "PRIMITIVE";
}
//**********************************************************************************
}]);
return Primitive;
}(BaseBlock);
//**************************************************************************************
//endregion
//**************************************************************************************
//region Declaration of basic block for all CONSTRUCTED types
//**************************************************************************************
var LocalConstructedValueBlock = function (_LocalValueBlock2) {
_inherits(LocalConstructedValueBlock, _LocalValueBlock2);
//**********************************************************************************
/**
* Constructor for "LocalConstructedValueBlock" class
* @param {Object} [parameters={}]
*/
function LocalConstructedValueBlock() {
var parameters = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
_classCallCheck(this, LocalConstructedValueBlock);
var _this8 = _possibleConstructorReturn(this, (LocalConstructedValueBlock.__proto__ || Object.getPrototypeOf(LocalConstructedValueBlock)).call(this, parameters));
_this8.value = (0, _pvutils.getParametersValue)(parameters, "value", []);
_this8.isIndefiniteForm = (0, _pvutils.getParametersValue)(parameters, "isIndefiniteForm", false);
return _this8;
}
//**********************************************************************************
/**
* Base function for converting block from BER encoded array of bytes
* @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
* @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
* @param {!number} inputLength Maximum length of array of bytes which can be using in this function
* @returns {number}
*/
_createClass(LocalConstructedValueBlock, [{
key: "fromBER",
value: function fromBER(inputBuffer, inputOffset, inputLength) {
//region Store initial offset and length
var initialOffset = inputOffset;
var initialLength = inputLength;
//endregion
//region Basic check for parameters
//noinspection JSCheckFunctionSignatures
if ((0, _pvutils.checkBufferParams)(this, inputBuffer, inputOffset, inputLength) === false) return -1;
//endregion
//region Getting Uint8Array from ArrayBuffer
var intBuffer = new Uint8Array(inputBuffer, inputOffset, inputLength);
//endregion
//region Initial checks
if (intBuffer.length === 0) {
this.warnings.push("Zero buffer length");
return inputOffset;
}
//endregion
//region Aux function
function checkLen(indefiniteLength, length) {
if (indefiniteLength === true) return 1;
return length;
}
//endregion
var currentOffset = inputOffset;
while (checkLen(this.isIndefiniteForm, inputLength) > 0) {
var returnObject = LocalFromBER(inputBuffer, currentOffset, inputLength);
if (returnObject.offset === -1) {
this.error = returnObject.result.error;
this.warnings.concat(returnObject.result.warnings);
return -1;
}
currentOffset = returnObject.offset;
this.blockLength += returnObject.result.blockLength;
inputLength -= returnObject.result.blockLength;
this.value.push(returnObject.result);
if (this.isIndefiniteForm === true && returnObject.result.constructor.blockName() === EndOfContent.blockName()) break;
}
if (this.isIndefiniteForm === true) {
if (this.value[this.value.length - 1].constructor.blockName() === EndOfContent.blockName()) this.value.pop();else this.warnings.push("No EndOfContent block encoded");
}
//region Copy "inputBuffer" to "valueBeforeDecode"
this.valueBeforeDecode = inputBuffer.slice(initialOffset, initialOffset + initialLength);
//endregion
return currentOffset;
}
//**********************************************************************************
/**
* Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)
* @param {boolean} [sizeOnly=false] Flag that we need only a size of encoding, not a real array of bytes
* @returns {ArrayBuffer}
*/
}, {
key: "toBER",
value: function toBER() {
var sizeOnly = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
var retBuf = new ArrayBuffer(0);
for (var i = 0; i < this.value.length; i++) {
var valueBuf = this.value[i].toBER(sizeOnly);
retBuf = (0, _pvutils.utilConcatBuf)(retBuf, valueBuf);
}
return retBuf;
}
//**********************************************************************************
/**
* Aux function, need to get a block name. Need to have it here for inhiritence
* @returns {string}
*/
}, {
key: "toJSON",
//**********************************************************************************
/**
* Convertion for the block to JSON object
* @returns {{blockName, blockLength, error, warnings, valueBeforeDecode}|{blockName: string, blockLength: number, error: string, warnings: Array.<string>, valueBeforeDecode: string}}
*/
value: function toJSON() {
var object = {};
//region Seems at the moment (Sep 2016) there is no way how to check method is supported in "super" object
try {
object = _get(LocalConstructedValueBlock.prototype.__proto__ || Object.getPrototypeOf(LocalConstructedValueBlock.prototype), "toJSON", this).call(this);
} catch (ex) {}
//endregion
object.isIndefiniteForm = this.isIndefiniteForm;
object.value = [];
for (var i = 0; i < this.value.length; i++) {
object.value.push(this.value[i].toJSON());
}return object;
}
//**********************************************************************************
}], [{
key: "blockName",
value: function blockName() {
return "ConstructedValueBlock";
}
}]);
return LocalConstructedValueBlock;
}(LocalValueBlock);
//**************************************************************************************
var Constructed = exports.Constructed = function (_BaseBlock2) {
_inherits(Constructed, _BaseBlock2);
//**********************************************************************************
/**
* Constructor for "Constructed" class
* @param {Object} [parameters={}]
*/
function Constructed() {
var parameters = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
_classCallCheck(this, Constructed);
var _this9 = _possibleConstructorReturn(this, (Constructed.__proto__ || Object.getPrototypeOf(Constructed)).call(this, parameters, LocalConstructedValueBlock));
_this9.i