215 lines
7.2 KiB
Nim
215 lines
7.2 KiB
Nim
|
## Nim-Libp2p
|
||
|
## Copyright (c) 2018 Status Research & Development GmbH
|
||
|
## Licensed under either of
|
||
|
## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
|
||
|
## * MIT license ([LICENSE-MIT](LICENSE-MIT))
|
||
|
## at your option.
|
||
|
## This file may not be copied, modified, or distributed except according to
|
||
|
## those terms.
|
||
|
import unittest
|
||
|
import ../libp2p/crypto/minasn1
|
||
|
import nimcrypto/utils as ncrutils
|
||
|
|
||
|
when defined(nimHasUsed): {.used.}
|
||
|
|
||
|
const Asn1EdgeValues = [
|
||
|
0'u64, (1'u64 shl 7) - 1'u64,
|
||
|
(1'u64 shl 7), (1'u64 shl 8) - 1'u64,
|
||
|
(1'u64 shl 8), (1'u64 shl 16) - 1'u64,
|
||
|
(1'u64 shl 16), (1'u64 shl 24) - 1'u64,
|
||
|
(1'u64 shl 24), (1'u64 shl 32) - 1'u64,
|
||
|
(1'u64 shl 32), (1'u64 shl 40) - 1'u64,
|
||
|
(1'u64 shl 40), (1'u64 shl 48) - 1'u64,
|
||
|
(1'u64 shl 48), (1'u64 shl 56) - 1'u64,
|
||
|
(1'u64 shl 56), 0xFFFF_FFFF_FFFF_FFFF'u64
|
||
|
]
|
||
|
|
||
|
const Asn1EdgeExpects = [
|
||
|
"00", "7F",
|
||
|
"8180", "81FF",
|
||
|
"820100", "82FFFF",
|
||
|
"83010000", "83FFFFFF",
|
||
|
"8401000000", "84FFFFFFFF",
|
||
|
"850100000000", "85FFFFFFFFFF",
|
||
|
"86010000000000", "86FFFFFFFFFFFF",
|
||
|
"8701000000000000", "87FFFFFFFFFFFFFF",
|
||
|
"880100000000000000", "88FFFFFFFFFFFFFFFF",
|
||
|
]
|
||
|
|
||
|
const Asn1UIntegerValues8 = [
|
||
|
0x00'u8, 0x7F'u8, 0x80'u8, 0xFF'u8,
|
||
|
]
|
||
|
|
||
|
const Asn1UIntegerExpects8 = [
|
||
|
"020100", "02017F", "02020080", "020200FF"
|
||
|
]
|
||
|
|
||
|
const Asn1UIntegerValues16 = [
|
||
|
0x00'u16, 0x7F'u16, 0x80'u16, 0xFF'u16,
|
||
|
0x7FFF'u16, 0x8000'u16, 0xFFFF'u16
|
||
|
]
|
||
|
|
||
|
const Asn1UIntegerExpects16 = [
|
||
|
"020100", "02017F", "02020080", "020200FF", "02027FFF",
|
||
|
"0203008000", "020300FFFF"
|
||
|
]
|
||
|
|
||
|
const Asn1UIntegerValues32 = [
|
||
|
0x00'u32, 0x7F'u32, 0x80'u32, 0xFF'u32,
|
||
|
0x7FFF'u32, 0x8000'u32, 0xFFFF'u32,
|
||
|
0x7FFF_FFFF'u32, 0x8000_0000'u32, 0xFFFF_FFFF'u32
|
||
|
]
|
||
|
|
||
|
const Asn1UIntegerExpects32 = [
|
||
|
"020100", "02017F", "02020080", "020200FF", "02027FFF",
|
||
|
"0203008000", "020300FFFF", "02047FFFFFFF", "02050080000000",
|
||
|
"020500FFFFFFFF"
|
||
|
]
|
||
|
|
||
|
const Asn1UIntegerValues64 = [
|
||
|
0x00'u64, 0x7F'u64, 0x80'u64, 0xFF'u64,
|
||
|
0x7FFF'u64, 0x8000'u64, 0xFFFF'u64,
|
||
|
0x7FFF_FFFF'u64, 0x8000_0000'u64, 0xFFFF_FFFF'u64,
|
||
|
0x7FFF_FFFF_FFFF_FFFF'u64, 0x8000_0000_0000_0000'u64,
|
||
|
0xFFFF_FFFF_FFFF_FFFF'u64
|
||
|
]
|
||
|
|
||
|
const Asn1UIntegerExpects64 = [
|
||
|
"020100", "02017F", "02020080", "020200FF", "02027FFF",
|
||
|
"0203008000", "020300FFFF", "02047FFFFFFF", "02050080000000",
|
||
|
"020500FFFFFFFF", "02087FFFFFFFFFFFFFFF", "0209008000000000000000",
|
||
|
"020900FFFFFFFFFFFFFFFF"
|
||
|
]
|
||
|
|
||
|
suite "Minimal ASN.1 encode/decode suite":
|
||
|
test "Length encoding edge values":
|
||
|
var empty = newSeq[byte](0)
|
||
|
for i in 0 ..< len(Asn1EdgeValues):
|
||
|
var value = newSeq[byte](9)
|
||
|
let r1 = asn1EncodeLength(empty, Asn1EdgeValues[i])
|
||
|
let r2 = asn1EncodeLength(value, Asn1EdgeValues[i])
|
||
|
value.setLen(r2)
|
||
|
check:
|
||
|
r1 == (len(Asn1EdgeExpects[i]) shr 1)
|
||
|
r2 == (len(Asn1EdgeExpects[i]) shr 1)
|
||
|
check:
|
||
|
ncrutils.fromHex(Asn1EdgeExpects[i]) == value
|
||
|
|
||
|
test "ASN.1 DER INTEGER encoding/decoding of native unsigned values test":
|
||
|
proc decodeBuffer(data: openarray[byte]): uint64 =
|
||
|
var ab = Asn1Buffer.init(data)
|
||
|
let fres = ab.read()
|
||
|
doAssert(fres.isOk() and fres.get().kind == Asn1Tag.Integer)
|
||
|
fres.get().vint
|
||
|
|
||
|
proc encodeInteger[T](value: T): seq[byte] =
|
||
|
var buffer = newSeq[byte](16)
|
||
|
let res = asn1EncodeInteger(buffer, value)
|
||
|
buffer.setLen(res)
|
||
|
buffer
|
||
|
|
||
|
for i in 0 ..< len(Asn1UIntegerValues8):
|
||
|
let buffer = encodeInteger(Asn1UIntegerValues8[i])
|
||
|
check:
|
||
|
toHex(buffer) == Asn1UIntegerExpects8[i]
|
||
|
decodeBuffer(buffer) == uint64(Asn1UIntegerValues8[i])
|
||
|
|
||
|
for i in 0 ..< len(Asn1UIntegerValues16):
|
||
|
let buffer = encodeInteger(Asn1UIntegerValues16[i])
|
||
|
check:
|
||
|
toHex(buffer) == Asn1UIntegerExpects16[i]
|
||
|
decodeBuffer(buffer) == uint64(Asn1UIntegerValues16[i])
|
||
|
|
||
|
for i in 0 ..< len(Asn1UIntegerValues32):
|
||
|
let buffer = encodeInteger(Asn1UIntegerValues32[i])
|
||
|
check:
|
||
|
toHex(buffer) == Asn1UIntegerExpects32[i]
|
||
|
decodeBuffer(buffer) == uint64(Asn1UIntegerValues32[i])
|
||
|
|
||
|
for i in 0 ..< len(Asn1UIntegerValues64):
|
||
|
let buffer = encodeInteger(Asn1UIntegerValues64[i])
|
||
|
check:
|
||
|
toHex(buffer) == Asn1UIntegerExpects64[i]
|
||
|
decodeBuffer(buffer) == uint64(Asn1UIntegerValues64[i])
|
||
|
|
||
|
test "ASN.1 DER INTEGER incorrect values decoding test":
|
||
|
proc decodeBuffer(data: string): Asn1Result[Asn1Field] =
|
||
|
var ab = Asn1Buffer.init(fromHex(data))
|
||
|
ab.read()
|
||
|
|
||
|
check:
|
||
|
decodeBuffer("0200").error == Asn1Error.Incorrect
|
||
|
decodeBuffer("0201").error == Asn1Error.Incomplete
|
||
|
decodeBuffer("02020000").error == Asn1Error.Incorrect
|
||
|
decodeBuffer("0203000001").error == Asn1Error.Incorrect
|
||
|
|
||
|
test "ASN.1 DER BITSTRING encoding/decoding with unused bits test":
|
||
|
proc encodeBits(value: string, bitsUsed: int): seq[byte] =
|
||
|
var buffer = newSeq[byte](16)
|
||
|
let res = asn1EncodeBitString(buffer, fromHex(value), bitsUsed)
|
||
|
buffer.setLen(res)
|
||
|
buffer
|
||
|
|
||
|
proc decodeBuffer(data: string): Asn1Field =
|
||
|
var ab = Asn1Buffer.init(fromHex(data))
|
||
|
let fres = ab.read()
|
||
|
doAssert(fres.isOk() and fres.get().kind == Asn1Tag.BitString)
|
||
|
fres.get()
|
||
|
|
||
|
check:
|
||
|
toHex(encodeBits("FF", 7)) == "03020780"
|
||
|
toHex(encodeBits("FF", 6)) == "030206C0"
|
||
|
toHex(encodeBits("FF", 5)) == "030205E0"
|
||
|
toHex(encodeBits("FF", 4)) == "030204F0"
|
||
|
toHex(encodeBits("FF", 3)) == "030203F8"
|
||
|
toHex(encodeBits("FF", 2)) == "030202FC"
|
||
|
toHex(encodeBits("FF", 1)) == "030201FE"
|
||
|
toHex(encodeBits("FF", 0)) == "030200FF"
|
||
|
|
||
|
let f0 = decodeBuffer("030200FF")
|
||
|
let f0b = @(f0.buffer.toOpenArray(f0.offset, f0.offset + f0.length - 1))
|
||
|
let f1 = decodeBuffer("030201FE")
|
||
|
let f1b = @(f1.buffer.toOpenArray(f1.offset, f1.offset + f1.length - 1))
|
||
|
let f2 = decodeBuffer("030202FC")
|
||
|
let f2b = @(f2.buffer.toOpenArray(f2.offset, f2.offset + f2.length - 1))
|
||
|
let f3 = decodeBuffer("030203F8")
|
||
|
let f3b = @(f3.buffer.toOpenArray(f3.offset, f3.offset + f3.length - 1))
|
||
|
let f4 = decodeBuffer("030204F0")
|
||
|
let f4b = @(f4.buffer.toOpenArray(f4.offset, f4.offset + f4.length - 1))
|
||
|
let f5 = decodeBuffer("030205E0")
|
||
|
let f5b = @(f5.buffer.toOpenArray(f5.offset, f5.offset + f5.length - 1))
|
||
|
let f6 = decodeBuffer("030206C0")
|
||
|
let f6b = @(f6.buffer.toOpenArray(f6.offset, f6.offset + f6.length - 1))
|
||
|
let f7 = decodeBuffer("03020780")
|
||
|
let f7b = @(f7.buffer.toOpenArray(f7.offset, f7.offset + f7.length - 1))
|
||
|
|
||
|
check:
|
||
|
f0.ubits == 0
|
||
|
toHex(f0b) == "FF"
|
||
|
f1.ubits == 1
|
||
|
toHex(f1b) == "FE"
|
||
|
f2.ubits == 2
|
||
|
toHex(f2b) == "FC"
|
||
|
f3.ubits == 3
|
||
|
toHex(f3b) == "F8"
|
||
|
f4.ubits == 4
|
||
|
toHex(f4b) == "F0"
|
||
|
f5.ubits == 5
|
||
|
toHex(f5b) == "E0"
|
||
|
f6.ubits == 6
|
||
|
toHex(f6b) == "C0"
|
||
|
f7.ubits == 7
|
||
|
toHex(f7b) == "80"
|
||
|
|
||
|
test "ASN.1 DER BITSTRING incorrect values decoding test":
|
||
|
proc decodeBuffer(data: string): Asn1Result[Asn1Field] =
|
||
|
var ab = Asn1Buffer.init(fromHex(data))
|
||
|
ab.read()
|
||
|
|
||
|
check:
|
||
|
decodeBuffer("0300").error == Asn1Error.Incorrect
|
||
|
decodeBuffer("030180").error == Asn1Error.Incorrect
|
||
|
decodeBuffer("030107").error == Asn1Error.Incorrect
|
||
|
decodeBuffer("030200").error == Asn1Error.Incomplete
|
||
|
decodeBuffer("030208FF").error == Asn1Error.Incorrect
|