feat: 초기 프로젝트 설정 및 룰.md 파일 추가

This commit is contained in:
2025-07-28 09:53:31 +09:00
commit 09a4d38512
8165 changed files with 1021855 additions and 0 deletions

View File

@@ -0,0 +1,26 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AsnConvert = void 0;
const asn1js = require("asn1js");
const pvtsutils_1 = require("pvtsutils");
const parser_1 = require("./parser");
const serializer_1 = require("./serializer");
class AsnConvert {
static serialize(obj) {
return serializer_1.AsnSerializer.serialize(obj);
}
static parse(data, target) {
return parser_1.AsnParser.parse(data, target);
}
static toString(data) {
const buf = pvtsutils_1.BufferSourceConverter.isBufferSource(data)
? pvtsutils_1.BufferSourceConverter.toArrayBuffer(data)
: AsnConvert.serialize(data);
const asn = asn1js.fromBER(buf);
if (asn.offset === -1) {
throw new Error(`Cannot decode ASN.1 data. ${asn.result.error}`);
}
return asn.result.toString();
}
}
exports.AsnConvert = AsnConvert;

View File

@@ -0,0 +1,140 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AsnNullConverter = exports.AsnGeneralizedTimeConverter = exports.AsnUTCTimeConverter = exports.AsnCharacterStringConverter = exports.AsnGeneralStringConverter = exports.AsnVisibleStringConverter = exports.AsnGraphicStringConverter = exports.AsnIA5StringConverter = exports.AsnVideotexStringConverter = exports.AsnTeletexStringConverter = exports.AsnPrintableStringConverter = exports.AsnNumericStringConverter = exports.AsnUniversalStringConverter = exports.AsnBmpStringConverter = exports.AsnUtf8StringConverter = exports.AsnConstructedOctetStringConverter = exports.AsnOctetStringConverter = exports.AsnBooleanConverter = exports.AsnObjectIdentifierConverter = exports.AsnBitStringConverter = exports.AsnIntegerBigIntConverter = exports.AsnIntegerArrayBufferConverter = exports.AsnEnumeratedConverter = exports.AsnIntegerConverter = exports.AsnAnyConverter = void 0;
exports.defaultConverter = defaultConverter;
const asn1js = require("asn1js");
const enums_1 = require("./enums");
const index_1 = require("./types/index");
exports.AsnAnyConverter = {
fromASN: (value) => value instanceof asn1js.Null ? null : value.valueBeforeDecodeView,
toASN: (value) => {
if (value === null) {
return new asn1js.Null();
}
const schema = asn1js.fromBER(value);
if (schema.result.error) {
throw new Error(schema.result.error);
}
return schema.result;
},
};
exports.AsnIntegerConverter = {
fromASN: (value) => value.valueBlock.valueHexView.byteLength >= 4
? value.valueBlock.toString()
: value.valueBlock.valueDec,
toASN: (value) => new asn1js.Integer({ value: +value }),
};
exports.AsnEnumeratedConverter = {
fromASN: (value) => value.valueBlock.valueDec,
toASN: (value) => new asn1js.Enumerated({ value }),
};
exports.AsnIntegerArrayBufferConverter = {
fromASN: (value) => value.valueBlock.valueHexView,
toASN: (value) => new asn1js.Integer({ valueHex: value }),
};
exports.AsnIntegerBigIntConverter = {
fromASN: (value) => value.toBigInt(),
toASN: (value) => asn1js.Integer.fromBigInt(value),
};
exports.AsnBitStringConverter = {
fromASN: (value) => value.valueBlock.valueHexView,
toASN: (value) => new asn1js.BitString({ valueHex: value }),
};
exports.AsnObjectIdentifierConverter = {
fromASN: (value) => value.valueBlock.toString(),
toASN: (value) => new asn1js.ObjectIdentifier({ value }),
};
exports.AsnBooleanConverter = {
fromASN: (value) => value.valueBlock.value,
toASN: (value) => new asn1js.Boolean({ value }),
};
exports.AsnOctetStringConverter = {
fromASN: (value) => value.valueBlock.valueHexView,
toASN: (value) => new asn1js.OctetString({ valueHex: value }),
};
exports.AsnConstructedOctetStringConverter = {
fromASN: (value) => new index_1.OctetString(value.getValue()),
toASN: (value) => value.toASN(),
};
function createStringConverter(Asn1Type) {
return {
fromASN: (value) => value.valueBlock.value,
toASN: (value) => new Asn1Type({ value }),
};
}
exports.AsnUtf8StringConverter = createStringConverter(asn1js.Utf8String);
exports.AsnBmpStringConverter = createStringConverter(asn1js.BmpString);
exports.AsnUniversalStringConverter = createStringConverter(asn1js.UniversalString);
exports.AsnNumericStringConverter = createStringConverter(asn1js.NumericString);
exports.AsnPrintableStringConverter = createStringConverter(asn1js.PrintableString);
exports.AsnTeletexStringConverter = createStringConverter(asn1js.TeletexString);
exports.AsnVideotexStringConverter = createStringConverter(asn1js.VideotexString);
exports.AsnIA5StringConverter = createStringConverter(asn1js.IA5String);
exports.AsnGraphicStringConverter = createStringConverter(asn1js.GraphicString);
exports.AsnVisibleStringConverter = createStringConverter(asn1js.VisibleString);
exports.AsnGeneralStringConverter = createStringConverter(asn1js.GeneralString);
exports.AsnCharacterStringConverter = createStringConverter(asn1js.CharacterString);
exports.AsnUTCTimeConverter = {
fromASN: (value) => value.toDate(),
toASN: (value) => new asn1js.UTCTime({ valueDate: value }),
};
exports.AsnGeneralizedTimeConverter = {
fromASN: (value) => value.toDate(),
toASN: (value) => new asn1js.GeneralizedTime({ valueDate: value }),
};
exports.AsnNullConverter = {
fromASN: () => null,
toASN: () => {
return new asn1js.Null();
},
};
function defaultConverter(type) {
switch (type) {
case enums_1.AsnPropTypes.Any:
return exports.AsnAnyConverter;
case enums_1.AsnPropTypes.BitString:
return exports.AsnBitStringConverter;
case enums_1.AsnPropTypes.BmpString:
return exports.AsnBmpStringConverter;
case enums_1.AsnPropTypes.Boolean:
return exports.AsnBooleanConverter;
case enums_1.AsnPropTypes.CharacterString:
return exports.AsnCharacterStringConverter;
case enums_1.AsnPropTypes.Enumerated:
return exports.AsnEnumeratedConverter;
case enums_1.AsnPropTypes.GeneralString:
return exports.AsnGeneralStringConverter;
case enums_1.AsnPropTypes.GeneralizedTime:
return exports.AsnGeneralizedTimeConverter;
case enums_1.AsnPropTypes.GraphicString:
return exports.AsnGraphicStringConverter;
case enums_1.AsnPropTypes.IA5String:
return exports.AsnIA5StringConverter;
case enums_1.AsnPropTypes.Integer:
return exports.AsnIntegerConverter;
case enums_1.AsnPropTypes.Null:
return exports.AsnNullConverter;
case enums_1.AsnPropTypes.NumericString:
return exports.AsnNumericStringConverter;
case enums_1.AsnPropTypes.ObjectIdentifier:
return exports.AsnObjectIdentifierConverter;
case enums_1.AsnPropTypes.OctetString:
return exports.AsnOctetStringConverter;
case enums_1.AsnPropTypes.PrintableString:
return exports.AsnPrintableStringConverter;
case enums_1.AsnPropTypes.TeletexString:
return exports.AsnTeletexStringConverter;
case enums_1.AsnPropTypes.UTCTime:
return exports.AsnUTCTimeConverter;
case enums_1.AsnPropTypes.UniversalString:
return exports.AsnUniversalStringConverter;
case enums_1.AsnPropTypes.Utf8String:
return exports.AsnUtf8StringConverter;
case enums_1.AsnPropTypes.VideotexString:
return exports.AsnVideotexStringConverter;
case enums_1.AsnPropTypes.VisibleString:
return exports.AsnVisibleStringConverter;
default:
return null;
}
}

View File

@@ -0,0 +1,44 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AsnProp = exports.AsnSequenceType = exports.AsnSetType = exports.AsnChoiceType = exports.AsnType = void 0;
const converters = require("./converters");
const enums_1 = require("./enums");
const storage_1 = require("./storage");
const AsnType = (options) => (target) => {
let schema;
if (!storage_1.schemaStorage.has(target)) {
schema = storage_1.schemaStorage.createDefault(target);
storage_1.schemaStorage.set(target, schema);
}
else {
schema = storage_1.schemaStorage.get(target);
}
Object.assign(schema, options);
};
exports.AsnType = AsnType;
const AsnChoiceType = () => (0, exports.AsnType)({ type: enums_1.AsnTypeTypes.Choice });
exports.AsnChoiceType = AsnChoiceType;
const AsnSetType = (options) => (0, exports.AsnType)({ type: enums_1.AsnTypeTypes.Set, ...options });
exports.AsnSetType = AsnSetType;
const AsnSequenceType = (options) => (0, exports.AsnType)({ type: enums_1.AsnTypeTypes.Sequence, ...options });
exports.AsnSequenceType = AsnSequenceType;
const AsnProp = (options) => (target, propertyKey) => {
let schema;
if (!storage_1.schemaStorage.has(target.constructor)) {
schema = storage_1.schemaStorage.createDefault(target.constructor);
storage_1.schemaStorage.set(target.constructor, schema);
}
else {
schema = storage_1.schemaStorage.get(target.constructor);
}
const copyOptions = Object.assign({}, options);
if (typeof copyOptions.type === "number" && !copyOptions.converter) {
const defaultConverter = converters.defaultConverter(options.type);
if (!defaultConverter) {
throw new Error(`Cannot get default converter for property '${propertyKey}' of ${target.constructor.name}`);
}
copyOptions.converter = defaultConverter;
}
schema.items[propertyKey] = copyOptions;
};
exports.AsnProp = AsnProp;

View File

@@ -0,0 +1,39 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AsnPropTypes = exports.AsnTypeTypes = void 0;
var AsnTypeTypes;
(function (AsnTypeTypes) {
AsnTypeTypes[AsnTypeTypes["Sequence"] = 0] = "Sequence";
AsnTypeTypes[AsnTypeTypes["Set"] = 1] = "Set";
AsnTypeTypes[AsnTypeTypes["Choice"] = 2] = "Choice";
})(AsnTypeTypes || (exports.AsnTypeTypes = AsnTypeTypes = {}));
var AsnPropTypes;
(function (AsnPropTypes) {
AsnPropTypes[AsnPropTypes["Any"] = 1] = "Any";
AsnPropTypes[AsnPropTypes["Boolean"] = 2] = "Boolean";
AsnPropTypes[AsnPropTypes["OctetString"] = 3] = "OctetString";
AsnPropTypes[AsnPropTypes["BitString"] = 4] = "BitString";
AsnPropTypes[AsnPropTypes["Integer"] = 5] = "Integer";
AsnPropTypes[AsnPropTypes["Enumerated"] = 6] = "Enumerated";
AsnPropTypes[AsnPropTypes["ObjectIdentifier"] = 7] = "ObjectIdentifier";
AsnPropTypes[AsnPropTypes["Utf8String"] = 8] = "Utf8String";
AsnPropTypes[AsnPropTypes["BmpString"] = 9] = "BmpString";
AsnPropTypes[AsnPropTypes["UniversalString"] = 10] = "UniversalString";
AsnPropTypes[AsnPropTypes["NumericString"] = 11] = "NumericString";
AsnPropTypes[AsnPropTypes["PrintableString"] = 12] = "PrintableString";
AsnPropTypes[AsnPropTypes["TeletexString"] = 13] = "TeletexString";
AsnPropTypes[AsnPropTypes["VideotexString"] = 14] = "VideotexString";
AsnPropTypes[AsnPropTypes["IA5String"] = 15] = "IA5String";
AsnPropTypes[AsnPropTypes["GraphicString"] = 16] = "GraphicString";
AsnPropTypes[AsnPropTypes["VisibleString"] = 17] = "VisibleString";
AsnPropTypes[AsnPropTypes["GeneralString"] = 18] = "GeneralString";
AsnPropTypes[AsnPropTypes["CharacterString"] = 19] = "CharacterString";
AsnPropTypes[AsnPropTypes["UTCTime"] = 20] = "UTCTime";
AsnPropTypes[AsnPropTypes["GeneralizedTime"] = 21] = "GeneralizedTime";
AsnPropTypes[AsnPropTypes["DATE"] = 22] = "DATE";
AsnPropTypes[AsnPropTypes["TimeOfDay"] = 23] = "TimeOfDay";
AsnPropTypes[AsnPropTypes["DateTime"] = 24] = "DateTime";
AsnPropTypes[AsnPropTypes["Duration"] = 25] = "Duration";
AsnPropTypes[AsnPropTypes["TIME"] = 26] = "TIME";
AsnPropTypes[AsnPropTypes["Null"] = 27] = "Null";
})(AsnPropTypes || (exports.AsnPropTypes = AsnPropTypes = {}));

View File

@@ -0,0 +1,4 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
tslib_1.__exportStar(require("./schema_validation"), exports);

View File

@@ -0,0 +1,10 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AsnSchemaValidationError = void 0;
class AsnSchemaValidationError extends Error {
constructor() {
super(...arguments);
this.schemas = [];
}
}
exports.AsnSchemaValidationError = AsnSchemaValidationError;

View File

@@ -0,0 +1,45 @@
"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) {
var _a;
if (target) {
const proto = Object.getPrototypeOf(target);
if (((_a = proto === null || proto === void 0 ? void 0 : proto.prototype) === null || _a === void 0 ? void 0 : _a.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;
}

View File

@@ -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);

View File

@@ -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;

View File

@@ -0,0 +1,139 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AsnParser = void 0;
const asn1js = require("asn1js");
const enums_1 = require("./enums");
const converters = require("./converters");
const errors_1 = require("./errors");
const helper_1 = require("./helper");
const storage_1 = require("./storage");
class AsnParser {
static parse(data, target) {
const asn1Parsed = asn1js.fromBER(data);
if (asn1Parsed.result.error) {
throw new Error(asn1Parsed.result.error);
}
const res = this.fromASN(asn1Parsed.result, target);
return res;
}
static fromASN(asn1Schema, target) {
var _a;
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;
if (asn1Schema.constructor === asn1js.Constructed && schema.type !== enums_1.AsnTypeTypes.Choice) {
targetSchema = new asn1js.Constructed({
idBlock: {
tagClass: 3,
tagNumber: asn1Schema.idBlock.tagNumber,
},
value: schema.schema.valueBlock.value,
});
for (const key in schema.items) {
delete asn1Schema[key];
}
}
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}`);
}
const res = new target();
if ((0, helper_1.isTypeOfArray)(target)) {
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));
}
}
for (const key in schema.items) {
const asn1SchemaValue = asn1ComparedSchema.result[key];
if (!asn1SchemaValue) {
continue;
}
const schemaItem = schema.items[key];
const schemaItemType = schemaItem.type;
if (typeof schemaItemType === "number" || (0, helper_1.isConvertible)(schemaItemType)) {
const converter = (_a = schemaItem.converter) !== null && _a !== void 0 ? _a : ((0, helper_1.isConvertible)(schemaItemType)
? new schemaItemType()
: null);
if (!converter) {
throw new Error("Converter is empty");
}
if (schemaItem.repeated) {
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));
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;
res[key] = Array.from(value, (element) => converter.fromASN(element));
}
else {
res[key] = Array.from(asn1SchemaValue, (element) => converter.fromASN(element));
}
}
else {
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)).result;
}
res[key] = converter.fromASN(value);
}
}
else {
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.");
}
res[key] = Array.from(asn1SchemaValue, (element) => this.fromASN(element, schemaItemType));
}
else {
res[key] = this.fromASN(asn1SchemaValue, schemaItemType);
}
}
}
return res;
}
catch (error) {
if (error instanceof errors_1.AsnSchemaValidationError) {
error.schemas.push(target.name);
}
throw error;
}
}
}
exports.AsnParser = AsnParser;

View File

@@ -0,0 +1,160 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AsnSchemaStorage = void 0;
const asn1js = require("asn1js");
const enums_1 = require("./enums");
const helper_1 = require("./helper");
class AsnSchemaStorage {
constructor() {
this.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;

View File

@@ -0,0 +1,158 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AsnSerializer = void 0;
const asn1js = require("asn1js");
const converters = 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
? 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;

View File

@@ -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();

View File

@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

View File

@@ -0,0 +1,67 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.BitString = void 0;
const asn1js = require("asn1js");
const pvtsutils_1 = require("pvtsutils");
class BitString {
constructor(params, unusedBits = 0) {
this.unusedBits = 0;
this.value = new ArrayBuffer(0);
if (params) {
if (typeof params === "number") {
this.fromNumber(params);
}
else if (pvtsutils_1.BufferSourceConverter.isBufferSource(params)) {
this.unusedBits = unusedBits;
this.value = pvtsutils_1.BufferSourceConverter.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 = 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;

View File

@@ -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);

View File

@@ -0,0 +1,43 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.OctetString = void 0;
const asn1js = require("asn1js");
const pvtsutils_1 = require("pvtsutils");
class OctetString {
get byteLength() {
return this.buffer.byteLength;
}
get byteOffset() {
return 0;
}
constructor(param) {
if (typeof param === "number") {
this.buffer = new ArrayBuffer(param);
}
else {
if (pvtsutils_1.BufferSourceConverter.isBufferSource(param)) {
this.buffer = pvtsutils_1.BufferSourceConverter.toArrayBuffer(param);
}
else if (Array.isArray(param)) {
this.buffer = new Uint8Array(param);
}
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 = asn.valueBlock.valueHex;
return this;
}
toASN() {
return new asn1js.OctetString({ valueHex: this.buffer });
}
toSchema(name) {
return new asn1js.OctetString({ name });
}
}
exports.OctetString = OctetString;