asn1-ber

Generate and parse ASN1.BER objects

asn1-ber

This project is a clone (not a fork) of the asn1project, and as such is a drop in replacement. The asn1project has received little attention over the past few years and is used in a number of heavily dependant modules (one being my own net-snmpmodule), so I have committed to maintaining this clone and for it to be a drop in replacement.

This module provides the ability to generate and parse ASN1.BER objects.

This module is installed using node package manager (npm):

npm install asn1-ber

It is loaded using the require()function:

var asn1 = require("asn1-ber")

A reader or writer can then be created to read or write objects:

// Let's create an ASN1.BER object using the writing interface:
var writer = new asn1.BerWriter()

writer.startSequence()
writer.writeBoolean(true)
writer.writeBoolean(false)
writer.endSequence()

var buffer = writer.buffer

// Now let's read the data back from the buffer:
var reader = new asn1.BerReader(buffer)

reader.readSequence()
reader.readBoolean() // first boolean is true
reader.readBoolean() // second boolean is false

It is assumed that users are somewhat familiar with ASN1 and BER encoding.

Constants

The following sections describe constants exported and used by this module.

asn1.Ber

This object contains constants which can be used wherever a tagparameter can be provided. For example, the asn1.BerWriter.writeBoolean()method accepts an optional tagparameter. In this method any of the following constants could be used (or a number if the required type is not defined) to specify the tag which be used when encoding the value, and in this particular case would default to asn1.Ber.Boolean, e.g.:

writer.writeBoolean(true, asn1.Ber.Boolean)

The following constants are defined in this object:

  • EOC
  • Boolean
  • Integer
  • BitString
  • OctetString
  • Null
  • OID
  • ObjectDescriptor
  • External
  • Real
  • Enumeration
  • PDV
  • Utf8String
  • RelativeOID
  • Sequence
  • Set
  • NumericString
  • PrintableString
  • T61String
  • VideotexString
  • IA5String
  • UTCTime
  • GeneralizedTime
  • GraphicString
  • VisibleString
  • GeneralString
  • UniversalString
  • CharacterString
  • BMPString
  • Constructor
  • Context
Using This Module

This module exposes two interfaces, one for reading ASN1.BER objects from Node.js Bufferobject instances, and another for writing ASN1.BER objects to Node.js Bufferinstances.

These two interfaces, and all their functions and methods, are documented in seperate sections below.

Writing Objects

Overview

ASN1.BER objects can be generated programatically using various methods. An instance of the BerWriterclass is instantiated and its methods used to do this. Once an object is complete the associated Node.js Bufferobject instance can be obtained by accessing the bufferattribute of the BerWriterobject instance.

In the following example a simple sequence of two boolean objects is written, then the Bufferinstance obtained:

var writer = new asn1.BerWriter()

writer.startSequence()
writer.writeBoolean(true)
writer.writeBoolean(false)
writer.endSequence()

var buffer = writer.buffer

The resulting buffer will contain the following:

var buffer = new Buffer([
        asn1.Ber.Sequence | asn1.Ber.Constructor,
        6, // length of the data contained within the sequence
        asn1.Ber.Boolean,
        1,
        255, // true
        asn1.Ber.Boolean,
        1,
        0, // false
    )

new asn1.BerWriter([options])

Instantiates and returns an instance of the BerWriterclass:

var options = {
    size: 1024,
    growthFactor: 8
}

var writer = new asn1.BerWriter(options)

The optional optionsparameter is an object, and can contain the following items:

  • size- The writer uses a Node.js Bufferinstance to render ASN1.BER types to a binary string, when creating the Bufferinstance its size must be specified, the sizeattribute specifies how bit this buffer should initially be, when the Bufferinstance has not space a new instance will be created which will be larger than the original sizespecified, this growth is controlled by the growthFactorvariable, defaults to 1024
  • growthFactor- When the Node.js Bufferinstance used to render ASN1.BER types to a binary string becomes full the Bufferinstance will be made larger, the size of the new instance is calculated using its current size multiplied by the growthFactorattribute, defaults to 8, for example, with a sizeof 1024and a growthFactorof 8when the Bufferinstance becomes full the new size would be calculated as 8192

writer.buffer

Once an object is complete the Node.js Bufferinstance can be obtained via the writes bufferattribute, e.g.:

var buffer = writer.buffer

The Bufferinstance returned will be a copy of the internal instance used by the writer and can be safely modified once obtained.

writer.startSequence([tag]) & writer.endSequence()

The startSequence()method starts a new sequence. This method can be called multiple times, and a matching call to the endSequence()method must be made for each time startSequence()is called.

The optional tagparameter is one of the constants defined in the asn1.Berobject, or a number if the required type is not pre-defined, and defaults to asn1.Ber.Sequence | asn1.Ber.Constructor.

The following example writes two sequences and a boolean, each nested in the previous:

writer.startSequence()
writer.startSequence()
writer.writeBoolean()
writer.endSequence()
writer.endSequence()

writer.writeBoolean(boolean, [tag])

The writeBoolean()method writes an object of type boolean.

The booleanparameter can be the values trueor false. The optional tagparameter is one of the constants defined in the asn1.Berobject, or a number if the required type is not pre-defined, and defaults to asn1.Ber.Boolean.

The following example writes two different boolean values, and in one case the tagis specified as asn1.Ber.Integer:

writer.writeBoolean(false)
writer.writeBoolean(true, asn1.Ber.Integer)

writer.writeBuffer(buffer, [tag])

The writerBuffer()method writes a Node.js Bufferinstance as a sequence of bytes, i.e. it will interpret it in any way.

The bufferparameter is an instance of the Node.js Bufferclass. The optional tagparameter is one of the constants defined in the asn1.Berobject, or a number if the required type is not pre-defined. If no tag is specified then bufferis assumed to already contain the tag and length for the object to be written, i.e. it is assumed to contain a pre-formatted ASN1.BER object such as a sequence, and will be inserted as is with no tag or length.

The following two examples write a single byte in different ways. One provides a tag, in which case writeBuffer()will write the tag and length, and in the other no tag is provided, so writeBuffer()will NOT write a tag or length:

var b1 = new Buffer([0x01])
writer.writeBuffer(b1, asn1.Ber.Integer)

var b2 = new Buffer([asn1.Ber.Integer, 0x01, 0x01])
writer.writeBuffer(b2)

writer.writeByte(byte)

The writeByte()method writes a single byte, i.e. not tag or length are written.

The byteparameter is an integer in the range 0to 255.

The writeByte()method can be used to insert ad-hoc data into the data stream. The following example writes the integer 2using only the writeByte()method instead of using the writeInt()method:

writer.writeByte(asn1.Ber.Integer) // tag
writer.writeByte(1) // length == 1
writer.writeByte(2) // integer == 2

writer.writeEnumeration(integer, [tag])

The writeEnumeration()method writes the value of an enumerated type.

The integerparameter is the integer value of the enumerated type. The optional tagparameter is one of the constants defined in the asn1.Berobject, or a number if the required type is not pre-defined, and defaults to asn1.Ber.Enumeration.

The following example writes the value 2which identifies a value for an enumerated type:

writer.writeEnumeration(2, asn1.Ber.Enumeration)

writer.writeInt(integer, [tag])

The writeInt()method writes a signed or unsigned integer.

The integerparameter is a signed or unsigned integer of 4 bytes in size. The optional tagparameter is one of the constants defined in the asn1.Berobject, or a number if the required type is not pre-defined, and defaults to asn1.Ber.Integer.

The following example writes the value -123, and since no tag is provided the type asn1.Ber.Integerwill be used:

writer.writeInt(-123)

writer.writeNull()

The writeNull()method writes 2 bytes, the first is the type asn1.Ber.Nulland the second is the 1 byte integer 0.

The following example writes a key and value pair, with the value being specified as undefined using writeNull():

writer.writeString("description") // key is a string
writer.writeNull() // value is undefined

writer.writeOID(oid, [tag])

The writeOID()method writes an object identifier.

The oidparameter is an object identifier in the formar of 1.3.6.1, i.e. dotted decimal. The optional tagparameter is one of the constants defined in the asn1.Berobject, or a number if the required type is not pre-defined, and defaults to asn1.Ber.OID.

The following example writes the object identifier 1.3.6.1, and since no tag is provided the type asn1.Ber.OIDwill be used:

writer.writeOID("1.3.6.1")

writer.writeString(string, [tag])

The writeString()method writes a string.

The stringparameter is a string, i.e. not a Node.js Bufferinstance. The optional tagparameter is one of the constants defined in the asn1.Berobject, or a number if the required type is not pre-defined, and defaults to asn1.Ber.OctetString.

The following example writes the string description, and since no tag is provided the type asn1.Ber.OctetStringwill be used:

writer.writeString("description")

writer.writeStringArray(strings, [tag])

The writeStringArray()method writes multiple strings by called the writeString()method.

The stringsparameter is an array of strings to pass when making repeated calls to the writeString()method. The optional tagparameter is one of the constants defined in the asn1.Berobject, or a number if the required type is not pre-defined, and defaults to asn1.Ber.OctetString.

The following two examples are equivilant, and will both write two strings, and since no tag is provided the type asn1.Ber.OctetStringwill be used:

writer.writeString("one")
writer.writeString("two")

writer.writeStringArray(["one", "two"])

Reading Objects

Overview

The reader interface reads from a Node.js Bufferinstance containing an ASN1.BER object. A number of methods are used to read specific types of data, also ensuring the required tags also exist for each. An instance of the BerReaderclass is instantiated, providing the constructor with a Node.js Bufferinstance, and methods used to do this.

As data is read from the Bufferinstance an offset to the next location from which to read data, i.e. following the last data read, is maintained and incremented based on the amount of data read per method call.

In the following example the appropriate methods are used to read a buffer containing an ASN1.BER object:

var buffer = new Buffer([
        asn1.Ber.Sequence | asn1.Ber.Constructor,
        6, // length of the data contained within the sequence
        asn1.Ber.Boolean,
        1,
        255, // true
        asn1.Ber.Boolean,
        1,
        0, // false
    )

var reader = new asn1.BerReader(buffer)

reader.readSequence(asn1.Ber.Sequence | asn1.Ber.Constructor)
reader.readBoolean() // 1st boolean is true
reader.readBoolean() // 2nd boolean is false

new asn1.BerReader(buffer)

Instantiates and returns an instance of the BerReaderclass:

var reader = new asn1.BerReader(buffer)

The bufferparameter is an instance of the Node.js Bufferclass, this is typically referred to as the "input buffer" throughout this documentation.

reader.peek()

The peek()method is sugar for the following method call:

var byte = reader.readByte(true)

reader.readBoolean([tag])

The readBoolean()method reads a boolean value from the input buffer and returns either trueor false.

The optional tagparameter is one of the constants defined in the asn1.Berobject, or a number if the required type is not pre-defined, and defaults to asn1.Ber.Boolean.

The following example reads a boolean value, since no tag is specified the type asn1.Ber.Booleanis used to validate the type being read:

var bool = reader.readBoolean()

reader.readByte([peek])

The readByte()method reads and returns the next byte from the input buffer, and advances the read offset by 1.

The optional peekparameter, if passed as true, will cause the read offset NOT to be incremented. This provides a way to look at the next byte in the input stream without consuming it.

The following example reads a a boolean value if the next object is of the type asn1.Ber.Boolean:

if (reader.readByte(true) == asn1.Ber.Boolean) {
    reader.readByte() // consume the type
    reader.readByte() // consume length, we assume 1, we /should/ really check

    var value = reader.readByte() ? true : false
}

reader.readEnumeration([tag])

The readEnumeration()method reads an integer value of the enumerated type and returns it.

The optional tagparameter is one of the constants defined in the asn1.Berobject, or a number if the required type is not pre-defined, and defaults to asn1.Ber.Enumeration.

The following example reads an enumerated value, since no tag is specified the type asn1.Ber.Enumerationis used to validate the type being read:

var integer = reader.readEnumeration()

reader.readInt([tag])

The readEnumeration()method reads a signed or unsigned integer and returns it.

The optional tagparameter is one of the constants defined in the asn1.Berobject, or a number if the required type is not pre-defined, and defaults to asn1.Ber.Integer.

The following example reads an integer value, since no tag is specified the type asn1.Ber.Integeris used to validate the type being read:

var integer = reader.readInt()

reader.readOID([tag])

The readOID()method reads an object identifier and returns it in the format 1.3.6.1, i.e. in dotted decimal.

The optional tagparameter is one of the constants defined in the asn1.Berobject, or a number if the required type is not pre-defined, and defaults to asn1.Ber.OID.

The following example reads a object identifier, since no tag is specified the type asn1.Ber.OIDis used to validate the type being read:

var oid = reader.readOID()

reader.readSequence([tag])

The readSequence()method attempts to read the next sequence and its length from the input buffer.

The optional tagparameter is one of the constants defined in the asn1.Berobject, or a number if the required type is not pre-defined. If no tagis defined the type of the sequence is not verified and simply accepted.

If there was not enough data left in the input buffer to read the sequence then nullwill be returned, otherwise the sequences type will be returned, i.e. if tagwas specified then the sequence type will be equal to tag.

The following example reads all sequences, each containing a key and value, until there are no more sequences left:

var kvs = []

while (true) {
    var tag = reader.readSequence() // We don't care about the sequences type
    if (! tag)
        break

    var key = reader.readString()
    var value = reader.readString()

    kvs.push({key: key, value: value})
}

reader.readString([tag], [retbuf])

The readString()method reads a value from the input buffer, and if retbufis specified as truewill return a Node.js Bufferinstance containing the bytes read, otherwise an attempt to parse the data as a utf8string is made and the resulting string will be returned, i.e. not a Bufferinstance.

The optional tagparameter is one of the constants defined in the asn1.Berobject, or a number if the required type is not pre-defined, and defaults to asn1.Ber.OctetString.

The following example reads a string and requests it be returned as a Bufferinstance:

var buffer = reader.readString(asn1.Ber.OctetString, true)
Changes

Version 1.0.0 - 22/07/2017

  • Negative numbers are read when unsigned integers should be used in some places
  • The tagparameter to the Writer.writeBuffer()method in lib/ber/writer.jsshould be optional so that pre-formatted buffers can be written that already include a tag and length
  • The licenseattribute is missing from package.json
  • Create .npmignorefile
  • Correct names of error classes imported and used in lib/ber/writer.jswhich result in not definederror messages
  • Remove require(sys)statement from tst/ber/writer.test.jsbecause it is no longer supported or required
  • Boolean logic error using instanceofin the writeStringArray()method in lib/ber/writer.js
  • Improve documentation
  • Migrate tests to the mocha framework
  • The tagparameter should be optional for methods which imply a type
  • Sort out indentation and use tabs

Version 1.0.1 - 22/07/2017

  • Minor changes to the README.md file

Version 1.0.2 - 01/02/2018

  • The lib/ber/reader.js/Reader.prototype.readInt() method always uses the tag type ASN1.Integer
  • The lib/ber/reader.js/Reader.prototype.readEnumeration() method always uses the tag type ASN1.Enumeration

Version 1.0.3 - 06/06/2018

  • Added NoSpaceships Ltd as a maintainer

Version 1.0.6 - 06/06/2018

  • Transfer to NoSpaceships github account

Version 1.0.7 - 06/06/2018

  • Update author to NoSpaceships

Version 1.0.9 - 07/06/2018

  • Remove redundant sections from README.md
License

Copyright (c) 2018 NoSpaceships Ltd hello@nospaceships.com

Copyright (c) 2017 Stephen Vickers stephen.vickers.sv@gmail.com

Copyright (c) 2011 Mark Cavage mcavage@gmail.com

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Repository

https://github.com/nospaceships/node-asn1-ber


上一篇:ngeohash
下一篇:net-snmp

相关推荐

  • 零代码深入浅出React并发模式,带你理解React Fiber架构

    React Fiber架构有一定的复杂度,如果硬着头皮去啃源码,我们会深陷于庞大的代码量和实现细节之中,往往学不到什么东西。 React并发模式是ReactFiber架构的重要应用,本文不贴任何Rea...

    4 个月前
  • 记isNaN与Number.isNaN的区别

    有一次项目中发现原来isNaN和Number.isNaN是有着不一样的判断结果。记录一下避免下次踩坑。 要了解他们的区别,首先得明确NaN到底是什么? 在MDN的官方解释中 NaN是一个全局...

    2 年前
  • 视图与组件ember.js

    Bradley Trager(https://stackoverflow.com/users/1864510/bradleytrager)提出了一个问题:Views vs Components in ...

    2 年前
  • 移动端苹果手机的input框type= number只是唤起数字键盘,但是还能输入汉字

    1、今天临下班之前测试突然测出这个BUG,一开始还觉得纳闷,input已经设置成number了啊,为啥还是可以输入汉字,效果复现之后,蒙蔽了,WC;    搜了很多资料发现只有IOS才有这个问题,试了...

    2 个月前
  • 理解 React Fiber & Concurrent Mode

    抛出问题 React 目前主要的问题有两个 reactcpuio.jpg(/public/upload/51e1950d6adee552bb72d8f4cb1b2482) 页面在大量 DOM...

    3 个月前
  • 深入了解 Number 类型

    Number 类型作为 JS 的基本数据类型之一,被应用在程序中的各种场景,其重要性就如数字对于我们日常生活。 下面就让我们来一起深入了解下,为以后的“策马奔腾”做好铺垫。

    2 年前
  • 深入react-fiber数据结构

    前言 上一篇介绍了reactdom,再往后面写很多都是在操作FiberRoot和Fiber这两个数据结构,这里简单的介绍一下,另外希望大家可以把他当成一个普通的数据结构来看,暂时不要把它跟react里...

    3 个月前
  • 深入FiberRoot

    1. 介绍 整个应用的起点 包含应用挂载的目标起点 记录整个应用更新过程的各种信息 2.相关函数及内容 在中我们返回了函数的执行结果, 然就在ReactFiberRoo...

    1 年前
  • 浅谈ReactFiber

    1. 什么是fiber 每一个ReactElement都有一个对应的fiber, 记录这个节点的各种状态, fiber是一链表的结构的串联起来。 fibertree.png(https://img...

    1 年前
  • 浅谈React16框架 - Fiber

    Fiber核心是实现了一个基于优先级和requestIdleCallback的循环任务调度算法。它包含以下特性:(参考:fiberreconciler) reconciliation阶段可...

    2 年前

官方社区

扫码加入 JavaScript 社区