jonathanwilbur / asn1-ts Goto Github PK
View Code? Open in Web Editor NEWASN.1 TypeScript library, including codecs for Basic Encoding Rules (BER) and Distinguished Encoding Rules (DER).
License: MIT License
ASN.1 TypeScript library, including codecs for Basic Encoding Rules (BER) and Distinguished Encoding Rules (DER).
License: MIT License
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:
Lines 761 to 762 in 5b05c4e
And here it is in the DER codec:
Lines 720 to 721 in 5b05c4e
And here are the enum definitions:
Lines 6 to 18 in 5b05c4e
This would result in tags being encoded with the incorrect tag numbers.
/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.
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
}```
https://github.com/svkreml/fireFoxTestX509 project Example
(i add it in src/app/app.component.ts)
do you have any regexp in lib?
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
.
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?
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
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:
Line 19 in 951e31b
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
?
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
7.0.6
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 could be one way of solving the issue, as both set
,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());
}
}
This library incorrectly validates OBJECT IDENTIFIER
s.
asn1-ts/source/types/objectidentifier.ts
Lines 12 to 16 in 9f524f5
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!
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)
7.0.4
continue
, instead of should be used for flow controlreturn
,
// 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 until7.0.3
.I understand it is now deprecated, but I had been using it for validation and decode.
I created the ASN1TagClass
enum with an incorrect mapping of names to values. Notice that I accidentally skipped 2 below:
Lines 6 to 12 in b7502f2
This resulted in context-specific tags being encoded as PRIVATE
tag class, and PRIVATE
tag class being encoded as UNIVERSAL
.
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.
Dear @JonathanWilbur , @hamano
Thanks for this library in native typescript.
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 ?
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
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.