constantine/tests/t_hash_sha256_vs_openssl.nim

142 lines
3.6 KiB
Nim

import
# Internals
../constantine/hashes/h_sha256,
# Helpers
../helpers/prng_unsafe,
# Third-party
stew/byteutils
# Deal with platform mess
# --------------------------------------------------------------------
when defined(windows):
when sizeof(int) == 8:
const DLLSSLName* = "(libssl-1_1-x64|ssleay64|libssl64).dll"
else:
const DLLSSLName* = "(libssl-1_1|ssleay32|libssl32).dll"
else:
when defined(macosx):
const versions = "(.1.1|.38|.39|.41|.43|.44|.45|.46|.47|.48|.10|.1.0.2|.1.0.1|.1.0.0|.0.9.9|.0.9.8|)"
else:
const versions = "(.1.1|.1.0.2|.1.0.1|.1.0.0|.0.9.9|.0.9.8|.48|.47|.46|.45|.44|.43|.41|.39|.38|.10|)"
when defined(macosx):
const DLLSSLName* = "libssl" & versions & ".dylib"
elif defined(genode):
const DLLSSLName* = "libssl.lib.so"
else:
const DLLSSLName* = "libssl.so" & versions
# OpenSSL wrapper
# --------------------------------------------------------------------
proc SHA256[T: byte|char](
msg: openarray[T],
digest: ptr array[32, byte] = nil
): ptr array[32, byte] {.cdecl, dynlib: DLLSSLName, importc.}
proc SHA256_OpenSSL[T: byte|char](
digest: var array[32, byte],
s: openarray[T]) =
discard SHA256(s, digest.addr)
# Test
# --------------------------------------------------------------------
echo "\n------------------------------------------------------\n"
const SmallSizeIters = 128
const LargeSizeIters = 10
proc sanityABC =
var bufCt: array[32, byte]
let msg = "abc"
let hashed = hexToByteArray[32](
"BA7816BF8F01CFEA414140DE5DAE2223" &
"B00361A396177A9CB410FF61F20015AD")
sha256.hash(bufCt, msg)
doAssert bufCt == hashed
proc sanityABC2 =
var bufCt: array[32, byte]
let msg = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
let hashed = hexToByteArray[32](
"248D6A61D20638B8E5C026930C3E6039" &
"A33CE45964FF2167F6ECEDD419DB06C1")
sha256.hash(bufCt, msg)
doAssert bufCt == hashed
proc innerTest(rng: var RngState, sizeRange: Slice[int]) =
let size = rng.random_unsafe(sizeRange)
let msg = rng.random_byte_seq(size)
var bufCt, bufOssl: array[32, byte]
sha256.hash(bufCt, msg)
SHA256_OpenSSL(bufOssl, msg)
doAssert bufCt == bufOssl
proc chunkTest(rng: var RngState, sizeRange: Slice[int]) =
let size = rng.random_unsafe(sizeRange)
let msg = rng.random_byte_seq(size)
let chunkSize = rng.random_unsafe(2 ..< 20)
var bufOnePass: array[32, byte]
sha256.hash(bufOnePass, msg)
var bufChunked: array[32, byte]
let maxChunk = max(2, sizeRange.b div 10) # Consume up to 10% at once
var ctx: Sha256Context
ctx.init()
var cur = 0
while size - cur > 0:
let chunkSize = rng.random_unsafe(0 ..< maxChunk)
let stop = min(cur+chunkSize-1, size-1)
let consumed = stop-cur+1
ctx.update(msg.toOpenArray(cur, stop))
cur += consumed
ctx.finish(bufChunked)
doAssert bufOnePass == bufChunked
proc main() =
echo "SHA256 - sanity checks"
sanityABC()
sanityABC2()
echo "SHA256 - Starting differential testing vs OpenSSL"
var rng: RngState
rng.seed(0xFACADE)
echo "SHA256 - 0 <= size < 64 - exhaustive"
for i in 0 ..< 64:
rng.innerTest(i .. i)
echo "SHA256 - 0 <= size < 64 - exhaustive chunked"
for i in 0 ..< 64:
rng.chunkTest(i .. i)
echo "SHA256 - 64 <= size < 1024B"
for _ in 0 ..< SmallSizeIters:
rng.innerTest(0 ..< 1024)
echo "SHA256 - 64 <= size < 1024B - chunked"
for _ in 0 ..< SmallSizeIters:
rng.chunkTest(0 ..< 1024)
echo "SHA256 - 1MB <= size < 50MB"
for _ in 0 ..< LargeSizeIters:
rng.innerTest(1_000_000 ..< 50_000_000)
echo "SHA256 - Differential testing vs OpenSSL - SUCCESS"
main()