ASN1

2.0.3

Abstract Syntax Notation One (ASN1) subset in Swift
leif-ibsen/ASN1

What's New

2022-12-11T12:00:03Z

Richard Moats reported a bug that caused ASN1 to erroneously throw an exception on certain inputs.
He also devised a solution which is now implemented.

Description

The ASN1 package implements a subset of the ASN1 (Abstract Syntax Notation One) specification in Swift. It is intended to be used in writing cryptographic applications like ECIES and ECDSA in Swift.

ASN1 supports:

  • Building ASN1 structures from their byte array representation
  • DER encoding of ASN1 structures
  • Displaying ASN1 structures
  • Definite length encoding and decoding
  • Indefinite length decoding of sets and sequences
  • Tag numbers less than 128
  • Universal (0) and context-specific (2) tag classes

It supports the following ASN1 types:

  • BitString
  • BMPString
  • Boolean
  • GeneralizedTime
  • IA5String
  • Integer
  • Null
  • ObjectIdentifier
  • OctetString
  • PrintableString
  • Sequence
  • Set
  • T61String
  • UTCTime
  • UTF8String

Usage

In your project Package.swift file add a dependency like
  dependencies: [
  .package(url: "https://github.com/leif-ibsen/ASN1", from: "2.0.3"),
  ]

Example 1

Example 1 shows how to decode a byte array containing an ASN1 structure.

import ASN1
import BigInt

// ASN1 encoding of a private key for the brainpoolP160r1 elliptic curve domain
let keyBytes: Bytes = [48, 84, 2, 1, 1, 4, 20, 41, 214, 158, 187, 255, 44, 248,
 248, 164, 95, 252, 51, 1, 186, 40, 137, 9, 116, 150, 79, 160, 11, 6, 9, 43, 36,
  3, 3, 2, 8, 1, 1, 1, 161, 44, 3, 42, 0, 4, 48, 46, 251, 62, 213, 248, 5, 82,
 62, 98, 171, 43, 207, 1, 175, 50, 2, 120, 7, 195, 112, 178, 217, 62, 194, 11,
 215, 59, 27, 221, 93, 51, 231, 135, 77, 120, 34, 107, 185, 154]

// Build the ASN1 structure - we happen to know it is a sequence
let seq = try ASN1.build(keyBytes) as! ASN1Sequence

print(seq)

// Extract the private key value - a large number
let privBytes = seq.get(1) as! ASN1OctetString
let privKey = BInt(magnitude: privBytes.value)

print("Private key =", privKey)

giving

Sequence (4):
  Integer: 1
  Octet String (20): 29 d6 9e bb ff 2c f8 f8 a4 5f fc 33 01 ba 28 89 09 74 96 4f
  [0]:
    Object Identifier: 1.3.36.3.3.2.8.1.1.1
  [1]:
    Bit String (328): 00000100 00110000 00101110 11111011 00111110 11010101 11111000
                      00000101 01010010 00111110 01100010 10101011 00101011 11001111
                      00000001 10101111 00110010 00000010 01111000 00000111 11000011
                      01110000 10110010 11011001 00111110 11000010 00001011 11010111
                      00111011 00011011 11011101 01011101 00110011 11100111 10000111
                      01001101 01111000 00100010 01101011 10111001 10011010

Private key = 238854808789429455904277046626010014418497476175

Example 2

Example 2 shows how to build an ASN1 structure programmatically and encode it to a byte array.

import ASN1
import BigInt

let privKey = BInt("238854808789429455904277046626010014418497476175")!

let seq = ASN1Sequence()
seq.add(ASN1Integer(BInt(1))).add(ASN1OctetString(privKey.asMagnitudeBytes()))
print(seq)

let b = seq.encode()
print("Byte array =", b)

giving

Sequence (2):
  Integer: 1
  Octet String (20): 29 d6 9e bb ff 2c f8 f8 a4 5f fc 33 01 ba 28 89 09 74 96 4f

Byte array = [48, 25, 2, 1, 1, 4, 20, 41, 214, 158, 187, 255, 44, 248,
              248, 164, 95, 252, 51, 1, 186, 40, 137, 9, 116, 150, 79]

Dependencies

ASN1 requires Swift 5.0.

The ASN1 package depends on the BigInt package

dependencies: [
    .package(url: "https://github.com/leif-ibsen/BigInt", from: "1.4.0"),
],

References

  • Burton S. Kaliski Jr.: A Layman's Guide to a Subset of ASN.1, BER, and DER, 1993
  • John Larmouth: ASN.1 Complete, Open Systems Solutions 1999
  • ITU-T Recommendation X.690

Description

  • Swift Tools 5.6.0
View More Packages from this Author

Dependencies

Last updated: Wed Mar 22 2023 04:22:55 GMT-0500 (GMT-05:00)