import * as asn1js from "asn1js"; import { getParametersValue, clearProps } from "pvutils"; import GeneralNames from "./GeneralNames.js"; import AlgorithmIdentifier from "./AlgorithmIdentifier.js"; import Attribute from "./Attribute.js"; import Extensions from "./Extensions.js"; //************************************************************************************** /** * Class from RFC5755 */ export class AttCertValidityPeriod { //********************************************************************************** /** * Constructor for AttCertValidityPeriod class * @param {Object} [parameters={}] * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from */ constructor(parameters = {}) { //region Internal properties of the object /** * @type {GeneralizedTime} * @desc notBeforeTime */ this.notBeforeTime = getParametersValue(parameters, "notBeforeTime", AttCertValidityPeriod.defaultValues("notBeforeTime")); /** * @type {GeneralizedTime} * @desc notAfterTime */ this.notAfterTime = getParametersValue(parameters, "notAfterTime", AttCertValidityPeriod.defaultValues("notAfterTime")); //endregion //region If input argument array contains "schema" for this object if("schema" in parameters) this.fromSchema(parameters.schema); //endregion } //********************************************************************************** /** * Return default values for all class members * @param {string} memberName String name for a class member */ static defaultValues(memberName) { switch(memberName) { case "notBeforeTime": case "notAfterTime": return new Date(0, 0, 0); default: throw new Error(`Invalid member name for AttCertValidityPeriod class: ${memberName}`); } } //********************************************************************************** /** * Return value of pre-defined ASN.1 schema for current class * * ASN.1 schema: * ```asn1 * AttCertValidityPeriod ::= SEQUENCE { * notBeforeTime GeneralizedTime, * notAfterTime GeneralizedTime * } * ``` * * @param {Object} parameters Input parameters for the schema * @returns {Object} asn1js schema object */ static schema(parameters = {}) { /** * @type {Object} * @property {string} [blockName] * @property {string} [notBeforeTime] * @property {string} [notAfterTime] */ const names = getParametersValue(parameters, "names", {}); return (new asn1js.Sequence({ name: (names.blockName || ""), value: [ new asn1js.GeneralizedTime({ name: (names.notBeforeTime || "") }), new asn1js.GeneralizedTime({ name: (names.notAfterTime || "") }) ] })); } //********************************************************************************** /** * Convert parsed asn1js object into current class * @param {!Object} schema */ fromSchema(schema) { //region Clear input data first clearProps(schema, [ "notBeforeTime", "notAfterTime" ]); //endregion //region Check the schema is valid const asn1 = asn1js.compareSchema(schema, schema, AttCertValidityPeriod.schema({ names: { notBeforeTime: "notBeforeTime", notAfterTime: "notAfterTime" } }) ); if(asn1.verified === false) throw new Error("Object's schema was not verified against input data for AttCertValidityPeriod"); //endregion //region Get internal properties from parsed schema this.notBeforeTime = asn1.result.notBeforeTime.toDate(); this.notAfterTime = asn1.result.notAfterTime.toDate(); //endregion } //********************************************************************************** /** * Convert current object to asn1js object and set correct values * @returns {Object} asn1js object */ toSchema() { //region Construct and return new ASN.1 schema for this object return (new asn1js.Sequence({ value: [ new asn1js.GeneralizedTime({ valueDate: this.notBeforeTime }), new asn1js.GeneralizedTime({ valueDate: this.notAfterTime }), ] })); //endregion } //********************************************************************************** /** * Convertion for the class to JSON object * @returns {Object} */ toJSON() { return { notBeforeTime: this.notBeforeTime, notAfterTime: this.notAfterTime }; } //********************************************************************************** } //************************************************************************************** /** * Class from RFC5755 */ export class IssuerSerial { //********************************************************************************** /** * Constructor for IssuerSerial class * @param {Object} [parameters={}] * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from */ constructor(parameters = {}) { //region Internal properties of the object /** * @type {RelativeDistinguishedNames} * @desc issuer */ this.issuer = getParametersValue(parameters, "issuer", IssuerSerial.defaultValues("issuer")); /** * @type {Integer} * @desc serialNumber */ this.serialNumber = getParametersValue(parameters, "serialNumber", IssuerSerial.defaultValues("serialNumber")); if("issuerUID" in parameters) /** * @type {BitString} * @desc issuerUID */ this.issuerUID = getParametersValue(parameters, "issuerUID", IssuerSerial.defaultValues("issuerUID")); //endregion //region If input argument array contains "schema" for this object if("schema" in parameters) this.fromSchema(parameters.schema); //endregion } //********************************************************************************** /** * Return default values for all class members * @param {string} memberName String name for a class member */ static defaultValues(memberName) { switch(memberName) { case "issuer": return new GeneralNames(); case "serialNumber": return new asn1js.Integer(); case "issuerUID": return new asn1js.BitString(); default: throw new Error(`Invalid member name for IssuerSerial class: ${memberName}`); } } //********************************************************************************** /** * Return value of pre-defined ASN.1 schema for current class * * ASN.1 schema: * ```asn1 * IssuerSerial ::= SEQUENCE { * issuer GeneralNames, * serial CertificateSerialNumber, * issuerUID UniqueIdentifier OPTIONAL * } * * CertificateSerialNumber ::= INTEGER * UniqueIdentifier ::= BIT STRING * ``` * * @param {Object} parameters Input parameters for the schema * @returns {Object} asn1js schema object */ static schema(parameters = {}) { /** * @type {Object} * @property {string} [blockName] * @property {string} [issuer] * @property {string} [serialNumber] * @property {string} [issuerUID] */ const names = getParametersValue(parameters, "names", {}); return (new asn1js.Sequence({ name: (names.blockName || ""), value: [ GeneralNames.schema(names.issuer || {}), new asn1js.Integer({ name: (names.serialNumber || "") }), new asn1js.BitString({ optional: true, name: (names.issuerUID || "") }) ] })); } //********************************************************************************** /** * Convert parsed asn1js object into current class * @param {!Object} schema */ fromSchema(schema) { //region Clear input data first clearProps(schema, [ "issuer", "serialNumber", "issuerUID" ]); //endregion //region Check the schema is valid const asn1 = asn1js.compareSchema(schema, schema, IssuerSerial.schema({ names: { issuer: { names: { blockName: "issuer" } }, serialNumber: "serialNumber", issuerUID: "issuerUID" } }) ); if(asn1.verified === false) throw new Error("Object's schema was not verified against input data for IssuerSerial"); //endregion //region Get internal properties from parsed schema this.issuer = new GeneralNames({ schema: asn1.result.issuer }); this.serialNumber = asn1.result.serialNumber; if("issuerUID" in asn1.result) this.issuerUID = asn1.result.issuerUID; //endregion } //********************************************************************************** /** * Convert current object to asn1js object and set correct values * @returns {Object} asn1js object */ toSchema() { const result = new asn1js.Sequence({ value: [ this.issuer.toSchema(), this.serialNumber ] }); if("issuerUID" in this) result.valueBlock.value.push(this.issuerUID); //region Construct and return new ASN.1 schema for this object return result; //endregion } //********************************************************************************** /** * Convertion for the class to JSON object * @returns {Object} */ toJSON() { const result = { issuer: this.issuer.toJSON(), serialNumber: this.serialNumber.toJSON() }; if("issuerUID" in this) result.issuerUID = this.issuerUID.toJSON(); return result; } //********************************************************************************** } //************************************************************************************** /** * Class from RFC5755 */ export class AttributeCertificateInfoV1 { //********************************************************************************** /** * Constructor for AttributeCertificateInfoV1 class * @param {Object} [parameters={}] * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from */ constructor(parameters = {}) { //region Internal properties of the object /** * @type {Number} * @desc version */ this.version = getParametersValue(parameters, "version", AttributeCertificateInfoV1.defaultValues("version")); if("baseCertificateID" in parameters) /** * @type {IssuerSerial} * @desc baseCertificateID */ this.baseCertificateID = getParametersValue(parameters, "baseCertificateID", AttributeCertificateInfoV1.defaultValues("baseCertificateID")); if("subjectName" in parameters) /** * @type {GeneralNames} * @desc subjectName */ this.subjectName = getParametersValue(parameters, "subjectName", AttributeCertificateInfoV1.defaultValues("subjectName")); /** * @type {GeneralNames} * @desc issuer */ this.issuer = getParametersValue(parameters, "issuer", AttributeCertificateInfoV1.defaultValues("issuer")); /** * @type {AlgorithmIdentifier} * @desc signature */ this.signature = getParametersValue(parameters, "signature", AttributeCertificateInfoV1.defaultValues("signature")); /** * @type {Integer} * @desc serialNumber */ this.serialNumber = getParametersValue(parameters, "serialNumber", AttributeCertificateInfoV1.defaultValues("serialNumber")); /** * @type {AttCertValidityPeriod} * @desc attrCertValidityPeriod */ this.attrCertValidityPeriod = getParametersValue(parameters, "attrCertValidityPeriod", AttributeCertificateInfoV1.defaultValues("attrCertValidityPeriod")); /** * @type {Array.} * @desc attributes */ this.attributes = getParametersValue(parameters, "attributes", AttributeCertificateInfoV1.defaultValues("attributes")); if("issuerUniqueID" in parameters) /** * @type {BitString} * @desc issuerUniqueID */ this.issuerUniqueID = getParametersValue(parameters, "issuerUniqueID", AttributeCertificateInfoV1.defaultValues("issuerUniqueID")); if("extensions" in parameters) /** * @type {Extensions} * @desc extensions */ this.extensions = getParametersValue(parameters, "extensions", AttributeCertificateInfoV1.defaultValues("extensions")); //endregion //region If input argument array contains "schema" for this object if("schema" in parameters) this.fromSchema(parameters.schema); //endregion } //********************************************************************************** /** * Return default values for all class members * @param {string} memberName String name for a class member */ static defaultValues(memberName) { switch(memberName) { case "version": return 0; case "baseCertificateID": return new IssuerSerial(); case "subjectName": return new GeneralNames(); case "issuer": return {}; case "signature": return new AlgorithmIdentifier(); case "serialNumber": return new asn1js.Integer(); case "attrCertValidityPeriod": return new AttCertValidityPeriod(); case "attributes": return []; case "issuerUniqueID": return new asn1js.BitString(); case "extensions": return new Extensions(); default: throw new Error(`Invalid member name for AttributeCertificateInfoV1 class: ${memberName}`); } } //********************************************************************************** /** * Return value of pre-defined ASN.1 schema for current class * * ASN.1 schema: * ```asn1 * AttributeCertificateInfo ::= SEQUENCE { * version Version DEFAULT v1, * subject CHOICE { * baseCertificateID [0] IssuerSerial, -- associated with a Public Key Certificate * subjectName [1] GeneralNames }, -- associated with a name * issuer GeneralNames, -- CA issuing the attribute certificate * signature AlgorithmIdentifier, * serialNumber CertificateSerialNumber, * attrCertValidityPeriod AttCertValidityPeriod, * attributes SEQUENCE OF Attribute, * issuerUniqueID UniqueIdentifier OPTIONAL, * extensions Extensions OPTIONAL * } * ``` * * @param {Object} parameters Input parameters for the schema * @returns {Object} asn1js schema object */ static schema(parameters = {}) { /** * @type {Object} * @property {string} [blockName] * @property {string} [issuer] * @property {string} [serialNumber] */ const names = getParametersValue(parameters, "names", {}); return (new asn1js.Sequence({ name: (names.blockName || ""), value: [ new asn1js.Integer({ name: (names.version || "") }), new asn1js.Choice({ value: [ new asn1js.Constructed({ name: (names.baseCertificateID || ""), idBlock: { tagClass: 3, tagNumber: 0 // [0] }, value: IssuerSerial.schema().valueBlock.value }), new asn1js.Constructed({ name: (names.subjectName || ""), idBlock: { tagClass: 3, tagNumber: 1 // [2] }, value: GeneralNames.schema().valueBlock.value }), ] }), GeneralNames.schema({ names: { blockName: (names.issuer || "") } }), AlgorithmIdentifier.schema(names.signature || {}), new asn1js.Integer({ name: (names.serialNumber || "") }), AttCertValidityPeriod.schema(names.attrCertValidityPeriod || {}), new asn1js.Sequence({ name: (names.attributes || ""), value: [ new asn1js.Repeated({ value: Attribute.schema() }) ] }), new asn1js.BitString({ optional: true, name: (names.issuerUniqueID || "") }), Extensions.schema(names.extensions || {}, true) ] })); } //********************************************************************************** /** * Convert parsed asn1js object into current class * @param {!Object} schema */ fromSchema(schema) { //region Clear input data first clearProps(schema, [ "version", "baseCertificateID", "subjectName", "issuer", "signature", "serialNumber", "attrCertValidityPeriod", "attributes", "issuerUniqueID", "extensions" ]); //endregion //region Check the schema is valid const asn1 = asn1js.compareSchema(schema, schema, AttributeCertificateInfoV1.schema({ names: { version: "version", baseCertificateID: "baseCertificateID", subjectName: "subjectName", issuer: "issuer", signature: { names: { blockName: "signature" } }, serialNumber: "serialNumber", attrCertValidityPeriod: { names: { blockName: "attrCertValidityPeriod" } }, attributes: "attributes", issuerUniqueID: "issuerUniqueID", extensions: { names: { blockName: "extensions" } } } }) ); if(asn1.verified === false) throw new Error("Object's schema was not verified against input data for AttributeCertificateInfoV1"); //endregion //region Get internal properties from parsed schema this.version = asn1.result.version.valueBlock.valueDec; if("baseCertificateID" in asn1.result) { this.baseCertificateID = new IssuerSerial({ schema: new asn1js.Sequence({ value: asn1.result.baseCertificateID.valueBlock.value }) }); } if("subjectName" in asn1.result) { this.subjectName = new GeneralNames({ schema: new asn1js.Sequence({ value: asn1.result.subjectName.valueBlock.value }) }); } this.issuer = asn1.result.issuer; this.signature = new AlgorithmIdentifier({ schema: asn1.result.signature }); this.serialNumber = asn1.result.serialNumber; this.attrCertValidityPeriod = new AttCertValidityPeriod({ schema: asn1.result.attrCertValidityPeriod }); this.attributes = Array.from(asn1.result.attributes.valueBlock.value, element => new Attribute({ schema: element })); if("issuerUniqueID" in asn1.result) this.issuerUniqueID = asn1.result.issuerUniqueID; if("extensions" in asn1.result) this.extensions = new Extensions({ schema: asn1.result.extensions }); //endregion } //********************************************************************************** /** * Convert current object to asn1js object and set correct values * @returns {Object} asn1js object */ toSchema() { const result = new asn1js.Sequence({ value: [new asn1js.Integer({ value: this.version })] }); if("baseCertificateID" in this) { result.valueBlock.value.push(new asn1js.Constructed({ idBlock: { tagClass: 3, tagNumber: 0 // [0] }, value: this.baseCertificateID.toSchema().valueBlock.value })); } if("subjectName" in this) { result.valueBlock.value.push(new asn1js.Constructed({ idBlock: { tagClass: 3, tagNumber: 1 // [1] }, value: this.subjectName.toSchema().valueBlock.value })); } result.valueBlock.value.push(this.issuer.toSchema()); result.valueBlock.value.push(this.signature.toSchema()); result.valueBlock.value.push(this.serialNumber); result.valueBlock.value.push(this.attrCertValidityPeriod.toSchema()); result.valueBlock.value.push(new asn1js.Sequence({ value: Array.from(this.attributes, element => element.toSchema()) })); if("issuerUniqueID" in this) result.valueBlock.value.push(this.issuerUniqueID); if("extensions" in this) result.valueBlock.value.push(this.extensions.toSchema()); return result; } //********************************************************************************** /** * Convertion for the class to JSON object * @returns {Object} */ toJSON() { const result = { version: this.version }; if("baseCertificateID" in this) result.baseCertificateID = this.baseCertificateID.toJSON(); if("subjectName" in this) result.subjectName = this.subjectName.toJSON(); result.issuer = this.issuer.toJSON(); result.signature = this.signature.toJSON(); result.serialNumber = this.serialNumber.toJSON(); result.attrCertValidityPeriod = this.attrCertValidityPeriod.toJSON(); result.attributes = Array.from(this.attributes, element => element.toJSON()); if("issuerUniqueID" in this) result.issuerUniqueID = this.issuerUniqueID.toJSON(); if("extensions" in this) result.extensions = this.extensions.toJSON(); return result; } //********************************************************************************** } //************************************************************************************** /** * Class from X.509:1997 */ export default class AttributeCertificateV1 { //********************************************************************************** /** * Constructor for AttributeCertificateV1 class * @param {Object} [parameters={}] * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from */ constructor(parameters = {}) { //region Internal properties of the object /** * @type {AttributeCertificateInfoV1} * @desc acinfo */ this.acinfo = getParametersValue(parameters, "acinfo", AttributeCertificateV1.defaultValues("acinfo")); /** * @type {AlgorithmIdentifier} * @desc signatureAlgorithm */ this.signatureAlgorithm = getParametersValue(parameters, "signatureAlgorithm", AttributeCertificateV1.defaultValues("signatureAlgorithm")); /** * @type {BitString} * @desc signatureValue */ this.signatureValue = getParametersValue(parameters, "signatureValue", AttributeCertificateV1.defaultValues("signatureValue")); //endregion //region If input argument array contains "schema" for this object if("schema" in parameters) this.fromSchema(parameters.schema); //endregion } //********************************************************************************** /** * Return default values for all class members * @param {string} memberName String name for a class member */ static defaultValues(memberName) { switch(memberName) { case "acinfo": return new AttributeCertificateInfoV1(); case "signatureAlgorithm": return new AlgorithmIdentifier(); case "signatureValue": return new asn1js.BitString(); default: throw new Error(`Invalid member name for AttributeCertificateV1 class: ${memberName}`); } } //********************************************************************************** /** * Return value of pre-defined ASN.1 schema for current class * * ASN.1 schema: * ```asn1 * AttributeCertificate ::= SEQUENCE { * acinfo AttributeCertificateInfoV1, * signatureAlgorithm AlgorithmIdentifier, * signatureValue BIT STRING * } * ``` * * @param {Object} parameters Input parameters for the schema * @returns {Object} asn1js schema object */ static schema(parameters = {}) { /** * @type {Object} * @property {string} [blockName] * @property {Object} [acinfo] * @property {Object} [signatureAlgorithm] * @property {string} [signatureValue] */ const names = getParametersValue(parameters, "names", {}); return (new asn1js.Sequence({ name: (names.blockName || ""), value: [ AttributeCertificateInfoV1.schema(names.acinfo || {}), AlgorithmIdentifier.schema(names.signatureAlgorithm || {}), new asn1js.BitString({ name: (names.signatureValue || "") }) ] })); } //********************************************************************************** /** * Convert parsed asn1js object into current class * @param {!Object} schema */ fromSchema(schema) { //region Clear input data first clearProps(schema, [ "acinfo", "signatureValue", "signatureAlgorithm" ]); //endregion //region Check the schema is valid const asn1 = asn1js.compareSchema(schema, schema, AttributeCertificateV1.schema({ names: { acinfo: { names: { blockName: "acinfo" } }, signatureAlgorithm: { names: { blockName: "signatureAlgorithm" } }, signatureValue: "signatureValue" } }) ); if(asn1.verified === false) throw new Error("Object's schema was not verified against input data for AttributeCertificateV1"); //endregion //region Get internal properties from parsed schema this.acinfo = new AttributeCertificateInfoV1({ schema: asn1.result.acinfo }); this.signatureAlgorithm = new AlgorithmIdentifier({ schema: asn1.result.signatureAlgorithm }); this.signatureValue = asn1.result.signatureValue; //endregion } //********************************************************************************** /** * Convert current object to asn1js object and set correct values * @returns {Object} asn1js object */ toSchema() { return (new asn1js.Sequence({ value: [ this.acinfo.toSchema(), this.signatureAlgorithm.toSchema(), this.signatureValue ] })); } //********************************************************************************** /** * Convertion for the class to JSON object * @returns {Object} */ toJSON() { return { acinfo: this.acinfo.toJSON(), signatureAlgorithm: this.signatureAlgorithm.toJSON(), signatureValue: this.signatureValue.toJSON() }; } //********************************************************************************** } //**************************************************************************************