On this page:
write-asn1
read-asn1
asn1->bytes
bytes->asn1
write-asn1/  DER
read-asn1/  DER
asn1->bytes/  DER
bytes->asn1/  DER
3.1 BER Utilities
BER-frame
BER-encode
BER-decode
write-BER-frame
read-BER-frame

3 ASN.1 Encoding and Decoding

This library supports the Basic Encoding Rules (BER) for ASN.1 as well as its restricted form, the Distinguished Encoding Rules (DER).

A BER encoding is logically a tag, length, value (TLV) triple. The tag indicates to what type the value belongs (or at least disambiguates; the tag is often context-specific). The tag also indicates whether the encoding is primitive or constructedthat is, consisting of a sequence of TLV triples. The length indicates the length of the value encoding, so even unknown types can be decomposed into TLV triples. The value component contains a type-specific encoding of the value. For example, integers are encoded in big-endian, base-256, two’s-complement form using a minimal number of octets.

procedure

(write-asn1 type value [out #:rules rules])  void?

  type : asn1-type?
  value : any/c
  out : output-port? = (current-output-port)
  rules : (or/c 'BER 'DER) = 'BER
Writes to out the encoding of value as an instance of the given ASN.1 type, using the specified encoding rules.

procedure

(read-asn1 type [in #:rules rules])  any/c

  type : asn1-type?
  in : input-port? = (current-input-port)
  rules : (or/c 'BER 'DER) = 'BER
Reads a value of the given ASN.1 type from in, using the specified encoding rules.

procedure

(asn1->bytes type value [#:rules rules])  bytes?

  type : asn1-type?
  value : any/c
  rules : (or/c 'BER 'DER) = 'BER
Encodes value as an instance of the given ASN.1 type, using the specified encoding rules.

procedure

(bytes->asn1 type bstr [#:rules rules])  any/c

  type : asn1-type?
  bstr : bytes?
  rules : (or/c 'BER 'DER) = 'BER
Decodes bstr as an instance of the given ASN.1 type, using the specified encoding rules.

procedure

(write-asn1/DER type value [out])  void?

  type : asn1-type?
  value : any/c
  out : output-port? = (current-output-port)

procedure

(read-asn1/DER type [in])  any/c

  type : asn1-type?
  in : input-port? = (current-input-port)

procedure

(asn1->bytes/DER type value)  bytes?

  type : asn1-type?
  value : any/c

procedure

(bytes->asn1/DER type bstr)  any/c

  type : asn1-type?
  bstr : bytes?
Like write-asn1, read-asn1, asn1->bytes, and bytes->asn1, respectively, but use the DER encoding rules.

Equivalent to calling the corresponding procedure with #:rules 'DER.

> (define Integers (SEQUENCE-OF INTEGER))
> (asn1->bytes Integers '(1 2 3 -1000))

#"0\200\2\1\1\2\1\2\2\1\3\2\2\374\30\0\0"

> (asn1->bytes Integers '(1 2 3 -1000) #:rules 'DER)

#"0\r\2\1\1\2\1\2\2\1\3\2\2\374\30"

> (asn1->bytes/DER Integers '(1 2 3 -1000))

#"0\r\2\1\1\2\1\2\2\1\3\2\2\374\30"

3.1 BER Utilities

 (require asn1/ber) package: asn1-lib

struct

(struct BER-frame (tag-class tag-number value))

  tag-class : (or/c 'universal 'private 'application 'context-sensitive)
  tag-number : exact-nonnegative-integer?
  value : (or/c bytes? (listof (or/c bytes? BER-frame?)))
Represents a decomposed TLV triple. The tag is broken down into the tagclass and tagn fields. The length is not represented; it is implicit in the value field. The value is a list for “constructed” types and a bytestring for “primitive” types.

procedure

(BER-encode type v [#:der? der?])  BER-frame?

  type : asn1-type?
  v : any/c
  der? : boolean? = #f

procedure

(BER-decode type b [#:der? der?])  any/c

  type : asn1-type?
  b : BER-frame?
  der? : boolean? = #f
Encode or decode a value of the given ASN.1 type to a BER TLV frame.

> (BER-encode INTEGER 5)

(BER-frame 'universal 2 #"\5")

> (BER-decode INTEGER (BER-frame 'universal 2 #"\5"))

5

> (BER-encode (SEQUENCE-OF INTEGER) '(1 2 3 -1000))

(BER-frame

 'universal 16

 (list

  (BER-frame 'universal 2 #"\1")

  (BER-frame 'universal 2 #"\2")

  (BER-frame 'universal 2 #"\3")

  (BER-frame 'universal 2 #"\374\30")))

> (BER-encode (SEQUENCE [a IA5String] [b INTEGER])
              (hasheq 'a "Jean" 'b 24601))

(BER-frame

 'universal 16

 (list (BER-frame 'universal 22 #"Jean") (BER-frame 'universal 2 #"`\31")))

procedure

(write-BER-frame frame [out #:rules rules])  void?

  frame : BER-frame?
  out : output-port? = (current-output-port)
  rules : (or/c 'BER 'DER) = 'BER

procedure

(read-BER-frame [in #:rules rules])  BER-frame?

  in : input-port? = (current-input-port)
  rules : (or/c 'BER 'DER) = 'BER
Write or read a BER TLV frame, respectively.