Use Result construct in minasn1 (#144)

This commit is contained in:
Giovanni Petrantoni 2020-04-23 21:10:20 +09:00 committed by GitHub
parent 6ae92eb21a
commit 1c4d72f5e3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 240 additions and 272 deletions

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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:

View File

@ -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: