GithubHelp home page GithubHelp logo

jonathanwilbur / asn1-ts Goto Github PK

View Code? Open in Web Editor NEW
32.0 3.0 6.0 2.92 MB

ASN.1 TypeScript library, including codecs for Basic Encoding Rules (BER) and Distinguished Encoding Rules (DER).

License: MIT License

TypeScript 100.00%
asn1 ber der typescript

asn1-ts's People

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

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.

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.

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
}```

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.

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?

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?

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

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!

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)

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.

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.

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.

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

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.