Remove SHA1 from crypto and crypto tests. (#251)

* Remove SHA1 from crypto and crypto tests.

* Simplify RSA comparison procedure.
Refactor some procedures in crypto.nim.
This commit is contained in:
Eugene Kabanov 2020-07-07 16:48:15 +03:00 committed by GitHub
parent d522537b19
commit 775cab414a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 124 additions and 206 deletions

View File

@ -13,13 +13,13 @@
import rsa, ecnist, ed25519/ed25519, secp, bearssl
import ../protobuf/minprotobuf, ../vbuffer, ../multihash, ../multicodec
import nimcrypto/[rijndael, blowfish, twofish, sha, sha2, hash, hmac, utils]
import nimcrypto/[rijndael, blowfish, twofish, sha2, hash, hmac, utils]
import ../utility
import stew/results
export results
# Export modules of types that are part of public API
export rijndael, blowfish, twofish, sha, sha2, hash, hmac, utils
# This is workaround for Nim's `import` bug
export rijndael, blowfish, twofish, sha2, hash, hmac, utils
from strutils import split
@ -37,7 +37,6 @@ type
Blowfish
DigestSheme* = enum
Sha1,
Sha256,
Sha512
@ -184,7 +183,8 @@ proc getKey*(key: PrivateKey): CryptoResult[PublicKey] =
else:
err(KeyError)
proc toRawBytes*(key: PrivateKey | PublicKey, data: var openarray[byte]): CryptoResult[int] =
proc toRawBytes*(key: PrivateKey | PublicKey,
data: var openarray[byte]): CryptoResult[int] =
## Serialize private key ``key`` (using scheme's own serialization) and store
## it to ``data``.
##
@ -274,7 +274,7 @@ proc getBytes*(sig: Signature): seq[byte] =
## Return signature ``sig`` in binary form.
result = sig.data
proc init*(key: var PrivateKey, data: openarray[byte]): bool =
proc init*[T: PrivateKey|PublicKey](key: var T, data: openarray[byte]): bool =
## Initialize private key ``key`` from libp2p's protobuf serialized raw
## binary form.
##
@ -287,54 +287,29 @@ proc init*(key: var PrivateKey, data: openarray[byte]): bool =
if pb.getBytes(2, buffer) != 0:
if cast[int8](id) in SupportedSchemesInt:
var scheme = cast[PKScheme](cast[int8](id))
var nkey = PrivateKey(scheme: scheme)
if scheme == RSA:
when key is PrivateKey:
var nkey = PrivateKey(scheme: scheme)
else:
var nkey = PublicKey(scheme: scheme)
case scheme:
of PKScheme.RSA:
if init(nkey.rsakey, buffer).isOk:
key = nkey
result = true
elif scheme == Ed25519:
return true
of PKScheme.Ed25519:
if init(nkey.edkey, buffer):
key = nkey
result = true
elif scheme == ECDSA:
return true
of PKScheme.ECDSA:
if init(nkey.eckey, buffer).isOk:
key = nkey
result = true
elif scheme == Secp256k1:
return true
of PKScheme.Secp256k1:
if init(nkey.skkey, buffer).isOk:
key = nkey
result = true
proc init*(key: var PublicKey, data: openarray[byte]): bool =
## Initialize public key ``key`` from libp2p's protobuf serialized raw
## binary form.
##
## Returns ``true`` on success.
var id: uint64
var buffer: seq[byte]
if len(data) > 0:
var pb = initProtoBuffer(@data)
if pb.getVarintValue(1, id) != 0:
if pb.getBytes(2, buffer) != 0:
if cast[int8](id) in SupportedSchemesInt:
var scheme = cast[PKScheme](cast[int8](id))
var nkey = PublicKey(scheme: scheme)
if scheme == RSA:
if init(nkey.rsakey, buffer).isOk:
key = nkey
result = true
elif scheme == Ed25519:
if init(nkey.edkey, buffer):
key = nkey
result = true
elif scheme == ECDSA:
if init(nkey.eckey, buffer).isOk:
key = nkey
result = true
elif scheme == Secp256k1:
if init(nkey.skkey, buffer).isOk:
key = nkey
result = true
return true
else:
return false
proc init*(sig: var Signature, data: openarray[byte]): bool =
## Initialize signature ``sig`` from raw binary form.
@ -344,18 +319,8 @@ proc init*(sig: var Signature, data: openarray[byte]): bool =
sig.data = @data
result = true
proc init*(key: var PrivateKey, data: string): bool =
## Initialize private key ``key`` from libp2p's protobuf serialized
## hexadecimal string representation.
##
## Returns ``true`` on success.
try:
key.init(fromHex(data))
except ValueError:
false
proc init*(key: var PublicKey, data: string): bool =
## Initialize public key ``key`` from libp2p's protobuf serialized
proc init*[T: PrivateKey|PublicKey](key: var T, data: string): bool =
## Initialize private/public key ``key`` from libp2p's protobuf serialized
## hexadecimal string representation.
##
## Returns ``true`` on success.
@ -374,7 +339,8 @@ proc init*(sig: var Signature, data: string): bool =
except ValueError:
false
proc init*(t: typedesc[PrivateKey], data: openarray[byte]): CryptoResult[PrivateKey] =
proc init*(t: typedesc[PrivateKey],
data: openarray[byte]): CryptoResult[PrivateKey] =
## Create new private key from libp2p's protobuf serialized binary form.
var res: t
if not res.init(data):
@ -382,7 +348,8 @@ proc init*(t: typedesc[PrivateKey], data: openarray[byte]): CryptoResult[Private
else:
ok(res)
proc init*(t: typedesc[PublicKey], data: openarray[byte]): CryptoResult[PublicKey] =
proc init*(t: typedesc[PublicKey],
data: openarray[byte]): CryptoResult[PublicKey] =
## Create new public key from libp2p's protobuf serialized binary form.
var res: t
if not res.init(data):
@ -390,7 +357,8 @@ proc init*(t: typedesc[PublicKey], data: openarray[byte]): CryptoResult[PublicKe
else:
ok(res)
proc init*(t: typedesc[Signature], data: openarray[byte]): CryptoResult[Signature] =
proc init*(t: typedesc[Signature],
data: openarray[byte]): CryptoResult[Signature] =
## Create new public key from libp2p's protobuf serialized binary form.
var res: t
if not res.init(data):
@ -421,117 +389,93 @@ proc init*(t: typedesc[Signature], data: string): CryptoResult[Signature] =
except ValueError:
err(SigError)
proc `==`*(key1, key2: PublicKey): bool =
proc `==`*(key1, key2: PublicKey): bool {.inline.} =
## Return ``true`` if two public keys ``key1`` and ``key2`` of the same
## scheme and equal.
if key1.scheme == key2.scheme:
if key1.scheme == RSA:
result = (key1.rsakey == key2.rsakey)
elif key1.scheme == Ed25519:
result = (key1.edkey == key2.edkey)
elif key1.scheme == ECDSA:
result = (key1.eckey == key2.eckey)
case key1.scheme
of PKScheme.RSA:
(key1.rsakey == key2.rsakey)
of PKScheme.Ed25519:
(key1.edkey == key2.edkey)
of PKScheme.ECDSA:
(key1.eckey == key2.eckey)
of PKScheme.Secp256k1:
(key1.skkey == key2.skkey)
of PKScheme.NoSupport:
false
else:
false
proc `==`*(key1, key2: PrivateKey): bool =
## Return ``true`` if two private keys ``key1`` and ``key2`` of the same
## scheme and equal.
if key1.scheme == key2.scheme:
if key1.scheme == RSA:
result = (key1.rsakey == key2.rsakey)
elif key1.scheme == Ed25519:
result = (key1.edkey == key2.edkey)
elif key1.scheme == ECDSA:
result = (key1.eckey == key2.eckey)
case key1.scheme
of PKScheme.RSA:
(key1.rsakey == key2.rsakey)
of PKScheme.Ed25519:
(key1.edkey == key2.edkey)
of PKScheme.ECDSA:
(key1.eckey == key2.eckey)
of PKScheme.Secp256k1:
(key1.skkey == key2.skkey)
of PKScheme.NoSupport:
false
else:
false
proc `$`*(key: PrivateKey): string =
## Get string representation of private key ``key``.
if key.scheme == RSA:
result = $(key.rsakey)
elif key.scheme == Ed25519:
result = "Ed25519 key ("
result.add($(key.edkey))
result.add(")")
elif key.scheme == ECDSA:
result = "Secp256r1 key ("
result.add($(key.eckey))
result.add(")")
elif key.scheme == Secp256k1:
result = "Secp256k1 key ("
result.add($(key.skkey))
result.add(")")
proc `$`*(key: PrivateKey|PublicKey): string =
## Get string representation of private/public key ``key``.
case key.scheme:
of PKScheme.RSA:
$(key.rsakey)
of PKScheme.Ed25519:
"ed25519 key (" & $key.edkey & ")"
of PKScheme.ECDSA:
"secp256r1 key (" & $key.eckey & ")"
of PKScheme.Secp256k1:
"secp256k1 key (" & $key.skkey & ")"
of PKScheme.NoSupport:
"not supported"
proc `$`*(key: PublicKey): string =
## Get string representation of public key ``key``.
if key.scheme == RSA:
result = $(key.rsakey)
elif key.scheme == Ed25519:
result = "Ed25519 key ("
result.add($(key.edkey))
result.add(")")
elif key.scheme == ECDSA:
result = "Secp256r1 key ("
result.add($(key.eckey))
result.add(")")
elif key.scheme == Secp256k1:
result = "Secp256k1 key ("
result.add($(key.skkey))
result.add(")")
func shortLog*(key: PrivateKey): string =
## Get string representation of private key ``key``.
if key.scheme == RSA:
result = ($key.rsakey).shortLog
elif key.scheme == Ed25519:
result = "Ed25519 key ("
result.add(($key.edkey).shortLog)
result.add(")")
elif key.scheme == ECDSA:
result = "Secp256r1 key ("
result.add(($key.eckey).shortLog)
result.add(")")
elif key.scheme == Secp256k1:
result = "Secp256k1 key ("
result.add(($key.skkey).shortLog)
result.add(")")
proc shortLog*(key: PublicKey): string =
## Get string representation of public key ``key``.
if key.scheme == RSA:
result = ($key.rsakey).shortLog
elif key.scheme == Ed25519:
result = "Ed25519 key ("
result.add(($key.edkey).shortLog)
result.add(")")
elif key.scheme == ECDSA:
result = "Secp256r1 key ("
result.add(($key.eckey).shortLog)
result.add(")")
elif key.scheme == Secp256k1:
result = "Secp256k1 key ("
result.add(($key.skkey).shortLog)
result.add(")")
func shortLog*(key: PrivateKey|PublicKey): string =
## Get short string representation of private/public key ``key``.
case key.scheme:
of PKScheme.RSA:
($key.rsakey).shortLog
of PKScheme.Ed25519:
"ed25519 key (" & ($key.edkey).shortLog & ")"
of PKScheme.ECDSA:
"secp256r1 key (" & ($key.eckey).shortLog & ")"
of PKScheme.Secp256k1:
"secp256k1 key (" & ($key.skkey).shortLog & ")"
of PKScheme.NoSupport:
"not supported"
proc `$`*(sig: Signature): string =
## Get string representation of signature ``sig``.
result = toHex(sig.data)
proc sign*(key: PrivateKey, data: openarray[byte]): CryptoResult[Signature] {.gcsafe.} =
proc sign*(key: PrivateKey,
data: openarray[byte]): CryptoResult[Signature] {.gcsafe.} =
## Sign message ``data`` using private key ``key`` and return generated
## signature in raw binary form.
var res: Signature
if key.scheme == RSA:
case key.scheme:
of PKScheme.RSA:
let sig = ? key.rsakey.sign(data).orError(SigError)
res.data = ? sig.getBytes().orError(SigError)
ok(res)
elif key.scheme == Ed25519:
of PKScheme.Ed25519:
let sig = key.edkey.sign(data)
res.data = sig.getBytes()
ok(res)
elif key.scheme == ECDSA:
of PKScheme.ECDSA:
let sig = ? key.eckey.sign(data).orError(SigError)
res.data = ? sig.getBytes().orError(SigError)
ok(res)
elif key.scheme == Secp256k1:
of PKScheme.Secp256k1:
let sig = key.skkey.sign(data)
res.data = sig.getBytes()
ok(res)
@ -541,22 +485,33 @@ proc sign*(key: PrivateKey, data: openarray[byte]): CryptoResult[Signature] {.gc
proc verify*(sig: Signature, message: openarray[byte], key: PublicKey): bool =
## Verify signature ``sig`` using message ``message`` and public key ``key``.
## Return ``true`` if message signature is valid.
if key.scheme == RSA:
case key.scheme:
of PKScheme.RSA:
var signature: RsaSignature
if signature.init(sig.data).isOk:
result = signature.verify(message, key.rsakey)
elif key.scheme == Ed25519:
signature.verify(message, key.rsakey)
else:
false
of PKScheme.Ed25519:
var signature: EdSignature
if signature.init(sig.data):
result = signature.verify(message, key.edkey)
elif key.scheme == ECDSA:
signature.verify(message, key.edkey)
else:
false
of PKScheme.ECDSA:
var signature: EcSignature
if signature.init(sig.data).isOk:
result = signature.verify(message, key.eckey)
elif key.scheme == Secp256k1:
signature.verify(message, key.eckey)
else:
false
of PKScheme.Secp256k1:
var signature: SkSignature
if signature.init(sig.data).isOk:
result = signature.verify(message, key.skkey)
signature.verify(message, key.skkey)
else:
false
else:
false
template makeSecret(buffer, hmactype, secret, seed: untyped) {.dirty.}=
var ctx: hmactype
@ -609,8 +564,6 @@ proc stretchKeys*(cipherType: string, hashType: string,
makeSecret(result.data, HMAC[sha256], sharedSecret, seed)
elif hashType == "SHA512":
makeSecret(result.data, HMAC[sha512], sharedSecret, seed)
elif hashType == "SHA1":
makeSecret(result.data, HMAC[sha1], sharedSecret, seed)
template goffset*(secret, id, o: untyped): untyped =
id * (len(secret.data) shr 1) + o
@ -802,23 +755,28 @@ proc decodeExchange*(message: seq[byte],
## Serialization/Deserialization helpers
proc write*(vb: var VBuffer, pubkey: PublicKey) {.inline, raises: [Defect, ResultError[CryptoError]].} =
proc write*(vb: var VBuffer, pubkey: PublicKey) {.
inline, raises: [Defect, ResultError[CryptoError]].} =
## Write PublicKey value ``pubkey`` to buffer ``vb``.
vb.writeSeq(pubkey.getBytes().tryGet())
proc write*(vb: var VBuffer, seckey: PrivateKey) {.inline, raises: [Defect, ResultError[CryptoError]].} =
proc write*(vb: var VBuffer, seckey: PrivateKey) {.
inline, raises: [Defect, ResultError[CryptoError]].} =
## Write PrivateKey value ``seckey`` to buffer ``vb``.
vb.writeSeq(seckey.getBytes().tryGet())
proc write*(vb: var VBuffer, sig: PrivateKey) {.inline, raises: [Defect, ResultError[CryptoError]].} =
proc write*(vb: var VBuffer, sig: PrivateKey) {.
inline, raises: [Defect, ResultError[CryptoError]].} =
## Write Signature value ``sig`` to buffer ``vb``.
vb.writeSeq(sig.getBytes().tryGet())
proc initProtoField*(index: int, pubkey: PublicKey): ProtoField {.raises: [Defect, ResultError[CryptoError]].} =
proc initProtoField*(index: int, pubkey: PublicKey): ProtoField {.
raises: [Defect, ResultError[CryptoError]].} =
## Initialize ProtoField with PublicKey ``pubkey``.
result = initProtoField(index, pubkey.getBytes().tryGet())
proc initProtoField*(index: int, seckey: PrivateKey): ProtoField {.raises: [Defect, ResultError[CryptoError]].} =
proc initProtoField*(index: int, seckey: PrivateKey): ProtoField {.
raises: [Defect, ResultError[CryptoError]].} =
## Initialize ProtoField with PrivateKey ``seckey``.
result = initProtoField(index, seckey.getBytes().tryGet())

View File

@ -661,15 +661,16 @@ proc cmp(a: openarray[byte], b: openarray[byte]): bool =
let blen = len(b)
if alen == blen:
if alen == 0:
result = true
true
else:
var n = alen
var res, diff: int
var res = 0
while n > 0:
dec(n)
diff = int(a[n]) - int(b[n])
res = (res and -not(diff)) or diff
result = (res == 0)
res = res or int(a[n] xor b[n])
(res == 0)
else:
false
proc `==`*(a, b: RsaPrivateKey): bool =
## Compare two RSA private keys for equality.

View File

@ -243,18 +243,6 @@ const
"""001CC33294544D898781010258C2FB81F02429D2DD54D0B59B8CD2335F57498F
D4E444BEC94DA7BE2BAF3E3796AFA8388F626AEB3178355991985EE5FFC9D1AA
CAD9""",
# AES-256 SHA-1
"85076756644AAC06A47B29E25CB39B3E0C717152EE587F50C5A10281DB7F2FA5",
"""256D46C5E5449AA7B9BE985646D5F32E455BB4B7AAF3566507A023B72801A7BC
5066647E82DE2BC37FE22AB0DE440F77""",
"""01FF82C71215CFFD7A42A5CED03BD2256D4A5B6850472A5C5CA90665D510F038
A21F3A6EA0BB0A64113960C54DDAFC5E7A5F018E4413D7CC93C736A8D30579ED
5A2B""",
# Edge case (where Go implementation returns 65 bytes of secret)
# Nim implementation has leading `00`.
"""00360D9410E58534AC6A89CA5AC17E9455F619DCA71A6C2FB6F3156AE58DDB91
6E9A7D223D1D7DD05D5475BFC4C517C85475600AAF6F28703ED1203281369A41
9A7C"""
]
Ivs = [
@ -275,15 +263,6 @@ const
"A828F6D249F38A917CD297F7BDDE7B70",
"54FC8070579A17F6DAD342174062D60A",
"D33C7696183DA21C5CD40AB677BECE7C",
"9EFF93741DC080A15B9E554080AB9869",
"7A007E351C9A5C930D01645D97648F8C",
"934DB2529D1D3AC37BAD56FD1E522196",
"30D19C3C1AB9A3391A5F88E92307261D",
"32ED1A961630D94A279F99757B3131CB",
"003ABE572377D59B74713425854FED29",
"3338850C0A4D7BD53C70E40FA0079AA2",
"62787F194DC218C5B0DAFD806F0D3125"
]
CipherKeys = [
@ -304,15 +283,6 @@ const
"FC2797D1040FF162A90275EBA3FCC4330C2BDC28D23DA80B89842C2D7A6EFA06",
"B83698789ED8E3B44E48EAAEB291B3003AD95FAF344EBA1B9071F4FB46A4E4E9",
"5D90C579971B7B7F9ECDE55EBCE8921B807AAD45D61952228758BA80F4490E8F",
"1C429A32A2E16168D3E3F942AEEAD708456C6566D800D5B7A6DCE8184739F16D",
"84987E7CC9F71243408454DD0787F438CCB62C79ED56078FD920FFFD7D5C44FF",
"971372E385E0F9FED8F67C922D0F5EB77D7D7818F63B26EF80C4D3C81D9E1B97",
"F20AE0A5387B2D1D38B8B340466D252F894C00C5907EE3A510442E4F38966AB0",
"B58F32D83C7A91B6B1DA731334D70502348CD82EFB8258C0AE316B983F2F1E1E",
"5903FE75A1C328BE6C98EB4A4EFF19C67D3C52C87B3131047F3773201D44BFCE",
"55EAD85B3124C36828ED3A43698952111EECE8C7FB156D71EE3F84E088B4F4CE",
"E4C99C782A88B69E5D83F4DEFDD2AE61A397486E17EC9EAE6EC679A75E47BBCD"
]
MacKeys = [
@ -333,15 +303,6 @@ const
"EE66A1579D732E99A8500F48595BF25289E722DB",
"E692EC73B0A2E68625221E1D01BA0E6B24BCB43F",
"8613E8F86D2DD1CF3CEDC52AD91423F2F31E0003",
"F8A7EF47F37257B54A5028424E64F172E532E7E7",
"4D3596723AECD3DF21A20E956755782E783C9E4A",
"484860090D99F4B702C809294037E6C7F6E58BBA",
"15163D55C0A32E79E0EDD8E8EDA5AC9564B5488C",
"6116BCB44773E3342AB5671D2AC107D4C9EC0757",
"1CA3FCA023C72B7695481CA815856FEF0C5D7E9E",
"E34004C383C36201DC23E062DAE791C76738C28E",
"FA5CB0689A1DFDBAE8618BC079D70E318377B0DA"
]
proc cmp(a, b: openarray[byte]): bool =
@ -459,8 +420,6 @@ suite "Key interface test suite":
check testStretcher(0, 4, "AES-128", "SHA256") == true
test "Go key stretch function AES256-SHA512 test vectors":
check testStretcher(4, 8, "AES-256", "SHA512") == true
test "Go key stretch function AES256-SHA1 test vectors":
check testStretcher(8, 12, "AES-256", "SHA1") == true
test "ChaChaPoly":
# test data from: