Use Result construct in minasn1 (#144)
This commit is contained in:
parent
6ae92eb21a
commit
1c4d72f5e3
|
@ -12,6 +12,8 @@ import rsa, ecnist, ed25519/ed25519, secp
|
|||
import ../protobuf/minprotobuf, ../vbuffer, ../multihash, ../multicodec
|
||||
import nimcrypto/[rijndael, blowfish, twofish, sha, sha2, hash, hmac, utils]
|
||||
import ../utility
|
||||
import stew/results
|
||||
export results
|
||||
|
||||
# This is workaround for Nim's `import` bug
|
||||
export rijndael, blowfish, twofish, sha, sha2, hash, hmac, utils
|
||||
|
@ -263,7 +265,7 @@ proc init*(key: var PrivateKey, data: openarray[byte]): bool =
|
|||
var scheme = cast[PKScheme](cast[int8](id))
|
||||
var nkey = PrivateKey(scheme: scheme)
|
||||
if scheme == RSA:
|
||||
if init(nkey.rsakey, buffer) == Asn1Status.Success:
|
||||
if init(nkey.rsakey, buffer).isOk:
|
||||
key = nkey
|
||||
result = true
|
||||
elif scheme == Ed25519:
|
||||
|
@ -271,7 +273,7 @@ proc init*(key: var PrivateKey, data: openarray[byte]): bool =
|
|||
key = nkey
|
||||
result = true
|
||||
elif scheme == ECDSA:
|
||||
if init(nkey.eckey, buffer) == Asn1Status.Success:
|
||||
if init(nkey.eckey, buffer).isOk:
|
||||
key = nkey
|
||||
result = true
|
||||
elif scheme == Secp256k1:
|
||||
|
@ -294,7 +296,7 @@ proc init*(key: var PublicKey, data: openarray[byte]): bool =
|
|||
var scheme = cast[PKScheme](cast[int8](id))
|
||||
var nkey = PublicKey(scheme: scheme)
|
||||
if scheme == RSA:
|
||||
if init(nkey.rsakey, buffer) == Asn1Status.Success:
|
||||
if init(nkey.rsakey, buffer).isOk:
|
||||
key = nkey
|
||||
result = true
|
||||
elif scheme == Ed25519:
|
||||
|
@ -302,7 +304,7 @@ proc init*(key: var PublicKey, data: openarray[byte]): bool =
|
|||
key = nkey
|
||||
result = true
|
||||
elif scheme == ECDSA:
|
||||
if init(nkey.eckey, buffer) == Asn1Status.Success:
|
||||
if init(nkey.eckey, buffer).isOk:
|
||||
key = nkey
|
||||
result = true
|
||||
elif scheme == Secp256k1:
|
||||
|
@ -484,7 +486,7 @@ proc verify*(sig: Signature, message: openarray[byte],
|
|||
## Return ``true`` if message signature is valid.
|
||||
if key.scheme == RSA:
|
||||
var signature: RsaSignature
|
||||
if signature.init(sig.data) == Asn1Status.Success:
|
||||
if signature.init(sig.data).isOk:
|
||||
result = signature.verify(message, key.rsakey)
|
||||
elif key.scheme == Ed25519:
|
||||
var signature: EdSignature
|
||||
|
@ -492,7 +494,7 @@ proc verify*(sig: Signature, message: openarray[byte],
|
|||
result = signature.verify(message, key.edkey)
|
||||
elif key.scheme == ECDSA:
|
||||
var signature: EcSignature
|
||||
if signature.init(sig.data) == Asn1Status.Success:
|
||||
if signature.init(sig.data).isOk:
|
||||
result = signature.verify(message, key.eckey)
|
||||
elif key.scheme == Secp256k1:
|
||||
var signature: SkSignature
|
||||
|
|
|
@ -17,7 +17,9 @@
|
|||
import bearssl
|
||||
import nimcrypto/utils
|
||||
import minasn1
|
||||
export minasn1.Asn1Status
|
||||
export minasn1.Asn1Error
|
||||
import stew/results
|
||||
export results
|
||||
|
||||
const
|
||||
PubKey256Length* = 65
|
||||
|
@ -529,43 +531,39 @@ proc `==`*(sig1, sig2: EcSignature): bool =
|
|||
else:
|
||||
result = (sig1.buffer == sig2.buffer)
|
||||
|
||||
proc init*(key: var EcPrivateKey, data: openarray[byte]): Asn1Status =
|
||||
proc init*(key: var EcPrivateKey, data: openarray[byte]): Result[void, Asn1Error] =
|
||||
## Initialize EC `private key` or `signature` ``key`` from ASN.1 DER binary
|
||||
## representation ``data``.
|
||||
##
|
||||
## Procedure returns ``Asn1Status``.
|
||||
## Procedure returns ``Result[void, Asn1Error]``.
|
||||
var raw, oid, field: Asn1Field
|
||||
var curve: cint
|
||||
|
||||
var ab = Asn1Buffer.init(data)
|
||||
|
||||
result = ab.read(field)
|
||||
if result != Asn1Status.Success:
|
||||
return
|
||||
field = ? ab.read()
|
||||
|
||||
if field.kind != Asn1Tag.Sequence:
|
||||
return Asn1Status.Incorrect
|
||||
return err(Asn1Error.Incorrect)
|
||||
|
||||
var ib = field.getBuffer()
|
||||
|
||||
result = ib.read(field)
|
||||
if result != Asn1Status.Success:
|
||||
return
|
||||
field = ? ib.read()
|
||||
|
||||
if field.kind != Asn1Tag.Integer:
|
||||
return Asn1Status.Incorrect
|
||||
return err(Asn1Error.Incorrect)
|
||||
if field.vint != 1'u64:
|
||||
return Asn1Status.Incorrect
|
||||
return err(Asn1Error.Incorrect)
|
||||
|
||||
raw = ? ib.read()
|
||||
|
||||
result = ib.read(raw)
|
||||
if result != Asn1Status.Success:
|
||||
return
|
||||
if raw.kind != Asn1Tag.OctetString:
|
||||
return Asn1Status.Incorrect
|
||||
return err(Asn1Error.Incorrect)
|
||||
|
||||
oid = ? ib.read()
|
||||
|
||||
result = ib.read(oid)
|
||||
if result != Asn1Status.Success:
|
||||
return
|
||||
if oid.kind != Asn1Tag.Oid:
|
||||
return Asn1Status.Incorrect
|
||||
return err(Asn1Error.Incorrect)
|
||||
|
||||
if oid == Asn1OidSecp256r1:
|
||||
curve = cast[cint](Secp256r1)
|
||||
|
@ -574,7 +572,7 @@ proc init*(key: var EcPrivateKey, data: openarray[byte]): Asn1Status =
|
|||
elif oid == Asn1OidSecp521r1:
|
||||
curve = cast[cint](Secp521r1)
|
||||
else:
|
||||
return Asn1Status.Incorrect
|
||||
return err(Asn1Error.Incorrect)
|
||||
|
||||
if checkScalar(raw.toOpenArray(), curve) == 1'u32:
|
||||
key = new EcPrivateKey
|
||||
|
@ -583,47 +581,44 @@ proc init*(key: var EcPrivateKey, data: openarray[byte]): Asn1Status =
|
|||
key.key.x = cast[ptr cuchar](addr key.buffer[0])
|
||||
key.key.xlen = raw.length
|
||||
key.key.curve = curve
|
||||
result = Asn1Status.Success
|
||||
ok()
|
||||
else:
|
||||
result = Asn1Status.Incorrect
|
||||
err(Asn1Error.Incorrect)
|
||||
|
||||
proc init*(pubkey: var EcPublicKey, data: openarray[byte]): Asn1Status =
|
||||
proc init*(pubkey: var EcPublicKey, data: openarray[byte]): Result[void, Asn1Error] =
|
||||
## Initialize EC public key ``pubkey`` from ASN.1 DER binary representation
|
||||
## ``data``.
|
||||
##
|
||||
## Procedure returns ``Asn1Status``.
|
||||
## Procedure returns ``Result[void, Asn1Error]``.
|
||||
var raw, oid, field: Asn1Field
|
||||
var curve: cint
|
||||
|
||||
var ab = Asn1Buffer.init(data)
|
||||
result = ab.read(field)
|
||||
if result != Asn1Status.Success:
|
||||
return
|
||||
|
||||
field = ? ab.read()
|
||||
|
||||
if field.kind != Asn1Tag.Sequence:
|
||||
return Asn1Status.Incorrect
|
||||
return err(Asn1Error.Incorrect)
|
||||
|
||||
var ib = field.getBuffer()
|
||||
result = ib.read(field)
|
||||
if result != Asn1Status.Success:
|
||||
return
|
||||
field = ? ib.read()
|
||||
|
||||
if field.kind != Asn1Tag.Sequence:
|
||||
return Asn1Status.Incorrect
|
||||
return err(Asn1Error.Incorrect)
|
||||
|
||||
var ob = field.getBuffer()
|
||||
result = ob.read(oid)
|
||||
if result != Asn1Status.Success:
|
||||
return
|
||||
oid = ? ob.read()
|
||||
|
||||
if oid.kind != Asn1Tag.Oid:
|
||||
return Asn1Status.Incorrect
|
||||
return err(Asn1Error.Incorrect)
|
||||
|
||||
if oid != Asn1OidEcPublicKey:
|
||||
return Asn1Status.Incorrect
|
||||
return err(Asn1Error.Incorrect)
|
||||
|
||||
oid = ? ob.read()
|
||||
|
||||
result = ob.read(oid)
|
||||
if result != Asn1Status.Success:
|
||||
return
|
||||
if oid.kind != Asn1Tag.Oid:
|
||||
return Asn1Status.Incorrect
|
||||
return err(Asn1Error.Incorrect)
|
||||
|
||||
if oid == Asn1OidSecp256r1:
|
||||
curve = cast[cint](Secp256r1)
|
||||
|
@ -632,13 +627,12 @@ proc init*(pubkey: var EcPublicKey, data: openarray[byte]): Asn1Status =
|
|||
elif oid == Asn1OidSecp521r1:
|
||||
curve = cast[cint](Secp521r1)
|
||||
else:
|
||||
return Asn1Status.Incorrect
|
||||
return err(Asn1Error.Incorrect)
|
||||
|
||||
raw = ? ib.read()
|
||||
|
||||
result = ib.read(raw)
|
||||
if result != Asn1Status.Success:
|
||||
return
|
||||
if raw.kind != Asn1Tag.BitString:
|
||||
return Asn1Status.Incorrect
|
||||
return err(Asn1Error.Incorrect)
|
||||
|
||||
if checkPublic(raw.toOpenArray(), curve) != 0:
|
||||
pubkey = new EcPublicKey
|
||||
|
@ -647,50 +641,51 @@ proc init*(pubkey: var EcPublicKey, data: openarray[byte]): Asn1Status =
|
|||
pubkey.key.q = cast[ptr cuchar](addr pubkey.buffer[0])
|
||||
pubkey.key.qlen = raw.length
|
||||
pubkey.key.curve = curve
|
||||
result = Asn1Status.Success
|
||||
ok()
|
||||
else:
|
||||
result = Asn1Status.Incorrect
|
||||
err(Asn1Error.Incorrect)
|
||||
|
||||
proc init*(sig: var EcSignature, data: openarray[byte]): Asn1Status =
|
||||
proc init*(sig: var EcSignature, data: openarray[byte]): Result[void, Asn1Error] =
|
||||
## Initialize EC signature ``sig`` from raw binary representation ``data``.
|
||||
##
|
||||
## Procedure returns ``Asn1Status``.
|
||||
result = Asn1Status.Incorrect
|
||||
## Procedure returns ``Result[void, Asn1Error]``.
|
||||
if len(data) > 0:
|
||||
sig = new EcSignature
|
||||
sig.buffer = @data
|
||||
result = Asn1Status.Success
|
||||
ok()
|
||||
else:
|
||||
err(Asn1Error.Incorrect)
|
||||
|
||||
proc init*[T: EcPKI](sospk: var T, data: string): Asn1Status {.inline.} =
|
||||
proc init*[T: EcPKI](sospk: var T, data: string): Result[void, Asn1Error] {.inline.} =
|
||||
## Initialize EC `private key`, `public key` or `signature` ``sospk`` from
|
||||
## ASN.1 DER hexadecimal string representation ``data``.
|
||||
##
|
||||
## Procedure returns ``Asn1Status``.
|
||||
result = sospk.init(fromHex(data))
|
||||
sospk.init(fromHex(data))
|
||||
|
||||
proc init*(t: typedesc[EcPrivateKey], data: openarray[byte]): EcPrivateKey =
|
||||
## Initialize EC private key from ASN.1 DER binary representation ``data`` and
|
||||
## return constructed object.
|
||||
let res = result.init(data)
|
||||
if res != Asn1Status.Success:
|
||||
if res.isErr:
|
||||
raise newException(EcKeyIncorrectError,
|
||||
"Incorrect private key (" & $res & ")")
|
||||
"Incorrect private key (" & $res.error & ")")
|
||||
|
||||
proc init*(t: typedesc[EcPublicKey], data: openarray[byte]): EcPublicKey =
|
||||
## Initialize EC public key from ASN.1 DER binary representation ``data`` and
|
||||
## return constructed object.
|
||||
let res = result.init(data)
|
||||
if res != Asn1Status.Success:
|
||||
if res.isErr:
|
||||
raise newException(EcKeyIncorrectError,
|
||||
"Incorrect public key (" & $res & ")")
|
||||
"Incorrect public key (" & $res.error & ")")
|
||||
|
||||
proc init*(t: typedesc[EcSignature], data: openarray[byte]): EcSignature =
|
||||
## Initialize EC signature from raw binary representation ``data`` and
|
||||
## return constructed object.
|
||||
let res = result.init(data)
|
||||
if res != Asn1Status.Success:
|
||||
if res.isErr:
|
||||
raise newException(EcKeyIncorrectError,
|
||||
"Incorrect signature (" & $res & ")")
|
||||
"Incorrect signature (" & $res.error & ")")
|
||||
|
||||
proc init*[T: EcPKI](t: typedesc[T], data: string): T {.inline.} =
|
||||
## Initialize EC `private key`, `public key` or `signature` from hexadecimal
|
||||
|
|
|
@ -8,13 +8,17 @@
|
|||
## those terms.
|
||||
|
||||
## This module implements minimal ASN.1 encoding/decoding primitives.
|
||||
import stew/endians2
|
||||
|
||||
{.push raises: [Defect].}
|
||||
|
||||
import stew/[endians2, results]
|
||||
export results
|
||||
import nimcrypto/utils
|
||||
|
||||
type
|
||||
Asn1Status* {.pure.} = enum
|
||||
Asn1Error* {.pure.} = enum
|
||||
None,
|
||||
Error,
|
||||
Success,
|
||||
Overflow,
|
||||
Incomplete,
|
||||
Indefinite,
|
||||
|
@ -22,6 +26,8 @@ type
|
|||
NoSupport,
|
||||
Overrun
|
||||
|
||||
Asn1Result*[T] = Result[T, Asn1Error]
|
||||
|
||||
Asn1Class* {.pure.} = enum
|
||||
Universal = 0x00,
|
||||
Application = 0x01
|
||||
|
@ -406,54 +412,51 @@ proc asn1EncodeContextTag*(dest: var openarray[byte], value: openarray[byte],
|
|||
copyMem(addr dest[1], addr buffer[0], lenlen)
|
||||
copyMem(addr dest[1 + lenlen], unsafeAddr value[0], len(value))
|
||||
|
||||
proc getLength(ab: var Asn1Buffer, length: var uint64): Asn1Status =
|
||||
proc getLength(ab: var Asn1Buffer): Asn1Result[uint64] =
|
||||
## Decode length part of ASN.1 TLV triplet.
|
||||
result = Asn1Status.Incomplete
|
||||
if not ab.isEmpty():
|
||||
let b = ab.buffer[ab.offset]
|
||||
if (b and 0x80'u8) == 0x00'u8:
|
||||
length = cast[uint64](b)
|
||||
let length = cast[uint64](b)
|
||||
ab.offset += 1
|
||||
result = Asn1Status.Success
|
||||
return
|
||||
return ok(length)
|
||||
if b == 0x80'u8:
|
||||
length = 0'u64
|
||||
result = Asn1Status.Indefinite
|
||||
return
|
||||
return err(Asn1Error.Indefinite)
|
||||
if b == 0xFF'u8:
|
||||
length = 0'u64
|
||||
result = Asn1Status.Incorrect
|
||||
return
|
||||
return err(Asn1Error.Incorrect)
|
||||
let octets = cast[uint64](b and 0x7F'u8)
|
||||
if octets > 8'u64:
|
||||
length = 0'u64
|
||||
result = Asn1Status.Overflow
|
||||
return
|
||||
length = 0'u64
|
||||
return err(Asn1Error.Overflow)
|
||||
if ab.isEnough(int(octets)):
|
||||
var length: uint64 = 0
|
||||
for i in 0..<int(octets):
|
||||
length = (length shl 8) or cast[uint64](ab.buffer[ab.offset + i + 1])
|
||||
ab.offset = ab.offset + int(octets) + 1
|
||||
result = Asn1Status.Success
|
||||
|
||||
proc getTag(ab: var Asn1Buffer, tag: var int,
|
||||
klass: var Asn1Class): Asn1Status =
|
||||
## Decode tag part of ASN.1 TLV triplet.
|
||||
result = Asn1Status.Incomplete
|
||||
if not ab.isEmpty():
|
||||
let b = ab.buffer[ab.offset]
|
||||
var c = int((b and 0xC0'u8) shr 6)
|
||||
if c >= 0 and c < 4:
|
||||
klass = cast[Asn1Class](c)
|
||||
return ok(length)
|
||||
else:
|
||||
return Asn1Status.Incorrect
|
||||
return err(Asn1Error.Incomplete)
|
||||
else:
|
||||
return err(Asn1Error.Incomplete)
|
||||
|
||||
proc getTag(ab: var Asn1Buffer, tag: var int): Asn1Result[Asn1Class] =
|
||||
## Decode tag part of ASN.1 TLV triplet.
|
||||
if not ab.isEmpty():
|
||||
let
|
||||
b = ab.buffer[ab.offset]
|
||||
c = int((b and 0xC0'u8) shr 6)
|
||||
tag = int(b and 0x3F)
|
||||
ab.offset += 1
|
||||
result = Asn1Status.Success
|
||||
if c >= 0 and c < 4:
|
||||
ok(cast[Asn1Class](c))
|
||||
else:
|
||||
err(Asn1Error.Incorrect)
|
||||
else:
|
||||
err(Asn1Error.Incomplete)
|
||||
|
||||
proc read*(ab: var Asn1Buffer, field: var Asn1Field): Asn1Status =
|
||||
proc read*(ab: var Asn1Buffer): Asn1Result[Asn1Field] =
|
||||
## Decode value part of ASN.1 TLV triplet.
|
||||
var
|
||||
field: Asn1Field
|
||||
tag, ttag, offset: int
|
||||
length, tlength: uint64
|
||||
klass: Asn1Class
|
||||
|
@ -462,55 +465,44 @@ proc read*(ab: var Asn1Buffer, field: var Asn1Field): Asn1Status =
|
|||
inclass = false
|
||||
while true:
|
||||
offset = ab.offset
|
||||
result = ab.getTag(tag, klass)
|
||||
if result != Asn1Status.Success:
|
||||
break
|
||||
klass = ? ab.getTag(tag)
|
||||
|
||||
if klass == Asn1Class.ContextSpecific:
|
||||
if inclass:
|
||||
result = Asn1Status.Incorrect
|
||||
break
|
||||
return err(Asn1Error.Incorrect)
|
||||
|
||||
inclass = true
|
||||
ttag = tag
|
||||
result = ab.getLength(tlength)
|
||||
if result != Asn1Status.Success:
|
||||
break
|
||||
tlength = ? ab.getLength()
|
||||
|
||||
elif klass == Asn1Class.Universal:
|
||||
result = ab.getLength(length)
|
||||
if result != Asn1Status.Success:
|
||||
break
|
||||
length = ? ab.getLength()
|
||||
|
||||
if inclass:
|
||||
if length >= tlength:
|
||||
result = Asn1Status.Incorrect
|
||||
break
|
||||
return err(Asn1Error.Incorrect)
|
||||
|
||||
if cast[byte](tag) == Asn1Tag.Boolean.code():
|
||||
# BOOLEAN
|
||||
if length != 1:
|
||||
result = Asn1Status.Incorrect
|
||||
break
|
||||
return err(Asn1Error.Incorrect)
|
||||
if not ab.isEnough(cast[int](length)):
|
||||
result = Asn1Status.Incomplete
|
||||
break
|
||||
return err(Asn1Error.Incomplete)
|
||||
let b = ab.buffer[ab.offset]
|
||||
if b != 0xFF'u8 and b != 0x00'u8:
|
||||
result = Asn1Status.Incorrect
|
||||
break
|
||||
return err(Asn1Error.Incorrect)
|
||||
|
||||
field = Asn1Field(kind: Asn1Tag.Boolean, klass: klass,
|
||||
index: ttag, offset: cast[int](ab.offset),
|
||||
length: 1)
|
||||
shallowCopy(field.buffer, ab.buffer)
|
||||
field.vbool = (b == 0xFF'u8)
|
||||
ab.offset += 1
|
||||
result = Asn1Status.Success
|
||||
break
|
||||
return ok(field)
|
||||
elif cast[byte](tag) == Asn1Tag.Integer.code():
|
||||
# INTEGER
|
||||
if not ab.isEnough(cast[int](length)):
|
||||
result = Asn1Status.Incomplete
|
||||
break
|
||||
return err(Asn1Error.Incomplete)
|
||||
if ab.buffer[ab.offset] == 0x00'u8:
|
||||
length -= 1
|
||||
ab.offset += 1
|
||||
|
@ -523,77 +515,64 @@ proc read*(ab: var Asn1Buffer, field: var Asn1Field): Asn1Status =
|
|||
field.vint = (field.vint shl 8) or
|
||||
cast[uint64](ab.buffer[ab.offset + i])
|
||||
ab.offset += cast[int](length)
|
||||
result = Asn1Status.Success
|
||||
break
|
||||
return ok(field)
|
||||
elif cast[byte](tag) == Asn1Tag.BitString.code():
|
||||
# BIT STRING
|
||||
if not ab.isEnough(cast[int](length)):
|
||||
result = Asn1Status.Incomplete
|
||||
break
|
||||
return err(Asn1Error.Incomplete)
|
||||
field = Asn1Field(kind: Asn1Tag.BitString, klass: klass,
|
||||
index: ttag, offset: cast[int](ab.offset + 1),
|
||||
length: cast[int](length - 1))
|
||||
shallowCopy(field.buffer, ab.buffer)
|
||||
field.ubits = cast[int](((length - 1) shl 3) - ab.buffer[ab.offset])
|
||||
ab.offset += cast[int](length)
|
||||
result = Asn1Status.Success
|
||||
break
|
||||
return ok(field)
|
||||
elif cast[byte](tag) == Asn1Tag.OctetString.code():
|
||||
# OCT STRING
|
||||
if not ab.isEnough(cast[int](length)):
|
||||
result = Asn1Status.Incomplete
|
||||
break
|
||||
return err(Asn1Error.Incomplete)
|
||||
field = Asn1Field(kind: Asn1Tag.OctetString, klass: klass,
|
||||
index: ttag, offset: cast[int](ab.offset),
|
||||
length: cast[int](length))
|
||||
shallowCopy(field.buffer, ab.buffer)
|
||||
ab.offset += cast[int](length)
|
||||
result = Asn1Status.Success
|
||||
break
|
||||
return ok(field)
|
||||
elif cast[byte](tag) == Asn1Tag.Null.code():
|
||||
# NULL
|
||||
if length != 0:
|
||||
result = Asn1Status.Incorrect
|
||||
break
|
||||
return err(Asn1Error.Incorrect)
|
||||
field = Asn1Field(kind: Asn1Tag.Null, klass: klass,
|
||||
index: ttag, offset: cast[int](ab.offset),
|
||||
length: 0)
|
||||
shallowCopy(field.buffer, ab.buffer)
|
||||
ab.offset += cast[int](length)
|
||||
result = Asn1Status.Success
|
||||
break
|
||||
return ok(field)
|
||||
elif cast[byte](tag) == Asn1Tag.Oid.code():
|
||||
# OID
|
||||
if not ab.isEnough(cast[int](length)):
|
||||
result = Asn1Status.Incomplete
|
||||
break
|
||||
return err(Asn1Error.Incomplete)
|
||||
field = Asn1Field(kind: Asn1Tag.Oid, klass: klass,
|
||||
index: ttag, offset: cast[int](ab.offset),
|
||||
length: cast[int](length))
|
||||
shallowCopy(field.buffer, ab.buffer)
|
||||
ab.offset += cast[int](length)
|
||||
result = Asn1Status.Success
|
||||
break
|
||||
return ok(field)
|
||||
elif cast[byte](tag) == Asn1Tag.Sequence.code():
|
||||
# SEQUENCE
|
||||
if not ab.isEnough(cast[int](length)):
|
||||
result = Asn1Status.Incomplete
|
||||
break
|
||||
return err(Asn1Error.Incomplete)
|
||||
field = Asn1Field(kind: Asn1Tag.Sequence, klass: klass,
|
||||
index: ttag, offset: cast[int](ab.offset),
|
||||
length: cast[int](length))
|
||||
shallowCopy(field.buffer, ab.buffer)
|
||||
ab.offset += cast[int](length)
|
||||
result = Asn1Status.Success
|
||||
break
|
||||
return ok(field)
|
||||
else:
|
||||
result = Asn1Status.NoSupport
|
||||
break
|
||||
return err(Asn1Error.NoSupport)
|
||||
inclass = false
|
||||
ttag = 0
|
||||
else:
|
||||
result = Asn1Status.NoSupport
|
||||
break
|
||||
return err(Asn1Error.NoSupport)
|
||||
|
||||
proc getBuffer*(field: Asn1Field): Asn1Buffer =
|
||||
## Return ``field`` as Asn1Buffer to enter composite types.
|
||||
|
|
|
@ -15,7 +15,9 @@
|
|||
import nimcrypto/utils
|
||||
import bearssl
|
||||
import minasn1
|
||||
export Asn1Status
|
||||
export Asn1Error
|
||||
import stew/results
|
||||
export results
|
||||
|
||||
const
|
||||
DefaultPublicExponent* = 3'u32
|
||||
|
@ -379,7 +381,7 @@ proc getBytes*(sig: RsaSignature): seq[byte] =
|
|||
else:
|
||||
raise newException(RsaSignatureError, "Incorrect signature")
|
||||
|
||||
proc init*(key: var RsaPrivateKey, data: openarray[byte]): Asn1Status =
|
||||
proc init*(key: var RsaPrivateKey, data: openarray[byte]): Result[void, Asn1Error] =
|
||||
## Initialize RSA private key ``key`` from ASN.1 DER binary representation
|
||||
## ``data``.
|
||||
##
|
||||
|
@ -387,71 +389,63 @@ proc init*(key: var RsaPrivateKey, data: openarray[byte]): Asn1Status =
|
|||
var
|
||||
field, rawn, rawpube, rawprie, rawp, rawq, rawdp, rawdq, rawiq: Asn1Field
|
||||
|
||||
# Asn1Field is not trivial so avoid too much Result
|
||||
|
||||
var ab = Asn1Buffer.init(data)
|
||||
result = ab.read(field)
|
||||
if result != Asn1Status.Success:
|
||||
return
|
||||
field = ? ab.read()
|
||||
|
||||
if field.kind != Asn1Tag.Sequence:
|
||||
return Asn1Status.Incorrect
|
||||
return err(Asn1Error.Incorrect)
|
||||
|
||||
var ib = field.getBuffer()
|
||||
|
||||
result = ib.read(field)
|
||||
if result != Asn1Status.Success:
|
||||
return
|
||||
field = ? ib.read()
|
||||
|
||||
if field.kind != Asn1Tag.Integer:
|
||||
return Asn1Status.Incorrect
|
||||
return err(Asn1Error.Incorrect)
|
||||
|
||||
if field.vint != 0'u64:
|
||||
return Asn1Status.Incorrect
|
||||
return err(Asn1Error.Incorrect)
|
||||
|
||||
rawn = ? ib.read()
|
||||
|
||||
result = ib.read(rawn)
|
||||
if result != Asn1Status.Success:
|
||||
return
|
||||
if rawn.kind != Asn1Tag.Integer:
|
||||
return Asn1Status.Incorrect
|
||||
return err(Asn1Error.Incorrect)
|
||||
|
||||
rawpube = ? ib.read()
|
||||
|
||||
result = ib.read(rawpube)
|
||||
if result != Asn1Status.Success:
|
||||
return
|
||||
if rawpube.kind != Asn1Tag.Integer:
|
||||
return Asn1Status.Incorrect
|
||||
return err(Asn1Error.Incorrect)
|
||||
|
||||
rawprie = ? ib.read()
|
||||
|
||||
result = ib.read(rawprie)
|
||||
if result != Asn1Status.Success:
|
||||
return
|
||||
if rawprie.kind != Asn1Tag.Integer:
|
||||
return Asn1Status.Incorrect
|
||||
return err(Asn1Error.Incorrect)
|
||||
|
||||
rawp = ? ib.read()
|
||||
|
||||
result = ib.read(rawp)
|
||||
if result != Asn1Status.Success:
|
||||
return
|
||||
if rawp.kind != Asn1Tag.Integer:
|
||||
return Asn1Status.Incorrect
|
||||
return err(Asn1Error.Incorrect)
|
||||
|
||||
rawq = ? ib.read()
|
||||
|
||||
result = ib.read(rawq)
|
||||
if result != Asn1Status.Success:
|
||||
return
|
||||
if rawq.kind != Asn1Tag.Integer:
|
||||
return Asn1Status.Incorrect
|
||||
return err(Asn1Error.Incorrect)
|
||||
|
||||
rawdp = ? ib.read()
|
||||
|
||||
result = ib.read(rawdp)
|
||||
if result != Asn1Status.Success:
|
||||
return
|
||||
if rawdp.kind != Asn1Tag.Integer:
|
||||
return Asn1Status.Incorrect
|
||||
return err(Asn1Error.Incorrect)
|
||||
|
||||
rawdq = ? ib.read()
|
||||
|
||||
result = ib.read(rawdq)
|
||||
if result != Asn1Status.Success:
|
||||
return
|
||||
if rawdq.kind != Asn1Tag.Integer:
|
||||
return Asn1Status.Incorrect
|
||||
return err(Asn1Error.Incorrect)
|
||||
|
||||
rawiq = ? ib.read()
|
||||
|
||||
result = ib.read(rawiq)
|
||||
if result != Asn1Status.Success:
|
||||
return
|
||||
if rawiq.kind != Asn1Tag.Integer:
|
||||
return Asn1Status.Incorrect
|
||||
return err(Asn1Error.Incorrect)
|
||||
|
||||
if len(rawn) >= (MinKeySize shr 3) and len(rawp) > 0 and len(rawq) > 0 and
|
||||
len(rawdp) > 0 and len(rawdq) > 0 and len(rawiq) > 0:
|
||||
|
@ -474,11 +468,11 @@ proc init*(key: var RsaPrivateKey, data: openarray[byte]): Asn1Status =
|
|||
key.seck.iqlen = len(rawiq)
|
||||
key.pexplen = len(rawprie)
|
||||
key.seck.nBitlen = cast[uint32](len(rawn) shl 3)
|
||||
result = Asn1Status.Success
|
||||
ok()
|
||||
else:
|
||||
result = Asn1Status.Incorrect
|
||||
err(Asn1Error.Incorrect)
|
||||
|
||||
proc init*(key: var RsaPublicKey, data: openarray[byte]): Asn1Status =
|
||||
proc init*(key: var RsaPublicKey, data: openarray[byte]): Result[void, Asn1Error] =
|
||||
## Initialize RSA public key ``key`` from ASN.1 DER binary representation
|
||||
## ``data``.
|
||||
##
|
||||
|
@ -486,59 +480,55 @@ proc init*(key: var RsaPublicKey, data: openarray[byte]): Asn1Status =
|
|||
var field, rawn, rawe: Asn1Field
|
||||
var ab = Asn1Buffer.init(data)
|
||||
|
||||
result = ab.read(field)
|
||||
if result != Asn1Status.Success:
|
||||
return
|
||||
field = ? ab.read()
|
||||
|
||||
if field.kind != Asn1Tag.Sequence:
|
||||
return Asn1Status.Incorrect
|
||||
return err(Asn1Error.Incorrect)
|
||||
|
||||
var ib = field.getBuffer()
|
||||
|
||||
result = ib.read(field)
|
||||
if result != Asn1Status.Success:
|
||||
return
|
||||
field = ? ib.read()
|
||||
|
||||
if field.kind != Asn1Tag.Sequence:
|
||||
return Asn1Status.Incorrect
|
||||
return err(Asn1Error.Incorrect)
|
||||
|
||||
var ob = field.getBuffer()
|
||||
|
||||
result = ob.read(field)
|
||||
if result != Asn1Status.Success:
|
||||
return
|
||||
field = ? ob.read()
|
||||
|
||||
if field.kind != Asn1Tag.Oid:
|
||||
return Asn1Status.Incorrect
|
||||
if field != Asn1OidRsaEncryption:
|
||||
return Asn1Status.Incorrect
|
||||
return err(Asn1Error.Incorrect)
|
||||
elif field != Asn1OidRsaEncryption:
|
||||
return err(Asn1Error.Incorrect)
|
||||
|
||||
field = ? ob.read()
|
||||
|
||||
result = ob.read(field)
|
||||
if result != Asn1Status.Success:
|
||||
return
|
||||
if field.kind != Asn1Tag.Null:
|
||||
return Asn1Status.Incorrect
|
||||
return err(Asn1Error.Incorrect)
|
||||
|
||||
field = ? ib.read()
|
||||
|
||||
result = ib.read(field)
|
||||
if result != Asn1Status.Success:
|
||||
return
|
||||
if field.kind != Asn1Tag.BitString:
|
||||
return Asn1Status.Incorrect
|
||||
return err(Asn1Error.Incorrect)
|
||||
|
||||
var vb = field.getBuffer()
|
||||
|
||||
result = vb.read(field)
|
||||
if result != Asn1Status.Success:
|
||||
return
|
||||
field = ? vb.read()
|
||||
|
||||
if field.kind != Asn1Tag.Sequence:
|
||||
return Asn1Status.Incorrect
|
||||
return err(Asn1Error.Incorrect)
|
||||
|
||||
var sb = field.getBuffer()
|
||||
|
||||
result = sb.read(rawn)
|
||||
if result != Asn1Status.Success:
|
||||
return
|
||||
if rawn.kind != Asn1Tag.Integer:
|
||||
return Asn1Status.Incorrect
|
||||
rawn = ? sb.read()
|
||||
|
||||
result = sb.read(rawe)
|
||||
if result != Asn1Status.Success:
|
||||
return
|
||||
if rawn.kind != Asn1Tag.Integer:
|
||||
return Asn1Status.Incorrect
|
||||
return err(Asn1Error.Incorrect)
|
||||
|
||||
rawe = ? sb.read()
|
||||
|
||||
if rawe.kind != Asn1Tag.Integer:
|
||||
return err(Asn1Error.Incorrect)
|
||||
|
||||
if len(rawn) >= (MinKeySize shr 3) and len(rawe) > 0:
|
||||
key = new RsaPublicKey
|
||||
|
@ -547,51 +537,52 @@ proc init*(key: var RsaPublicKey, data: openarray[byte]): Asn1Status =
|
|||
key.key.e = cast[ptr cuchar](addr key.buffer[rawe.offset])
|
||||
key.key.nlen = len(rawn)
|
||||
key.key.elen = len(rawe)
|
||||
result = Asn1Status.Success
|
||||
ok()
|
||||
else:
|
||||
result = Asn1Status.Incorrect
|
||||
err(Asn1Error.Incorrect)
|
||||
|
||||
proc init*(sig: var RsaSignature, data: openarray[byte]): Asn1Status =
|
||||
proc init*(sig: var RsaSignature, data: openarray[byte]): Result[void, Asn1Error] =
|
||||
## Initialize RSA signature ``sig`` from ASN.1 DER binary representation
|
||||
## ``data``.
|
||||
##
|
||||
## Procedure returns ``Asn1Status``.
|
||||
result = Asn1Status.Incorrect
|
||||
## Procedure returns ``Result[void, Asn1Status]``.
|
||||
if len(data) > 0:
|
||||
sig = new RsaSignature
|
||||
sig.buffer = @data
|
||||
result = Asn1Status.Success
|
||||
ok()
|
||||
else:
|
||||
err(Asn1Error.Incorrect)
|
||||
|
||||
proc init*[T: RsaPKI](sospk: var T, data: string): Asn1Status {.inline.} =
|
||||
proc init*[T: RsaPKI](sospk: var T, data: string): Result[void, Asn1Error] {.inline.} =
|
||||
## Initialize EC `private key`, `public key` or `scalar` ``sospk`` from
|
||||
## hexadecimal string representation ``data``.
|
||||
##
|
||||
## Procedure returns ``Asn1Status``.
|
||||
result = sospk.init(fromHex(data))
|
||||
## Procedure returns ``Result[void, Asn1Status]``.
|
||||
sospk.init(fromHex(data))
|
||||
|
||||
proc init*(t: typedesc[RsaPrivateKey], data: openarray[byte]): RsaPrivateKey =
|
||||
## Initialize RSA private key from ASN.1 DER binary representation ``data``
|
||||
## and return constructed object.
|
||||
let res = result.init(data)
|
||||
if res != Asn1Status.Success:
|
||||
if res.isErr:
|
||||
raise newException(RsaKeyIncorrectError,
|
||||
"Incorrect private key (" & $res & ")")
|
||||
"Incorrect private key (" & $res.error & ")")
|
||||
|
||||
proc init*(t: typedesc[RsaPublicKey], data: openarray[byte]): RsaPublicKey =
|
||||
## Initialize RSA public key from ASN.1 DER binary representation ``data``
|
||||
## and return constructed object.
|
||||
let res = result.init(data)
|
||||
if res != Asn1Status.Success:
|
||||
if res.isErr:
|
||||
raise newException(RsaKeyIncorrectError,
|
||||
"Incorrect public key (" & $res & ")")
|
||||
"Incorrect public key (" & $res.error & ")")
|
||||
|
||||
proc init*(t: typedesc[RsaSignature], data: openarray[byte]): RsaSignature =
|
||||
## Initialize RSA signature from raw binary representation ``data`` and
|
||||
## return constructed object.
|
||||
let res = result.init(data)
|
||||
if res != Asn1Status.Success:
|
||||
if res.isErr:
|
||||
raise newException(RsaKeyIncorrectError,
|
||||
"Incorrect signature (" & $res & ")")
|
||||
"Incorrect signature (" & $res.error & ")")
|
||||
|
||||
proc init*[T: RsaPKI](t: typedesc[T], data: string): T {.inline.} =
|
||||
## Initialize RSA `private key`, `public key` or `signature` from hexadecimal
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
import unittest
|
||||
import nimcrypto/utils
|
||||
import ../libp2p/crypto/ecnist
|
||||
import stew/results
|
||||
|
||||
when defined(nimHasUsed): {.used.}
|
||||
|
||||
|
@ -304,8 +305,8 @@ suite "EC NIST-P256/384/521 test suite":
|
|||
check:
|
||||
key.toBytes(skey2) > 0
|
||||
check:
|
||||
rkey1.init(skey1) == Asn1Status.Success
|
||||
rkey2.init(skey2) == Asn1Status.Success
|
||||
rkey1.init(skey1).isOk
|
||||
rkey2.init(skey2).isOk
|
||||
var rkey3 = EcPrivateKey.init(skey1)
|
||||
var rkey4 = EcPrivateKey.init(skey2)
|
||||
check:
|
||||
|
@ -322,8 +323,8 @@ suite "EC NIST-P256/384/521 test suite":
|
|||
var skey1 = pair.pubkey.getBytes()
|
||||
check:
|
||||
pair.pubkey.toBytes(skey2) > 0
|
||||
rkey1.init(skey1) == Asn1Status.Success
|
||||
rkey2.init(skey2) == Asn1Status.Success
|
||||
rkey1.init(skey1).isOk
|
||||
rkey2.init(skey2).isOk
|
||||
var rkey3 = EcPublicKey.init(skey1)
|
||||
var rkey4 = EcPublicKey.init(skey2)
|
||||
check:
|
||||
|
@ -411,8 +412,8 @@ suite "EC NIST-P256/384/521 test suite":
|
|||
check:
|
||||
key.toBytes(skey2) > 0
|
||||
check:
|
||||
rkey1.init(skey1) == Asn1Status.Success
|
||||
rkey2.init(skey2) == Asn1Status.Success
|
||||
rkey1.init(skey1).isOk
|
||||
rkey2.init(skey2).isOk
|
||||
var rkey3 = EcPrivateKey.init(skey1)
|
||||
var rkey4 = EcPrivateKey.init(skey2)
|
||||
check:
|
||||
|
@ -429,8 +430,8 @@ suite "EC NIST-P256/384/521 test suite":
|
|||
var skey1 = pair.pubkey.getBytes()
|
||||
check:
|
||||
pair.pubkey.toBytes(skey2) > 0
|
||||
rkey1.init(skey1) == Asn1Status.Success
|
||||
rkey2.init(skey2) == Asn1Status.Success
|
||||
rkey1.init(skey1).isOk
|
||||
rkey2.init(skey2).isOk
|
||||
var rkey3 = EcPublicKey.init(skey1)
|
||||
var rkey4 = EcPublicKey.init(skey2)
|
||||
check:
|
||||
|
@ -518,8 +519,8 @@ suite "EC NIST-P256/384/521 test suite":
|
|||
check:
|
||||
key.toBytes(skey2) > 0
|
||||
check:
|
||||
rkey1.init(skey1) == Asn1Status.Success
|
||||
rkey2.init(skey2) == Asn1Status.Success
|
||||
rkey1.init(skey1).isOk
|
||||
rkey2.init(skey2).isOk
|
||||
var rkey3 = EcPrivateKey.init(skey1)
|
||||
var rkey4 = EcPrivateKey.init(skey2)
|
||||
check:
|
||||
|
@ -536,8 +537,8 @@ suite "EC NIST-P256/384/521 test suite":
|
|||
var skey1 = pair.pubkey.getBytes()
|
||||
check:
|
||||
pair.pubkey.toBytes(skey2) > 0
|
||||
rkey1.init(skey1) == Asn1Status.Success
|
||||
rkey2.init(skey2) == Asn1Status.Success
|
||||
rkey1.init(skey1).isOk
|
||||
rkey2.init(skey2).isOk
|
||||
var rkey3 = EcPublicKey.init(skey1)
|
||||
var rkey4 = EcPublicKey.init(skey2)
|
||||
check:
|
||||
|
|
|
@ -277,8 +277,8 @@ suite "RSA 512/1024/2048/4096 test suite":
|
|||
var skey1 = key.getBytes()
|
||||
check key.toBytes(skey2) > 0
|
||||
check:
|
||||
rkey1.init(skey1) == Asn1Status.Success
|
||||
rkey2.init(skey2) == Asn1Status.Success
|
||||
rkey1.init(skey1).isOk()
|
||||
rkey2.init(skey2).isOk()
|
||||
var rkey3 = RsaPrivateKey.init(skey1)
|
||||
var rkey4 = RsaPrivateKey.init(skey2)
|
||||
check:
|
||||
|
@ -295,8 +295,8 @@ suite "RSA 512/1024/2048/4096 test suite":
|
|||
var skey1 = key.getBytes()
|
||||
check key.toBytes(skey2) > 0
|
||||
check:
|
||||
rkey1.init(skey1) == Asn1Status.Success
|
||||
rkey2.init(skey2) == Asn1Status.Success
|
||||
rkey1.init(skey1).isOk()
|
||||
rkey2.init(skey2).isOk()
|
||||
var rkey3 = RsaPrivateKey.init(skey1)
|
||||
var rkey4 = RsaPrivateKey.init(skey2)
|
||||
check:
|
||||
|
@ -312,8 +312,8 @@ suite "RSA 512/1024/2048/4096 test suite":
|
|||
var skey1 = key.getBytes()
|
||||
check key.toBytes(skey2) > 0
|
||||
check:
|
||||
rkey1.init(skey1) == Asn1Status.Success
|
||||
rkey2.init(skey2) == Asn1Status.Success
|
||||
rkey1.init(skey1).isOk()
|
||||
rkey2.init(skey2).isOk()
|
||||
var rkey3 = RsaPrivateKey.init(skey1)
|
||||
var rkey4 = RsaPrivateKey.init(skey2)
|
||||
check:
|
||||
|
@ -331,8 +331,8 @@ suite "RSA 512/1024/2048/4096 test suite":
|
|||
var skey1 = key.getBytes()
|
||||
check key.toBytes(skey2) > 0
|
||||
check:
|
||||
rkey1.init(skey1) == Asn1Status.Success
|
||||
rkey2.init(skey2) == Asn1Status.Success
|
||||
rkey1.init(skey1).isOk()
|
||||
rkey2.init(skey2).isOk()
|
||||
var rkey3 = RsaPrivateKey.init(skey1)
|
||||
var rkey4 = RsaPrivateKey.init(skey2)
|
||||
check:
|
||||
|
@ -349,8 +349,8 @@ suite "RSA 512/1024/2048/4096 test suite":
|
|||
var skey1 = pair.pubkey().getBytes()
|
||||
check:
|
||||
pair.pubkey.toBytes(skey2) > 0
|
||||
rkey1.init(skey1) == Asn1Status.Success
|
||||
rkey2.init(skey2) == Asn1Status.Success
|
||||
rkey1.init(skey1).isOk()
|
||||
rkey2.init(skey2).isOk()
|
||||
var rkey3 = RsaPublicKey.init(skey1)
|
||||
var rkey4 = RsaPublicKey.init(skey2)
|
||||
check:
|
||||
|
@ -367,8 +367,8 @@ suite "RSA 512/1024/2048/4096 test suite":
|
|||
var skey1 = pair.pubkey.getBytes()
|
||||
check:
|
||||
pair.pubkey.toBytes(skey2) > 0
|
||||
rkey1.init(skey1) == Asn1Status.Success
|
||||
rkey2.init(skey2) == Asn1Status.Success
|
||||
rkey1.init(skey1).isOk()
|
||||
rkey2.init(skey2).isOk()
|
||||
var rkey3 = RsaPublicKey.init(skey1)
|
||||
var rkey4 = RsaPublicKey.init(skey2)
|
||||
check:
|
||||
|
@ -384,8 +384,8 @@ suite "RSA 512/1024/2048/4096 test suite":
|
|||
var skey1 = pair.pubkey.getBytes()
|
||||
check:
|
||||
pair.pubkey.toBytes(skey2) > 0
|
||||
rkey1.init(skey1) == Asn1Status.Success
|
||||
rkey2.init(skey2) == Asn1Status.Success
|
||||
rkey1.init(skey1).isOk()
|
||||
rkey2.init(skey2).isOk()
|
||||
var rkey3 = RsaPublicKey.init(skey1)
|
||||
var rkey4 = RsaPublicKey.init(skey2)
|
||||
check:
|
||||
|
@ -402,8 +402,8 @@ suite "RSA 512/1024/2048/4096 test suite":
|
|||
var skey1 = pair.pubkey.getBytes()
|
||||
check:
|
||||
pair.pubkey.toBytes(skey2) > 0
|
||||
rkey1.init(skey1) == Asn1Status.Success
|
||||
rkey2.init(skey2) == Asn1Status.Success
|
||||
rkey1.init(skey1).isOk()
|
||||
rkey2.init(skey2).isOk()
|
||||
var rkey3 = RsaPublicKey.init(skey1)
|
||||
var rkey4 = RsaPublicKey.init(skey2)
|
||||
check:
|
||||
|
|
Loading…
Reference in New Issue