Giter Club home page Giter Club logo

asn1-ts's Introduction

ASN.1 TypeScript Library

This library was based off of my D ASN.1 Library.

What is ASN.1?

ASN.1 stands for Abstract Syntax Notation. ASN.1 was first specified in X.680 - Abstract Syntax Notation One (ASN.1), by the International Telecommunications Union. ASN.1 messages can be encoded in one of several encoding/decoding standards. It provides a system of types that are extensible, and can presumably describe every protocol. You can think of it as a protocol for describing other protocols as well as a family of standards for encoding and decoding said protocols. It is similar to Google's Protocol Buffers, or Sun Microsystems' External Data Representation (XDR).

For more information on what ASN.1 is, see documentation/asn1.md.

Why Use This Library?

I believe this library is the first complete implementation of ASN.1, meaning that it implements all data types defined in the specification, and encodes and decodes exactly as specified.

I have never seen any implementation of ASN.1 elsewhere that supports all data types; in fact, most just implement the ten or so most common types. Several implementations I have seen do not support things that are supported by the specification, such as constructed strings.

This library is fully compliant to the specification. If I am wrong, please write up an issue and I will correct it.

Why Not Use This Library?

This library is meant to be fully compliant to the specification, not lightweight. If you need a web application that encodes and decodes very simple ASN.1 data and loads lightning-fast, this may not be the library for you.

Building

You can build this library by running npm run build. The outputs will all be in dist.

  • dist/index.js is the root for usage in NodeJS.
  • dist/asn1.min.js is the entire ASN.1 library for the web browser, which is minified, and accessible under the variable asn1.

Library Usage

Data Types

In this library, all ASN.1 data types are represented as aliases to TypeScript / JavaScript types in source/macros.ts. For your convenience these aliases are copied here:

export type OPTIONAL<T> = T | undefined;
export type BOOLEAN = boolean;
export type INTEGER = number | bigint;
export type BIT_STRING = Uint8ClampedArray;
export type OCTET_STRING = Uint8Array;
export type NULL = null;
export type OBJECT_IDENTIFIER = ObjectIdentifier;
export type ObjectDescriptor = string;
export type EXTERNAL = External;
export type REAL = number;
export type INSTANCE_OF = External;
export type ENUMERATED = number;
export type EMBEDDED_PDV = EmbeddedPDV;
export type UTF8String = string;
export type RELATIVE_OID = number[];
export type SEQUENCE<T> = T[];
export type SEQUENCE_OF<T> = T[];
export type SET<T> = T[];
export type SET_OF<T> = T[];
export type GraphicString = string;
export type NumericString = string;
export type VisibleString = string;
export type PrintableString = string;
export type ISO646String = string;
export type TeletexString = Uint8Array;
export type GeneralString = string;
export type T61String = Uint8Array;
export type UniversalString = string;
export type VideotexString = Uint8Array;
export type BMPString = string;
export type IA5String = string;
// export type CharacterString = CharacterString;
export { default as CharacterString } from "./types/CharacterString";
export type UTCTime = Date;
export type GeneralizedTime = Date;
export type TIME = string;
export type DATE = Date;
export type TIME_OF_DAY = Date;
export type DATE_TIME = Date;
export type DURATION = DURATION_EQUIVALENT;
export type OID_IRI = string;
export type RELATIVE_OID_IRI = string;

Native ASN.1 types that don't have an obvious corollary to a native JavaScript type have an implementation in the types folder. This includes these types:

  • OBJECT IDENTIFIER, implemented as ObjectIdentifier
  • EXTERNAL, implemented as External
  • EMBEDDED PDV, implemented as EmbeddedPDV
  • CHARACTER STRING, implemented as CharacterString

The TYPE-IDENTIFIER object class is implemented as TypeIdentifier. There are also implementation of all of the structured time types specified in the ITU Recommendation X.696 in types/time.

Encoding and Decoding

For each codec in the library, usage entails instantiating the class, then using that class' properties to get and set the encoded value. For all classes, the empty constructor creates an END OF CONTENT element. The remaining constructors will be codec-specific.

Here is a TypeScript example of encoding with Basic Encoding Rules, using the BERElement class.

let el: BERElement = new BERElement();
el.tagClass = ASN1TagClass.universal; // Not technically necessary.
el.construction = ASN1Construction.construction; // Not technically necessary.
el.tagNumber = ASN1UniversalType.integer;
el.integer = 1433; // Now the data is encoded.
console.log(el.integer); // Logs '1433'

... and here is how you would decode that same element:

let encodedData: Uint8Array = el.toBytes();
let el2: BERElement = new BERElement();
el2.fromBytes(encodedData);
console.log(el2.integer); // Logs 1433

Tests under the test directory can also serve as examples.

In this library, you can use the Basic Encoding Rules, Canonical Encoding Rules, and Distinguished Encoding Rules via the BERElement, CERElement, and DERElement classes respectively. You should use DERElement for anything that will be cryptographically signed or hashed.

The tag class can be read and written via the tagClass property using the ASN1TagClass enum. The construction (whether it is constructed or primitive) of the element can be read and written via the construction property using the ASN1Construction enum. The tag number can be set using the tagNumber property. For your convenience, the ASN1UniveralType enum contains the tag numbers of the UNIVERSAL tags by the data type.

Generic "bytes" are represented with the Uint8Array class. Note that Buffer is a subtype of Uint8Array, so you can use a Buffer anywhere you use a Uint8Array (but not the reverse). You can interact with the value bytes of the ASN.1 element through the value property. You can convert ASN.1 elements to and from bytes using toBytes() and fromBytes(). fromBytes() returns an integer indicating the number of bytes read from the Uint8Array. Here is an example of how you would decode multiple back-to-back encoded ASN.1 elements from a buffer:

const encodedElements: BERElement[] = [];
let i: number = 0;
while (i < value.length) {
    const next: BERElement = new BERElement();
    i += next.fromBytes(value.slice(i));
    encodedElements.push(next);
}

Here are the properties available for you to get and set ASN.1 values:

set boolean (value: BOOLEAN);
get boolean (): BOOLEAN;
set integer (value: INTEGER);
get integer (): INTEGER;
set bitString (value: BIT_STRING);
get bitString (): BIT_STRING;
set octetString (value: OCTET_STRING);
get octetString (): OCTET_STRING;
set objectIdentifier (value: OBJECT_IDENTIFIER);
get objectIdentifier (): OBJECT_IDENTIFIER;
set objectDescriptor (value: ObjectDescriptor);
get objectDescriptor (): ObjectDescriptor;
set external (value: EXTERNAL);
get external (): EXTERNAL;
set real (value: REAL);
get real (): REAL;
set enumerated (value: ENUMERATED);
get enumerated (): ENUMERATED;
set embeddedPDV (value: EMBEDDED_PDV);
get embeddedPDV (): EMBEDDED_PDV;
set utf8String (value: UTF8String);
get utf8String (): UTF8String;
set relativeObjectIdentifier (value: RELATIVE_OID);
get relativeObjectIdentifier (): RELATIVE_OID;
set time (value: TIME);
get time (): TIME;
set sequence (value: SEQUENCE<ASN1Element>);
get sequence (): SEQUENCE<ASN1Element>;
set set (value: SET<ASN1Element>);
get set (): SET<ASN1Element>;
set numericString (value: NumericString);
get numericString (): NumericString;
set printableString (value: PrintableString);
get printableString (): PrintableString;
set teletexString (value: TeletexString);
get teletexString (): TeletexString;
set videotexString (value: VideotexString);
get videotexString (): VideotexString;
set ia5String (value: IA5String);
get ia5String (): IA5String;
set utcTime (value: UTCTime);
get utcTime (): UTCTime;
set generalizedTime (value: GeneralizedTime);
get generalizedTime (): GeneralizedTime;
set graphicString (value: GraphicString);
get graphicString (): GraphicString;
set visibleString (value: VisibleString);
get visibleString (): VisibleString;
set generalString (value: GeneralString);
get generalString (): GeneralString;
set universalString (value: UniversalString);
get universalString (): UniversalString;
set characterString (value: CharacterString);
get characterString (): CharacterString;
set bmpString (value: BMPString);
get bmpString (): BMPString;
set date (value: DATE);
get date (): DATE;
set timeOfDay (value: TIME_OF_DAY);
get timeOfDay (): TIME_OF_DAY;
set dateTime (value: DATE_TIME);
get dateTime (): DATE_TIME;
set duration (value: DURATION);
get duration (): DURATION;
set oidIRI (value: OID_IRI);
get oidIRI (): OID_IRI;
set relativeOIDIRI (value: RELATIVE_OID_IRI);
get relativeOIDIRI (): RELATIVE_OID_IRI;

There are shorthand equivalents of the getters and setters above (created to make source files more concise), but these will be removed in a future version.

ASN.1 elements (BERElement, CERElement, and DERElement) support the toString() and toJSON() properties. In general, toString() encodes the elements according to how their values would be represented in an ASN.1 file. In general, toJSON() encodes the elements according to the JSON Encoding Rules (JER).

Finally, there are functional equivalents of the codecs above in functional.ts such as _decodeUTF8String. These will not be documented (for now). They were implemented to support Wildboar Software's ASN.1 Compiler. You can look at the source code for the NPM package @wildboar/x500 for an example for how it works.

Error Handling

This library throws a few subtypes of ASN1Error, which is a subtype of Error. These are:

  • ASN1NotImplementedError, which is thrown when some functionality of this library is not implemented.
  • ASN1RecursionError, which is thrown when an ASN.1 element is too deeply constructed (e.g. a string is encoded on a construction of constructions of constructions, etc.).
  • ASN1TruncationError, which is thrown when the ASN.1 element was too short. This error may be thrown when you are receiving encoded ASN.1 elements over a network and you simply have not received the complete encoding yet. For this reason, if you are reading ASN.1 elements from a network buffer, you may have to catch this error and just wait for more data to come in.
  • ASN1OverflowError, which is thrown when an encoded data type, such as an INTEGER or an arc of an OBJECT IDENTIFIER encodes such a large value that this library cannot encode or decode it.
  • ASN1SizeError, which is thrown when a value is encoded on an incorrect number of bytes. This can happen with a UNIVERSAL type is encoded on a wrong number of bytes (such as a BOOLEAN being encoded on more than one byte), or it can be thrown by third-party libraries when a SIZE constraint is violated.
  • ASN1PaddingError, which is thrown when an encoded value has prohibited padding bytes. For instance, in the Basic Encoding Rules encoding of an INTEGER, the integer must be encoded on the minimum number of octets possible; any encoding containing more than the minimum would throw this error.
  • ASN1UndefinedError, which is thrown when some encoding is not defined, such as an unrecognized encoding for a REAL value.
  • ASN1CharactersError, which is thrown when a string contains a character that is prohibited for that string type.
  • ASN1ConstructionError, which is thrown when the construction of an ASN.1 element is incorrect, such as an INTEGER being "constructed." This may also be thrown by third-party libraries when a SEQUENCE is constructed of an invalid sequence of elements.

BIT STRING

In this library, BIT STRING is represented by a Uint8ClampedArray. Set bits are represented by a value of 1 and unset bits are represented by a value of 0. To "pack" these bytes into bytes, you can use packBits, and to reverse this, you can use unpackBits. Note that this does not include the "unused bits" prefix that the BIT STRING requires; packBits and unpackBits are only responsible for packing eight bits into a byte, and the reverse, respectively.

OBJECT IDENTIFIER

OBJECT IDENTIFIER is represented as objects of the ObjectIdentifier class.

You can encode and decode object identifiers to and from their dot-delimited string representations (e.g. 2.5.4.3) using toString() and ObjectIdentifier.fromString() (the latter is a static method.)

Future Development

  • Implement a function for ITU X.690, Section 11.6.
  • Implement these codecs:
    • Octet Encoding Rules (This is used by Simple Transportation Management Protocol (STMP) and DATEX-ASN.)
    • Canonical Octet Encoding Rules
    • NTCIP Encoding Rules (This is used by Simple Transportation Management Protocol (STMP) and DATEX-ASN.)
    • JSON Encoding Rules (May require changes to ASN1Element, or a separate element.)
    • Lightweight Encoding Rules (I cannot find a standard anywhere for this.)
    • BACNet Encoding Rules
    • Packed Encoding Rules
      • Basic Aligned Packed Encoding Rules (PER) (This is used by MCS / T.125, which is used by RDP. I believe it is also used by J2735 / DSRC.)
      • Make a separate RDPER (Remoted Desktop Protocol Encoding Rules)
      • Basic Unaligned Packed Encoding Rules (UPER) (May require changes to ASN1Element) (Used by 3GPP RRC)
      • Canonical Aligned Packed Encoding Rules (CPER)
      • Canonical Unaligned Packed Encoding Rules (CUPER) (May require changes to ASN1Element)
  • Internationalized strings
  • Serverless Functions (May be done in a different repo.)

See Also

asn1-ts's People

Contributors

dicksonhk avatar hamano avatar jonathanwilbur avatar msinisal avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

asn1-ts's Issues

Broken validateConstruction function on 7.0.4

  • Version: 7.0.4
  • Platform: N/A
  • Subsystem: N/A

continue, instead of return, should be used for flow control

// specification.forEach((spec: ConstructedElementSpecification): void => { // <-- 7.0.3
for (const spec of specification) { // <-- 7.0.4
    if (
        (i >= elements.length)
        || (spec.tagClass && spec.tagClass !== elements[i].tagClass)
        || (spec.construction && spec.construction !== elements[i].construction)
        || (spec.tagNumber && spec.tagNumber !== elements[i].tagNumber)
    ) {
        if (!spec.optional) {
            throw new errors.ASN1ConstructionError(`Missing required element '${spec.name}'.`);
        }
        // return; // <-- this return statement "breaks out" of the loop, ending the whole function early
        continue;
    }
    // ...
}

P.S.

The validateConstruction function was working just fine up until 7.0.3.

I understand it is now deprecated, but I had been using it for validation and decode.

Question ASN1 DER Encoding/Decoding Class=APPLICATION TAGNUMBER=31

Dear @JonathanWilbur , @hamano

Thanks for this library I'm starting to use in javascript and ASN1 DER.

I get the following exception while decoding a DER element from:

File: der.js, Function: fromBytes(bytes), Line 454:

[source,javascript]
....

        if (this.tagNumber <= 31) {
            throw new errors.ASN1Error("ASN.1 tag number could have been encoded in short form.", this);
        }

....

Before that, it was encoded using the following code snippet:

[source,javascript]
....
/* ASN1 Description
application_tag_31 ::= [APPLICATION 31] IMPLICIT UTF8String OPTIONAL

Used Library: [Jonathan M. Wilbur](https://github.com/JonathanWilbur/asn1-ts)
const ASN1 = require('asn1-ts');

*/

module.exports.set_tag31 = function(tag=31) {
var e = new ASN1.DERElement();
e.tagClass = ASN1.ASN1TagClass.application;
e.construction = ASN1.ASN1Construction.primitive;
e.tagNumber = tag;
e.name = "application_tag_31";
e.utf8String = "Hi";
LOG_ASN1_ELEMENT(e);
return e;
}
....

Encoding with: der_encoded = der_element.toBytes() gives the following console output:

....
Name: application_tag_31-ASN1-DER Encoded, Number bytes: 5
Dezimal: 95,31,2,72,105
Hex: 0x5F,0x1F,0x02,0x48,0x69
....

Decoding same buffer with der_element.fromBytes(der_encoded) gives the following exeption as console output and fails therefore:

....
Exception Thrown: Error: ASN.1 tag number could have been encoded in short form.
....

To me the identifier octet (class application,primitive,for tags with a number greater than or equal to 31 (bit5 to bit0 0b11111)):0x5F and Tag (last Octet = bit8 zero, tag number 31) 0x1F encoding looks correct, but the decode function should check if (this.tagNumber < 31) instead of if (this.tagNumber <= 31).

What do you think?

Best regards,

Axel

Broken toString and toJSON function on 7.0.6

  • Version: 7.0.6
  • Platform: N/A
  • Subsystem: N/A

Calling toString and toJSON on a SET_OF ASN1Element that is not uniquely tagged throws ASN1ConstructionError, after the introduction of uniqueness checking for SET introduced in v7.0.6.

Calling setOf, instead of set, could be one way of solving the issue, as both SET and SET_OF have the same signature.

source/codecs/ber.ts, source/codecs/cer.ts, source/codecs/der.ts:

get set (): SET<ASN1Element> {
    const ret = this.sequence;
    if (!isUniquelyTagged(ret)) {
        throw new errors.ASN1ConstructionError("Duplicate tag in SET.", this);
    }
    return ret;
}

source/asn1.ts

// toString()
switch (this.tagNumber) {
    case (ASN1UniversalType.set): return ("{ " + this.set // <-- this could be a SET_OF, with might not be uniquely tagged
        .map((el) => (el.name.length ? `${el.name} ${el.toString()}` : el.toString()))
        .join(" , ") + " }");
}

source/asn1.ts

// toJSON()
switch (this.tagNumber) {
    case (ASN1UniversalType.set): { // <-- this could be a SET_OF, with might not be uniquely tagged
        if (!recurse) {
            return null;
        }
        return this.set.map((el) => el.toJSON());
    }
}

test/x690/constructor.test.js failed

  • Version: master
  • Platform: linux
  • Subsystem:

npm t failed for master branch
The test looks good for me...

  ● Function's constructor › encodes a Date correctly

    expect(received).toBe(expected) // Object.is equality

    Expected: "2019-11-"
    Received: "2019-12-"

      110 |             );
      111 |             expect(el.generalizedTime.toISOString().slice(0, 8))
    > 112 |                 .toBe((new Date(2019, 10, 3)).toISOString().slice(0, 8));
          |                  ^
      113 |         });
      114 |     });
      115 | });

      at Object.toBe (test/x690/constructor.test.js:112:18)

Buffer error with Cloudflare Workers

  • Version: 8.0.2
  • Platform: CloudFlare Workers

Attempting to use this with Cloudflare Workers, I'm getting an error that buffer isn't defined. I suspect it's because Buffer isn't imported explicitly.

(base) mistial@Mistials-MacBook-Pro xxx % npx wrangler deploy                                            
 ⛅️ wrangler 3.52.0
-------------------
Your worker has access to the following bindings:
- Queues:
  - QUEUE: xxx
- D1 Databases:
  - DB: xxx (xxx-xxx-xxx-xxx-xxx)
Total Upload: xxx KiB / gzip: xxx KiB

✘ [ERROR] A request to the Cloudflare API (/accounts/xxx/workers/scripts/xxx) failed.

  Uncaught ReferenceError: Buffer is not defined
    at null.<anonymous>
  (file:///Users/mistial/Projects/xxx/node_modules/asn1-ts/source/asn1.ts:88:9) in toBytes
    at null.<anonymous> (file:///Users/mistial/Projects/xxx/src/router.ts:12:26)
   [code: 10021]

I am using nodejs compatibility mode:

compatibility_flags = [ "nodejs_compat" ]

Looking through the CloudFlare Documentation, it states:

To ensure compatibility with a wider set of npm packages, and make it easier for you to run existing 
applications on Cloudflare Workers, the following APIs from the Node.js runtime are available directly 
as Workers runtime APIs, with no need to add polyfills to your own code

They show the need to add an import like import { Buffer } from 'node:buffer'; This seems to align with nodejs recommendations:

While the Buffer class is available within the global scope, it is still recommended to explicitly reference
it via an import or require statement.

Markdown support possible?

It would be nice to see the asn.1 syntax support in VScode's markdown:

Something like in (*.md file):

```asn.1
id-ct-TSTInfo  OBJECT IDENTIFIER ::= {
    iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) ct(1) 4
}```

Invalid Tag Class and Construction Setting in toBytes()

The method toBytes in all codecs incorrectly sets the tag class and construction.

In the lines below, I OR'ed the tag octets with the ASN1TagClass and ASN1Construction with the assumption that those enum members had values that were already shifted to the proper bit. Below is the OR in the BER codec:

tagBytes[0] |= this.tagClass;
tagBytes[0] |= this.construction;

And here it is in the DER codec:

tagBytes[0] |= this.tagClass;
tagBytes[0] |= this.construction;

And here are the enum definitions:

export
const enum ASN1TagClass {
universal = 0,
application = 1,
context = 3,
private = 4
}
export
const enum ASN1Construction {
primitive = 0,
constructed = 1
}

This would result in tags being encoded with the incorrect tag numbers.

Incorrect Tag Class Numbers

I created the ASN1TagClass enum with an incorrect mapping of names to values. Notice that I accidentally skipped 2 below:

export
const enum ASN1TagClass {
universal = 0,
application = 1,
context = 3,
private = 4
}

This resulted in context-specific tags being encoded as PRIVATE tag class, and PRIVATE tag class being encoded as UNIVERSAL.

rollup warn Circular dependencies

  • Version: 7.1.0
  • Platform: linux
  • Subsystem:

Im using rollup for bundle asn1-ts. it warn circular dependencies.
Is there a way to suppress the warning?

$ rollup -c
(!) Circular dependencies
node_modules/asn1-ts/dist/node/codecs/x690/decoders/decodeObjectIdentifier.js -> node_modules/asn1-ts/dist/node/types/ObjectIdentifier.js -> node_modules/asn1-ts/dist/node/codecs/x690/decoders/decodeObjectIdentifier.js
node_modules/asn1-ts/dist/node/codecs/ber.js -> node_modules/asn1-ts/dist/node/codecs/ber/decoders/decodeSequence.js -> node_modules/asn1-ts/dist/node/codecs/ber.js
node_modules/asn1-ts/dist/node/codecs/der.js -> node_modules/asn1-ts/dist/node/codecs/der/decoders/decodeSequence.js -> node_modules/asn1-ts/dist/node/codecs/der.js
...and 4 more
created dist/bundle.js in 21.1s

Missing tslib dependency

Hello, thanks for making a nice project!

I noticed that after importing this project and compiling my (TypeScript) code into a common js module it was failing to run due to a missing dependency tslib.

Uncaught Error: Cannot find module 'tslib'
Require stack:
- /dev/shm/t/node_modules/asn1-ts/dist/node/index.js

I believe the issue is related to:

"importHelpers": true,

From the TypeScript documenation:

If the importHelpers flag is on, these helper functions are instead imported from the tslib module. You will need to ensure that the tslib module is able to be imported at runtime. This only affects modules; global script files will not attempt to import modules.

I believe you need to do a simple npm i tslib?

Error decoding string types in NodeJS version 11.0 and higher

To my knowledge, these types fail to decode correctly in NodeJS version 11.0 and higher:

  • ObjectDescriptor
  • UTF8String
  • NumericString
  • PrintableString
  • TeletexString
  • VideotexString
  • IA5String
  • UTCTime
  • GeneralizedTime
  • GraphicString
  • VisibleString
  • GeneralString
  • BMPString

The problem starts with this piece of recurring code:

if (typeof TextEncoder !== "undefined") { // Browser JavaScript
    dateString = (new TextDecoder("utf-8")).decode(<ArrayBuffer>this.value.subarray(0).buffer);
} else if (typeof Buffer !== "undefined") { // NodeJS
    dateString = (new Buffer(this.value)).toString("utf-8");
}

Before NodeJS version 11.0, TextEncoder and TextDecoder were in the util part of the standard library. I did not know about this. I thought they were undefined in NodeJS altogether, so I wrote the above code to accommodate both browser and NodeJS versions. In version 11.0 of NodeJS, both TextEncoder and TextDecoder were made global, which made the first block execute instead of the second. This works fine in a web browser, but in NodeJS, it seems that this.value tends to be a slice of the underlying ArrayBuffer rather than a brand new Uint8Array, so when this.value.subarray(0) is called in NodeJS, it returns the entire underlying ArrayBuffer instead of the slice, which we are expecting to be a copy of this.value.

BER sample to decode

Dear @JonathanWilbur , @hamano

Thanks for this library in native typescript.

BER SAMPLE

I 'd like to know if you could decode this BER file generated by a telecom device.

https://www.dropbox.com/t/qqUueFLO5xOCCCDq

I 'd like to know if the library could support object size > 8M ?

BER DECODING IN JSON file

In the library, it will be great to read a ber file and decode it into json file and vice-versa ?
What do you think ?

Best regards
Joseph

Cannot find module '../../../types/External' from 'decodeExternal.js'

  • Version: 2.8.0
  • Platform: Ubuntu 18.04, using ext4 filesystem
  • Subsystem:

/dist/codecs/x690/decoders/decodeExternal.d.ts has a reference:

import External from "../../../types/External";

However, /dist/types directory only has an external.d.ts file.
On a case sensitive filesystem such as ext4 used on Ubuntu, external.d.ts and External.d.ts are different files.

This causes build error:

Cannot find module '../../../types/External' from 'decodeExternal.js'

It seems that the source file in /source/types is correctly named as External.ts.
Therefore, this is a publishing problem. I guess you are building the tarball on a case insensitive filesystem without clearing the cache.
To fix this problem, delete output folder in your clone, and rebuild from a clean clone.

How to get updated ber?

I am trying to update a value from the decoded ber element. Here is quick snippet (npm RunKit):

const ber = new asn.BERElement();

ber.fromBytes( new Uint8Array( [ 48,12,2,1,1,96,7,2,1,3,4,0,128,0 ] ) );

ber.components[0].integer = ber.sequence[0].integer = 5;

const newBytes = ber.toBytes();

console.assert( ber.components[0].integer === 5 );
console.assert( ber.sequence[0].integer === 5 );
console.assert( newBytes[4] === 5 );

All assertions fail.

How can I update a value and get the final updated structure?

Incorrect OBJECT IDENTIFIER validation

This library incorrectly validates OBJECT IDENTIFIERs.

if
(
((nodes[0] == 0 || nodes[0] == 1) && nodes[2] > 39) ||
(nodes[0] == 2 && nodes[0] > 175)
)

In the lines above, a possibly non-existent third node is checked (having index 2), which is a one-off error. Then, the alternative condition, where the first node is 2, the first node is checked again for being greater than 175, which is obviously contradictory with the first condition. This is two bugs in one expression!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.