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