Upload via GUI (7543 Dateien)
This commit is contained in:
+7
@@ -0,0 +1,7 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.AsnSchemaValidationError = void 0;
|
||||
class AsnSchemaValidationError extends Error {
|
||||
schemas = [];
|
||||
}
|
||||
exports.AsnSchemaValidationError = AsnSchemaValidationError;
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.isConvertible = isConvertible;
|
||||
exports.isTypeOfArray = isTypeOfArray;
|
||||
exports.isArrayEqual = isArrayEqual;
|
||||
function isConvertible(target) {
|
||||
if (typeof target === "function" && target.prototype) {
|
||||
if (target.prototype.toASN && target.prototype.fromASN) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return isConvertible(target.prototype);
|
||||
}
|
||||
}
|
||||
else {
|
||||
return !!(target && typeof target === "object" && "toASN" in target && "fromASN" in target);
|
||||
}
|
||||
}
|
||||
function isTypeOfArray(target) {
|
||||
if (target) {
|
||||
const proto = Object.getPrototypeOf(target);
|
||||
if (proto?.prototype?.constructor === Array) {
|
||||
return true;
|
||||
}
|
||||
return isTypeOfArray(proto);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function isArrayEqual(bytes1, bytes2) {
|
||||
if (!(bytes1 && bytes2)) {
|
||||
return false;
|
||||
}
|
||||
if (bytes1.byteLength !== bytes2.byteLength) {
|
||||
return false;
|
||||
}
|
||||
const b1 = new Uint8Array(bytes1);
|
||||
const b2 = new Uint8Array(bytes2);
|
||||
for (let i = 0; i < bytes1.byteLength; i++) {
|
||||
if (b1[i] !== b2[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.AsnSerializer = exports.AsnParser = exports.AsnPropTypes = exports.AsnTypeTypes = exports.AsnSetType = exports.AsnSequenceType = exports.AsnChoiceType = exports.AsnType = exports.AsnProp = void 0;
|
||||
const tslib_1 = require("tslib");
|
||||
tslib_1.__exportStar(require("./converters"), exports);
|
||||
tslib_1.__exportStar(require("./types/index"), exports);
|
||||
var decorators_1 = require("./decorators");
|
||||
Object.defineProperty(exports, "AsnProp", { enumerable: true, get: function () { return decorators_1.AsnProp; } });
|
||||
Object.defineProperty(exports, "AsnType", { enumerable: true, get: function () { return decorators_1.AsnType; } });
|
||||
Object.defineProperty(exports, "AsnChoiceType", { enumerable: true, get: function () { return decorators_1.AsnChoiceType; } });
|
||||
Object.defineProperty(exports, "AsnSequenceType", { enumerable: true, get: function () { return decorators_1.AsnSequenceType; } });
|
||||
Object.defineProperty(exports, "AsnSetType", { enumerable: true, get: function () { return decorators_1.AsnSetType; } });
|
||||
var enums_1 = require("./enums");
|
||||
Object.defineProperty(exports, "AsnTypeTypes", { enumerable: true, get: function () { return enums_1.AsnTypeTypes; } });
|
||||
Object.defineProperty(exports, "AsnPropTypes", { enumerable: true, get: function () { return enums_1.AsnPropTypes; } });
|
||||
var parser_1 = require("./parser");
|
||||
Object.defineProperty(exports, "AsnParser", { enumerable: true, get: function () { return parser_1.AsnParser; } });
|
||||
var serializer_1 = require("./serializer");
|
||||
Object.defineProperty(exports, "AsnSerializer", { enumerable: true, get: function () { return serializer_1.AsnSerializer; } });
|
||||
tslib_1.__exportStar(require("./errors"), exports);
|
||||
tslib_1.__exportStar(require("./objects"), exports);
|
||||
tslib_1.__exportStar(require("./convert"), exports);
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.AsnArray = void 0;
|
||||
class AsnArray extends Array {
|
||||
constructor(items = []) {
|
||||
if (typeof items === "number") {
|
||||
super(items);
|
||||
}
|
||||
else {
|
||||
super();
|
||||
for (const item of items) {
|
||||
this.push(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.AsnArray = AsnArray;
|
||||
+313
@@ -0,0 +1,313 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.AsnParser = void 0;
|
||||
const tslib_1 = require("tslib");
|
||||
const asn1js = tslib_1.__importStar(require("asn1js"));
|
||||
const utils_1 = require("@peculiar/utils");
|
||||
const enums_1 = require("./enums");
|
||||
const converters = tslib_1.__importStar(require("./converters"));
|
||||
const errors_1 = require("./errors");
|
||||
const helper_1 = require("./helper");
|
||||
const storage_1 = require("./storage");
|
||||
class AsnParser {
|
||||
static parse(data, target, options) {
|
||||
const asn1Parsed = asn1js.fromBER((0, utils_1.toArrayBuffer)(data), options?.berOptions);
|
||||
if (asn1Parsed.result.error) {
|
||||
throw new Error(asn1Parsed.result.error);
|
||||
}
|
||||
const res = this.fromASN(asn1Parsed.result, target, options);
|
||||
return res;
|
||||
}
|
||||
static fromASN(asn1Schema, target, options) {
|
||||
try {
|
||||
if ((0, helper_1.isConvertible)(target)) {
|
||||
const value = new target();
|
||||
return value.fromASN(asn1Schema);
|
||||
}
|
||||
const schema = storage_1.schemaStorage.get(target);
|
||||
storage_1.schemaStorage.cache(target);
|
||||
let targetSchema = schema.schema;
|
||||
const choiceResult = this.handleChoiceTypes(asn1Schema, schema, target, targetSchema, options);
|
||||
if (choiceResult?.result) {
|
||||
return choiceResult.result;
|
||||
}
|
||||
if (choiceResult?.targetSchema) {
|
||||
targetSchema = choiceResult.targetSchema;
|
||||
}
|
||||
const sequenceResult = this.handleSequenceTypes(asn1Schema, schema, target, targetSchema);
|
||||
const res = new target();
|
||||
if ((0, helper_1.isTypeOfArray)(target)) {
|
||||
return this.handleArrayTypes(asn1Schema, schema, target, options);
|
||||
}
|
||||
this.processSchemaItems(schema, sequenceResult, res, options);
|
||||
return res;
|
||||
}
|
||||
catch (error) {
|
||||
if (error instanceof errors_1.AsnSchemaValidationError) {
|
||||
error.schemas.push(target.name);
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
static handleChoiceTypes(asn1Schema, schema, target, targetSchema, options) {
|
||||
if (asn1Schema.constructor === asn1js.Constructed && schema.type === enums_1.AsnTypeTypes.Choice && asn1Schema.idBlock.tagClass === 3) {
|
||||
for (const key in schema.items) {
|
||||
const schemaItem = schema.items[key];
|
||||
if (schemaItem.context === asn1Schema.idBlock.tagNumber && schemaItem.implicit) {
|
||||
if (typeof schemaItem.type === "function" && storage_1.schemaStorage.has(schemaItem.type)) {
|
||||
const fieldSchema = storage_1.schemaStorage.get(schemaItem.type);
|
||||
if (fieldSchema && fieldSchema.type === enums_1.AsnTypeTypes.Sequence) {
|
||||
const newSeq = new asn1js.Sequence();
|
||||
if ("value" in asn1Schema.valueBlock && Array.isArray(asn1Schema.valueBlock.value) && "value" in newSeq.valueBlock) {
|
||||
newSeq.valueBlock.value = asn1Schema.valueBlock.value;
|
||||
const fieldValue = this.fromASN(newSeq, schemaItem.type, options);
|
||||
const res = new target();
|
||||
res[key] = fieldValue;
|
||||
return { result: res };
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (asn1Schema.constructor === asn1js.Constructed && schema.type !== enums_1.AsnTypeTypes.Choice) {
|
||||
const newTargetSchema = new asn1js.Constructed({
|
||||
idBlock: {
|
||||
tagClass: 3,
|
||||
tagNumber: asn1Schema.idBlock.tagNumber,
|
||||
},
|
||||
value: schema.schema.valueBlock.value,
|
||||
});
|
||||
for (const key in schema.items) {
|
||||
delete asn1Schema[key];
|
||||
}
|
||||
return { targetSchema: newTargetSchema };
|
||||
}
|
||||
return null;
|
||||
}
|
||||
static handleSequenceTypes(asn1Schema, schema, target, targetSchema) {
|
||||
if (schema.type === enums_1.AsnTypeTypes.Sequence) {
|
||||
const asn1ComparedSchema = asn1js.compareSchema({}, asn1Schema, targetSchema);
|
||||
if (!asn1ComparedSchema.verified) {
|
||||
throw new errors_1.AsnSchemaValidationError(`Data does not match to ${target.name} ASN1 schema.${asn1ComparedSchema.result.error ? ` ${asn1ComparedSchema.result.error}` : ""}`);
|
||||
}
|
||||
return asn1ComparedSchema;
|
||||
}
|
||||
else {
|
||||
const asn1ComparedSchema = asn1js.compareSchema({}, asn1Schema, targetSchema);
|
||||
if (!asn1ComparedSchema.verified) {
|
||||
throw new errors_1.AsnSchemaValidationError(`Data does not match to ${target.name} ASN1 schema.${asn1ComparedSchema.result.error ? ` ${asn1ComparedSchema.result.error}` : ""}`);
|
||||
}
|
||||
return asn1ComparedSchema;
|
||||
}
|
||||
}
|
||||
static processRepeatedField(asn1Elements, asn1Index, schemaItem) {
|
||||
let elementsToProcess = asn1Elements.slice(asn1Index);
|
||||
if (elementsToProcess.length === 1 && elementsToProcess[0].constructor.name === "Sequence") {
|
||||
const seq = elementsToProcess[0];
|
||||
if (seq.valueBlock && seq.valueBlock.value && Array.isArray(seq.valueBlock.value)) {
|
||||
elementsToProcess = seq.valueBlock.value;
|
||||
}
|
||||
}
|
||||
if (typeof schemaItem.type === "number") {
|
||||
const converter = converters.defaultConverter(schemaItem.type);
|
||||
if (!converter)
|
||||
throw new Error(`No converter for ASN.1 type ${schemaItem.type}`);
|
||||
return elementsToProcess
|
||||
.filter((el) => el && el.valueBlock)
|
||||
.map((el) => {
|
||||
try {
|
||||
return converter.fromASN(el);
|
||||
}
|
||||
catch {
|
||||
return undefined;
|
||||
}
|
||||
})
|
||||
.filter((v) => v !== undefined);
|
||||
}
|
||||
else {
|
||||
return elementsToProcess
|
||||
.filter((el) => el && el.valueBlock)
|
||||
.map((el) => {
|
||||
try {
|
||||
return this.fromASN(el, schemaItem.type);
|
||||
}
|
||||
catch {
|
||||
return undefined;
|
||||
}
|
||||
})
|
||||
.filter((v) => v !== undefined);
|
||||
}
|
||||
}
|
||||
static processPrimitiveField(asn1Element, schemaItem) {
|
||||
const converter = converters.defaultConverter(schemaItem.type);
|
||||
if (!converter)
|
||||
throw new Error(`No converter for ASN.1 type ${schemaItem.type}`);
|
||||
return converter.fromASN(asn1Element);
|
||||
}
|
||||
static isOptionalChoiceField(schemaItem) {
|
||||
return (schemaItem.optional &&
|
||||
typeof schemaItem.type === "function" &&
|
||||
storage_1.schemaStorage.has(schemaItem.type) &&
|
||||
storage_1.schemaStorage.get(schemaItem.type).type === enums_1.AsnTypeTypes.Choice);
|
||||
}
|
||||
static processOptionalChoiceField(asn1Element, schemaItem) {
|
||||
try {
|
||||
const value = this.fromASN(asn1Element, schemaItem.type);
|
||||
return {
|
||||
processed: true,
|
||||
value,
|
||||
};
|
||||
}
|
||||
catch (err) {
|
||||
if (err instanceof errors_1.AsnSchemaValidationError && /Wrong values for Choice type/.test(err.message)) {
|
||||
return { processed: false };
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
static handleArrayTypes(asn1Schema, schema, target, options) {
|
||||
if (!("value" in asn1Schema.valueBlock && Array.isArray(asn1Schema.valueBlock.value))) {
|
||||
throw new Error("Cannot get items from the ASN.1 parsed value. ASN.1 object is not constructed.");
|
||||
}
|
||||
const itemType = schema.itemType;
|
||||
if (typeof itemType === "number") {
|
||||
const converter = converters.defaultConverter(itemType);
|
||||
if (!converter) {
|
||||
throw new Error(`Cannot get default converter for array item of ${target.name} ASN1 schema`);
|
||||
}
|
||||
return target.from(asn1Schema.valueBlock.value, (element) => converter.fromASN(element));
|
||||
}
|
||||
else {
|
||||
return target.from(asn1Schema.valueBlock.value, (element) => this.fromASN(element, itemType, options));
|
||||
}
|
||||
}
|
||||
static processSchemaItems(schema, asn1ComparedSchema, res, options) {
|
||||
for (const key in schema.items) {
|
||||
const asn1SchemaValue = asn1ComparedSchema.result[key];
|
||||
if (!asn1SchemaValue) {
|
||||
continue;
|
||||
}
|
||||
const schemaItem = schema.items[key];
|
||||
const schemaItemType = schemaItem.type;
|
||||
let parsedValue;
|
||||
if (typeof schemaItemType === "number" || (0, helper_1.isConvertible)(schemaItemType)) {
|
||||
parsedValue = this.processPrimitiveSchemaItem(asn1SchemaValue, schemaItem, schemaItemType, options);
|
||||
}
|
||||
else {
|
||||
parsedValue = this.processComplexSchemaItem(asn1SchemaValue, schemaItem, schemaItemType, options);
|
||||
}
|
||||
if (parsedValue && typeof parsedValue === "object" && "value" in parsedValue && "raw" in parsedValue) {
|
||||
res[key] = parsedValue.value;
|
||||
res[`${key}Raw`] = parsedValue.raw;
|
||||
}
|
||||
else {
|
||||
res[key] = parsedValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
static processPrimitiveSchemaItem(asn1SchemaValue, schemaItem, schemaItemType, options) {
|
||||
const converter = schemaItem.converter ?? ((0, helper_1.isConvertible)(schemaItemType) ? new schemaItemType() : null);
|
||||
if (!converter) {
|
||||
throw new Error("Converter is empty");
|
||||
}
|
||||
if (schemaItem.repeated) {
|
||||
return this.processRepeatedPrimitiveItem(asn1SchemaValue, schemaItem, converter, options);
|
||||
}
|
||||
else {
|
||||
return this.processSinglePrimitiveItem(asn1SchemaValue, schemaItem, schemaItemType, converter, options);
|
||||
}
|
||||
}
|
||||
static processRepeatedPrimitiveItem(asn1SchemaValue, schemaItem, converter, options) {
|
||||
if (schemaItem.implicit) {
|
||||
const Container = schemaItem.repeated === "sequence" ? asn1js.Sequence : asn1js.Set;
|
||||
const newItem = new Container();
|
||||
newItem.valueBlock = asn1SchemaValue.valueBlock;
|
||||
const newItemAsn = asn1js.fromBER(newItem.toBER(false), options?.berOptions);
|
||||
if (newItemAsn.offset === -1) {
|
||||
throw new Error(`Cannot parse the child item. ${newItemAsn.result.error}`);
|
||||
}
|
||||
if (!("value" in newItemAsn.result.valueBlock && Array.isArray(newItemAsn.result.valueBlock.value))) {
|
||||
throw new Error("Cannot get items from the ASN.1 parsed value. ASN.1 object is not constructed.");
|
||||
}
|
||||
const value = newItemAsn.result.valueBlock.value;
|
||||
return Array.from(value, (element) => converter.fromASN(element));
|
||||
}
|
||||
else {
|
||||
return Array.from(asn1SchemaValue, (element) => converter.fromASN(element));
|
||||
}
|
||||
}
|
||||
static processSinglePrimitiveItem(asn1SchemaValue, schemaItem, schemaItemType, converter, options) {
|
||||
let value = asn1SchemaValue;
|
||||
if (schemaItem.implicit) {
|
||||
let newItem;
|
||||
if ((0, helper_1.isConvertible)(schemaItemType)) {
|
||||
newItem = new schemaItemType().toSchema("");
|
||||
}
|
||||
else {
|
||||
const Asn1TypeName = enums_1.AsnPropTypes[schemaItemType];
|
||||
const Asn1Type = asn1js[Asn1TypeName];
|
||||
if (!Asn1Type) {
|
||||
throw new Error(`Cannot get '${Asn1TypeName}' class from asn1js module`);
|
||||
}
|
||||
newItem = new Asn1Type();
|
||||
}
|
||||
newItem.valueBlock = value.valueBlock;
|
||||
value = asn1js.fromBER(newItem.toBER(false), options?.berOptions).result;
|
||||
}
|
||||
return converter.fromASN(value);
|
||||
}
|
||||
static processComplexSchemaItem(asn1SchemaValue, schemaItem, schemaItemType, options) {
|
||||
if (schemaItem.repeated) {
|
||||
if (!Array.isArray(asn1SchemaValue)) {
|
||||
throw new Error("Cannot get list of items from the ASN.1 parsed value. ASN.1 value should be iterable.");
|
||||
}
|
||||
return Array.from(asn1SchemaValue, (element) => this.fromASN(element, schemaItemType, options));
|
||||
}
|
||||
else {
|
||||
const valueToProcess = this.handleImplicitTagging(asn1SchemaValue, schemaItem, schemaItemType);
|
||||
if (this.isOptionalChoiceField(schemaItem)) {
|
||||
try {
|
||||
return this.fromASN(valueToProcess, schemaItemType, options);
|
||||
}
|
||||
catch (err) {
|
||||
if (err instanceof errors_1.AsnSchemaValidationError && /Wrong values for Choice type/.test(err.message)) {
|
||||
return undefined;
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
else {
|
||||
const parsedValue = this.fromASN(valueToProcess, schemaItemType, options);
|
||||
if (schemaItem.raw) {
|
||||
return {
|
||||
value: parsedValue,
|
||||
raw: asn1SchemaValue.valueBeforeDecodeView,
|
||||
};
|
||||
}
|
||||
return parsedValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
static handleImplicitTagging(asn1SchemaValue, schemaItem, schemaItemType) {
|
||||
if (schemaItem.implicit && typeof schemaItem.context === "number") {
|
||||
const schema = storage_1.schemaStorage.get(schemaItemType);
|
||||
if (schema.type === enums_1.AsnTypeTypes.Sequence) {
|
||||
const newSeq = new asn1js.Sequence();
|
||||
if ("value" in asn1SchemaValue.valueBlock && Array.isArray(asn1SchemaValue.valueBlock.value) && "value" in newSeq.valueBlock) {
|
||||
newSeq.valueBlock.value = asn1SchemaValue.valueBlock.value;
|
||||
return newSeq;
|
||||
}
|
||||
}
|
||||
else if (schema.type === enums_1.AsnTypeTypes.Set) {
|
||||
const newSet = new asn1js.Set();
|
||||
if ("value" in asn1SchemaValue.valueBlock && Array.isArray(asn1SchemaValue.valueBlock.value) && "value" in newSet.valueBlock) {
|
||||
newSet.valueBlock.value = asn1SchemaValue.valueBlock.value;
|
||||
return newSet;
|
||||
}
|
||||
}
|
||||
}
|
||||
return asn1SchemaValue;
|
||||
}
|
||||
}
|
||||
exports.AsnParser = AsnParser;
|
||||
+165
@@ -0,0 +1,165 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.AsnSchemaStorage = void 0;
|
||||
const tslib_1 = require("tslib");
|
||||
const asn1js = tslib_1.__importStar(require("asn1js"));
|
||||
const enums_1 = require("./enums");
|
||||
const helper_1 = require("./helper");
|
||||
class AsnSchemaStorage {
|
||||
items = new WeakMap();
|
||||
has(target) {
|
||||
return this.items.has(target);
|
||||
}
|
||||
get(target, checkSchema = false) {
|
||||
const schema = this.items.get(target);
|
||||
if (!schema) {
|
||||
throw new Error(`Cannot get schema for '${target.prototype.constructor.name}' target`);
|
||||
}
|
||||
if (checkSchema && !schema.schema) {
|
||||
throw new Error(`Schema '${target.prototype.constructor.name}' doesn't contain ASN.1 schema. Call 'AsnSchemaStorage.cache'.`);
|
||||
}
|
||||
return schema;
|
||||
}
|
||||
cache(target) {
|
||||
const schema = this.get(target);
|
||||
if (!schema.schema) {
|
||||
schema.schema = this.create(target, true);
|
||||
}
|
||||
}
|
||||
createDefault(target) {
|
||||
const schema = {
|
||||
type: enums_1.AsnTypeTypes.Sequence,
|
||||
items: {},
|
||||
};
|
||||
const parentSchema = this.findParentSchema(target);
|
||||
if (parentSchema) {
|
||||
Object.assign(schema, parentSchema);
|
||||
schema.items = Object.assign({}, schema.items, parentSchema.items);
|
||||
}
|
||||
return schema;
|
||||
}
|
||||
create(target, useNames) {
|
||||
const schema = this.items.get(target) || this.createDefault(target);
|
||||
const asn1Value = [];
|
||||
for (const key in schema.items) {
|
||||
const item = schema.items[key];
|
||||
const name = useNames ? key : "";
|
||||
let asn1Item;
|
||||
if (typeof item.type === "number") {
|
||||
const Asn1TypeName = enums_1.AsnPropTypes[item.type];
|
||||
const Asn1Type = asn1js[Asn1TypeName];
|
||||
if (!Asn1Type) {
|
||||
throw new Error(`Cannot get ASN1 class by name '${Asn1TypeName}'`);
|
||||
}
|
||||
asn1Item = new Asn1Type({ name });
|
||||
}
|
||||
else if ((0, helper_1.isConvertible)(item.type)) {
|
||||
const instance = new item.type();
|
||||
asn1Item = instance.toSchema(name);
|
||||
}
|
||||
else if (item.optional) {
|
||||
const itemSchema = this.get(item.type);
|
||||
if (itemSchema.type === enums_1.AsnTypeTypes.Choice) {
|
||||
asn1Item = new asn1js.Any({ name });
|
||||
}
|
||||
else {
|
||||
asn1Item = this.create(item.type, false);
|
||||
asn1Item.name = name;
|
||||
}
|
||||
}
|
||||
else {
|
||||
asn1Item = new asn1js.Any({ name });
|
||||
}
|
||||
const optional = !!item.optional || item.defaultValue !== undefined;
|
||||
if (item.repeated) {
|
||||
asn1Item.name = "";
|
||||
const Container = item.repeated === "set" ? asn1js.Set : asn1js.Sequence;
|
||||
asn1Item = new Container({
|
||||
name: "",
|
||||
value: [
|
||||
new asn1js.Repeated({
|
||||
name,
|
||||
value: asn1Item,
|
||||
}),
|
||||
],
|
||||
});
|
||||
}
|
||||
if (item.context !== null && item.context !== undefined) {
|
||||
if (item.implicit) {
|
||||
if (typeof item.type === "number" || (0, helper_1.isConvertible)(item.type)) {
|
||||
const Container = item.repeated ? asn1js.Constructed : asn1js.Primitive;
|
||||
asn1Value.push(new Container({
|
||||
name,
|
||||
optional,
|
||||
idBlock: {
|
||||
tagClass: 3,
|
||||
tagNumber: item.context,
|
||||
},
|
||||
}));
|
||||
}
|
||||
else {
|
||||
this.cache(item.type);
|
||||
const isRepeated = !!item.repeated;
|
||||
let value = !isRepeated ? this.get(item.type, true).schema : asn1Item;
|
||||
value = "valueBlock" in value ? value.valueBlock.value : value.value;
|
||||
asn1Value.push(new asn1js.Constructed({
|
||||
name: !isRepeated ? name : "",
|
||||
optional,
|
||||
idBlock: {
|
||||
tagClass: 3,
|
||||
tagNumber: item.context,
|
||||
},
|
||||
value: value,
|
||||
}));
|
||||
}
|
||||
}
|
||||
else {
|
||||
asn1Value.push(new asn1js.Constructed({
|
||||
optional,
|
||||
idBlock: {
|
||||
tagClass: 3,
|
||||
tagNumber: item.context,
|
||||
},
|
||||
value: [asn1Item],
|
||||
}));
|
||||
}
|
||||
}
|
||||
else {
|
||||
asn1Item.optional = optional;
|
||||
asn1Value.push(asn1Item);
|
||||
}
|
||||
}
|
||||
switch (schema.type) {
|
||||
case enums_1.AsnTypeTypes.Sequence:
|
||||
return new asn1js.Sequence({
|
||||
value: asn1Value,
|
||||
name: "",
|
||||
});
|
||||
case enums_1.AsnTypeTypes.Set:
|
||||
return new asn1js.Set({
|
||||
value: asn1Value,
|
||||
name: "",
|
||||
});
|
||||
case enums_1.AsnTypeTypes.Choice:
|
||||
return new asn1js.Choice({
|
||||
value: asn1Value,
|
||||
name: "",
|
||||
});
|
||||
default:
|
||||
throw new Error("Unsupported ASN1 type in use");
|
||||
}
|
||||
}
|
||||
set(target, schema) {
|
||||
this.items.set(target, schema);
|
||||
return this;
|
||||
}
|
||||
findParentSchema(target) {
|
||||
const parent = Object.getPrototypeOf(target);
|
||||
if (parent) {
|
||||
const schema = this.items.get(parent);
|
||||
return schema || this.findParentSchema(parent);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
exports.AsnSchemaStorage = AsnSchemaStorage;
|
||||
+150
@@ -0,0 +1,150 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.AsnSerializer = void 0;
|
||||
const tslib_1 = require("tslib");
|
||||
const asn1js = tslib_1.__importStar(require("asn1js"));
|
||||
const utils_1 = require("@peculiar/utils");
|
||||
const converters = tslib_1.__importStar(require("./converters"));
|
||||
const enums_1 = require("./enums");
|
||||
const helper_1 = require("./helper");
|
||||
const storage_1 = require("./storage");
|
||||
class AsnSerializer {
|
||||
static serialize(obj) {
|
||||
if (obj instanceof asn1js.BaseBlock) {
|
||||
return obj.toBER(false);
|
||||
}
|
||||
return this.toASN(obj).toBER(false);
|
||||
}
|
||||
static toASN(obj) {
|
||||
if (obj && typeof obj === "object" && (0, helper_1.isConvertible)(obj)) {
|
||||
return obj.toASN();
|
||||
}
|
||||
if (!(obj && typeof obj === "object")) {
|
||||
throw new TypeError("Parameter 1 should be type of Object.");
|
||||
}
|
||||
const target = obj.constructor;
|
||||
const schema = storage_1.schemaStorage.get(target);
|
||||
storage_1.schemaStorage.cache(target);
|
||||
let asn1Value = [];
|
||||
if (schema.itemType) {
|
||||
if (!Array.isArray(obj)) {
|
||||
throw new TypeError("Parameter 1 should be type of Array.");
|
||||
}
|
||||
if (typeof schema.itemType === "number") {
|
||||
const converter = converters.defaultConverter(schema.itemType);
|
||||
if (!converter) {
|
||||
throw new Error(`Cannot get default converter for array item of ${target.name} ASN1 schema`);
|
||||
}
|
||||
asn1Value = obj.map((o) => converter.toASN(o));
|
||||
}
|
||||
else {
|
||||
asn1Value = obj.map((o) => this.toAsnItem({ type: schema.itemType }, "[]", target, o));
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (const key in schema.items) {
|
||||
const schemaItem = schema.items[key];
|
||||
const objProp = obj[key];
|
||||
if (objProp === undefined ||
|
||||
schemaItem.defaultValue === objProp ||
|
||||
(typeof schemaItem.defaultValue === "object" && typeof objProp === "object" && (0, helper_1.isArrayEqual)(this.serialize(schemaItem.defaultValue), this.serialize(objProp)))) {
|
||||
continue;
|
||||
}
|
||||
const asn1Item = AsnSerializer.toAsnItem(schemaItem, key, target, objProp);
|
||||
if (typeof schemaItem.context === "number") {
|
||||
if (schemaItem.implicit) {
|
||||
if (!schemaItem.repeated && (typeof schemaItem.type === "number" || (0, helper_1.isConvertible)(schemaItem.type))) {
|
||||
const value = {};
|
||||
value.valueHex = asn1Item instanceof asn1js.Null ? (0, utils_1.toArrayBuffer)(asn1Item.valueBeforeDecodeView) : asn1Item.valueBlock.toBER();
|
||||
asn1Value.push(new asn1js.Primitive({
|
||||
optional: schemaItem.optional,
|
||||
idBlock: {
|
||||
tagClass: 3,
|
||||
tagNumber: schemaItem.context,
|
||||
},
|
||||
...value,
|
||||
}));
|
||||
}
|
||||
else {
|
||||
asn1Value.push(new asn1js.Constructed({
|
||||
optional: schemaItem.optional,
|
||||
idBlock: {
|
||||
tagClass: 3,
|
||||
tagNumber: schemaItem.context,
|
||||
},
|
||||
value: asn1Item.valueBlock.value,
|
||||
}));
|
||||
}
|
||||
}
|
||||
else {
|
||||
asn1Value.push(new asn1js.Constructed({
|
||||
optional: schemaItem.optional,
|
||||
idBlock: {
|
||||
tagClass: 3,
|
||||
tagNumber: schemaItem.context,
|
||||
},
|
||||
value: [asn1Item],
|
||||
}));
|
||||
}
|
||||
}
|
||||
else if (schemaItem.repeated) {
|
||||
asn1Value = asn1Value.concat(asn1Item);
|
||||
}
|
||||
else {
|
||||
asn1Value.push(asn1Item);
|
||||
}
|
||||
}
|
||||
}
|
||||
let asnSchema;
|
||||
switch (schema.type) {
|
||||
case enums_1.AsnTypeTypes.Sequence:
|
||||
asnSchema = new asn1js.Sequence({ value: asn1Value });
|
||||
break;
|
||||
case enums_1.AsnTypeTypes.Set:
|
||||
asnSchema = new asn1js.Set({ value: asn1Value });
|
||||
break;
|
||||
case enums_1.AsnTypeTypes.Choice:
|
||||
if (!asn1Value[0]) {
|
||||
throw new Error(`Schema '${target.name}' has wrong data. Choice cannot be empty.`);
|
||||
}
|
||||
asnSchema = asn1Value[0];
|
||||
break;
|
||||
}
|
||||
return asnSchema;
|
||||
}
|
||||
static toAsnItem(schemaItem, key, target, objProp) {
|
||||
let asn1Item;
|
||||
if (typeof schemaItem.type === "number") {
|
||||
const converter = schemaItem.converter;
|
||||
if (!converter) {
|
||||
throw new Error(`Property '${key}' doesn't have converter for type ${enums_1.AsnPropTypes[schemaItem.type]} in schema '${target.name}'`);
|
||||
}
|
||||
if (schemaItem.repeated) {
|
||||
if (!Array.isArray(objProp)) {
|
||||
throw new TypeError("Parameter 'objProp' should be type of Array.");
|
||||
}
|
||||
const items = Array.from(objProp, (element) => converter.toASN(element));
|
||||
const Container = schemaItem.repeated === "sequence" ? asn1js.Sequence : asn1js.Set;
|
||||
asn1Item = new Container({ value: items });
|
||||
}
|
||||
else {
|
||||
asn1Item = converter.toASN(objProp);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (schemaItem.repeated) {
|
||||
if (!Array.isArray(objProp)) {
|
||||
throw new TypeError("Parameter 'objProp' should be type of Array.");
|
||||
}
|
||||
const items = Array.from(objProp, (element) => this.toASN(element));
|
||||
const Container = schemaItem.repeated === "sequence" ? asn1js.Sequence : asn1js.Set;
|
||||
asn1Item = new Container({ value: items });
|
||||
}
|
||||
else {
|
||||
asn1Item = this.toASN(objProp);
|
||||
}
|
||||
}
|
||||
return asn1Item;
|
||||
}
|
||||
}
|
||||
exports.AsnSerializer = AsnSerializer;
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.schemaStorage = void 0;
|
||||
const schema_1 = require("./schema");
|
||||
exports.schemaStorage = new schema_1.AsnSchemaStorage();
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.BitString = void 0;
|
||||
const tslib_1 = require("tslib");
|
||||
const asn1js = tslib_1.__importStar(require("asn1js"));
|
||||
const utils_1 = require("@peculiar/utils");
|
||||
class BitString {
|
||||
unusedBits = 0;
|
||||
value = new ArrayBuffer(0);
|
||||
constructor(params, unusedBits = 0) {
|
||||
if (params) {
|
||||
if (typeof params === "number") {
|
||||
this.fromNumber(params);
|
||||
}
|
||||
else if ((0, utils_1.isBufferSource)(params)) {
|
||||
this.unusedBits = unusedBits;
|
||||
this.value = (0, utils_1.toArrayBuffer)(params);
|
||||
}
|
||||
else {
|
||||
throw TypeError("Unsupported type of 'params' argument for BitString");
|
||||
}
|
||||
}
|
||||
}
|
||||
fromASN(asn) {
|
||||
if (!(asn instanceof asn1js.BitString)) {
|
||||
throw new TypeError("Argument 'asn' is not instance of ASN.1 BitString");
|
||||
}
|
||||
this.unusedBits = asn.valueBlock.unusedBits;
|
||||
this.value = (0, utils_1.toArrayBuffer)(asn.valueBlock.valueHex);
|
||||
return this;
|
||||
}
|
||||
toASN() {
|
||||
return new asn1js.BitString({
|
||||
unusedBits: this.unusedBits,
|
||||
valueHex: this.value,
|
||||
});
|
||||
}
|
||||
toSchema(name) {
|
||||
return new asn1js.BitString({ name });
|
||||
}
|
||||
toNumber() {
|
||||
let res = "";
|
||||
const uintArray = new Uint8Array(this.value);
|
||||
for (const octet of uintArray) {
|
||||
res += octet.toString(2).padStart(8, "0");
|
||||
}
|
||||
res = res.split("").reverse().join("");
|
||||
if (this.unusedBits) {
|
||||
res = res.slice(this.unusedBits).padStart(this.unusedBits, "0");
|
||||
}
|
||||
return parseInt(res, 2);
|
||||
}
|
||||
fromNumber(value) {
|
||||
let bits = value.toString(2);
|
||||
const octetSize = (bits.length + 7) >> 3;
|
||||
this.unusedBits = (octetSize << 3) - bits.length;
|
||||
const octets = new Uint8Array(octetSize);
|
||||
bits = bits
|
||||
.padStart(octetSize << 3, "0")
|
||||
.split("")
|
||||
.reverse()
|
||||
.join("");
|
||||
let index = 0;
|
||||
while (index < octetSize) {
|
||||
octets[index] = parseInt(bits.slice(index << 3, (index << 3) + 8), 2);
|
||||
index++;
|
||||
}
|
||||
this.value = octets.buffer;
|
||||
}
|
||||
}
|
||||
exports.BitString = BitString;
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const tslib_1 = require("tslib");
|
||||
tslib_1.__exportStar(require("./bit_string"), exports);
|
||||
tslib_1.__exportStar(require("./octet_string"), exports);
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.OctetString = void 0;
|
||||
const tslib_1 = require("tslib");
|
||||
const asn1js = tslib_1.__importStar(require("asn1js"));
|
||||
const utils_1 = require("@peculiar/utils");
|
||||
class OctetString {
|
||||
buffer;
|
||||
get byteLength() {
|
||||
return this.buffer.byteLength;
|
||||
}
|
||||
get byteOffset() {
|
||||
return 0;
|
||||
}
|
||||
constructor(param) {
|
||||
if (typeof param === "number") {
|
||||
this.buffer = new ArrayBuffer(param);
|
||||
}
|
||||
else {
|
||||
if ((0, utils_1.isBufferSource)(param)) {
|
||||
this.buffer = (0, utils_1.toArrayBuffer)(param);
|
||||
}
|
||||
else if (Array.isArray(param)) {
|
||||
this.buffer = new Uint8Array(param).buffer;
|
||||
}
|
||||
else {
|
||||
this.buffer = new ArrayBuffer(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
fromASN(asn) {
|
||||
if (!(asn instanceof asn1js.OctetString)) {
|
||||
throw new TypeError("Argument 'asn' is not instance of ASN.1 OctetString");
|
||||
}
|
||||
this.buffer = (0, utils_1.toArrayBuffer)(asn.valueBlock.valueHex);
|
||||
return this;
|
||||
}
|
||||
toASN() {
|
||||
return new asn1js.OctetString({ valueHex: this.buffer });
|
||||
}
|
||||
toSchema(name) {
|
||||
return new asn1js.OctetString({ name });
|
||||
}
|
||||
}
|
||||
exports.OctetString = OctetString;
|
||||
Reference in New Issue
Block a user