751 lines
23 KiB
Nim
751 lines
23 KiB
Nim
#
|
|
#
|
|
# NimCrypto
|
|
# (c) Copyright 2016-2018 Eugene Kabanov
|
|
#
|
|
# See the file "LICENSE", included in this
|
|
# distribution, for details about the copyright.
|
|
#
|
|
|
|
## This module implements RIPEMD set of cryptographic hash functions,
|
|
## designed by Hans Dobbertin, Antoon Bosselaers and Bart Preneel.
|
|
## [http://www.esat.kuleuven.be/~bosselae/ripemd160/pdf/AB-9601/AB-9601.pdf]
|
|
##
|
|
## This module is Nim adoptation of original C source code by
|
|
## Antoon Bosselaers.
|
|
## [https://homes.esat.kuleuven.be/~bosselae/ripemd160/ps/AB-9601/rmd160.c]
|
|
##
|
|
## This module includes support of RIPEMD-128/160/256/320.
|
|
##
|
|
## Tests made according to official test vectors
|
|
## [https://homes.esat.kuleuven.be/~bosselae/ripemd160.html].
|
|
|
|
import hash, utils
|
|
|
|
type
|
|
RipemdContext*[bits: static[int]] = object
|
|
count: array[2, uint32]
|
|
state: array[bits div 32, uint32]
|
|
buffer: array[64, byte]
|
|
|
|
ripemd128* = RipemdContext[128]
|
|
ripemd160* = RipemdContext[160]
|
|
ripemd256* = RipemdContext[256]
|
|
ripemd320* = RipemdContext[320]
|
|
ripemd* = ripemd128 | ripemd160 | ripemd256 | ripemd320
|
|
|
|
# Five basic functions F(), G() and H()
|
|
template F(x, y, z: untyped): untyped =
|
|
# x^y^z
|
|
((x) xor (y) xor (z))
|
|
|
|
template G(x, y, z: untyped): untyped =
|
|
# (x&y)|(~x&z)
|
|
(((x) and (y)) or (not (x) and (z)))
|
|
|
|
template H(x, y, z: untyped): untyped =
|
|
# (x|~y)^z
|
|
(((x) or not (y)) xor (z))
|
|
|
|
template I(x, y, z: untyped): untyped =
|
|
# (x&z)|(y&~z)
|
|
(((x) and (z)) or ((y) and not (z)))
|
|
|
|
template J(x, y, z: untyped): untyped =
|
|
# x^(y|~z)
|
|
((x) xor ((y) or not (z)))
|
|
|
|
# Eight basic operations FF() through III() for 128 and 256 bits
|
|
template FF128(a, b, c, d, x, s: untyped): void =
|
|
(a) = (a) + F((b), (c), (d)) + (x)
|
|
(a) = ROL(cast[uint32](a), (s))
|
|
|
|
template GG128(a, b, c, d, x, s: untyped): void =
|
|
(a) = (a) + G((b), (c), (d)) + (x) + 0x5A827999'u32
|
|
(a) = ROL(cast[uint32](a), (s))
|
|
|
|
template HH128(a, b, c, d, x, s: untyped): void =
|
|
(a) = (a) + H((b), (c), (d)) + (x) + 0x6ED9EBA1'u32
|
|
(a) = ROL(cast[uint32](a), (s))
|
|
|
|
template II128(a, b, c, d, x, s: untyped): void =
|
|
(a) = (a) + I((b), (c), (d)) + (x) + 0x8F1BBCDC'u32
|
|
(a) = ROL(cast[uint32](a), (s))
|
|
|
|
template FFF128(a, b, c, d, x, s: untyped): void =
|
|
(a) = (a) + F((b), (c), (d)) + (x)
|
|
(a) = ROL(cast[uint32](a), (s))
|
|
|
|
template GGG128(a, b, c, d, x, s: untyped): void =
|
|
(a) = (a) + G((b), (c), (d)) + (x) + 0x6D703EF3'u32
|
|
(a) = ROL(cast[uint32](a), (s))
|
|
|
|
template HHH128(a, b, c, d, x, s: untyped): void =
|
|
(a) = (a) + H((b), (c), (d)) + (x) + 0x5C4DD124'u32
|
|
(a) = ROL(cast[uint32](a), (s))
|
|
|
|
template III128(a, b, c, d, x, s: untyped): void =
|
|
(a) = (a) + I((b), (c), (d)) + (x) + 0x50A28BE6'u32
|
|
(a) = ROL((a), (s))
|
|
|
|
# Ten basic operations FF() through III() for 160 and 320 bits
|
|
template FF160(a, b, c, d, e, x, s: untyped): void =
|
|
(a) = (a) + F((b), (c), (d)) + (x)
|
|
(a) = ROL(cast[uint32](a), (s)) + (e)
|
|
(c) = ROL(cast[uint32](c), 10)
|
|
|
|
template GG160(a, b, c, d, e, x, s: untyped): void =
|
|
(a) = (a) + G((b), (c), (d)) + (x) + 0x5A827999'u32
|
|
(a) = ROL(cast[uint32](a), (s)) + (e)
|
|
(c) = ROL(cast[uint32](c), 10)
|
|
|
|
template HH160(a, b, c, d, e, x, s: untyped): void =
|
|
(a) = (a) + H((b), (c), (d)) + (x) + 0x6ED9EBA1'u32
|
|
(a) = ROL(cast[uint32](a), (s)) + (e)
|
|
(c) = ROL(cast[uint32](c), 10)
|
|
|
|
template II160(a, b, c, d, e, x, s: untyped): void =
|
|
(a) = (a) + I((b), (c), (d)) + (x) + 0x8F1BBCDC'u32
|
|
(a) = ROL(cast[uint32](a), (s)) + (e)
|
|
(c) = ROL(cast[uint32](c), 10)
|
|
|
|
template JJ160(a, b, c, d, e, x, s: untyped): void =
|
|
(a) = (a) + J((b), (c), (d)) + (x) + 0xA953FD4E'u32
|
|
(a) = ROL(cast[uint32](a), (s)) + (e)
|
|
(c) = ROL(cast[uint32](c), 10)
|
|
|
|
template FFF160(a, b, c, d, e, x, s: untyped): void =
|
|
(a) = (a) + F((b), (c), (d)) + (x)
|
|
(a) = ROL(cast[uint32](a), (s)) + (e)
|
|
(c) = ROL(cast[uint32](c), 10)
|
|
|
|
template GGG160(a, b, c, d, e, x, s: untyped): void =
|
|
(a) = (a) + G((b), (c), (d)) + (x) + 0x7A6D76E9'u32
|
|
(a) = ROL(cast[uint32](a), (s)) + (e)
|
|
(c) = ROL(cast[uint32](c), 10)
|
|
|
|
template HHH160(a, b, c, d, e, x, s: untyped): void =
|
|
(a) = (a) + H((b), (c), (d)) + (x) + 0x6D703EF3'u32
|
|
(a) = ROL(cast[uint32](a), (s)) + (e)
|
|
(c) = ROL(cast[uint32](c), 10)
|
|
|
|
template III160(a, b, c, d, e, x, s: untyped): void =
|
|
(a) = (a) + I((b), (c), (d)) + (x) + 0x5C4DD124'u32
|
|
(a) = ROL(cast[uint32](a), (s)) + (e)
|
|
(c) = ROL(cast[uint32](c), 10)
|
|
|
|
template JJJ160(a, b, c, d, e, x, s: untyped): void =
|
|
(a) = (a) + J((b), (c), (d)) + (x) + 0x50A28BE6'u32
|
|
(a) = ROL(cast[uint32](a), (s)) + (e)
|
|
(c) = ROL(cast[uint32](c), 10)
|
|
|
|
template LROUND128N1(a, b, c, d, x): void =
|
|
FF128(a, b, c, d, x[ 0], 11)
|
|
FF128(d, a, b, c, x[ 1], 14)
|
|
FF128(c, d, a, b, x[ 2], 15)
|
|
FF128(b, c, d, a, x[ 3], 12)
|
|
FF128(a, b, c, d, x[ 4], 5)
|
|
FF128(d, a, b, c, x[ 5], 8)
|
|
FF128(c, d, a, b, x[ 6], 7)
|
|
FF128(b, c, d, a, x[ 7], 9)
|
|
FF128(a, b, c, d, x[ 8], 11)
|
|
FF128(d, a, b, c, x[ 9], 13)
|
|
FF128(c, d, a, b, x[10], 14)
|
|
FF128(b, c, d, a, x[11], 15)
|
|
FF128(a, b, c, d, x[12], 6)
|
|
FF128(d, a, b, c, x[13], 7)
|
|
FF128(c, d, a, b, x[14], 9)
|
|
FF128(b, c, d, a, x[15], 8)
|
|
|
|
template LROUND128N2(a, b, c, d, x): void =
|
|
GG128(a, b, c, d, x[ 7], 7)
|
|
GG128(d, a, b, c, x[ 4], 6)
|
|
GG128(c, d, a, b, x[13], 8)
|
|
GG128(b, c, d, a, x[ 1], 13)
|
|
GG128(a, b, c, d, x[10], 11)
|
|
GG128(d, a, b, c, x[ 6], 9)
|
|
GG128(c, d, a, b, x[15], 7)
|
|
GG128(b, c, d, a, x[ 3], 15)
|
|
GG128(a, b, c, d, x[12], 7)
|
|
GG128(d, a, b, c, x[ 0], 12)
|
|
GG128(c, d, a, b, x[ 9], 15)
|
|
GG128(b, c, d, a, x[ 5], 9)
|
|
GG128(a, b, c, d, x[ 2], 11)
|
|
GG128(d, a, b, c, x[14], 7)
|
|
GG128(c, d, a, b, x[11], 13)
|
|
GG128(b, c, d, a, x[ 8], 12)
|
|
|
|
template LROUND128N3(a, b, c, d, x): void =
|
|
HH128(a, b, c, d, x[ 3], 11)
|
|
HH128(d, a, b, c, x[10], 13)
|
|
HH128(c, d, a, b, x[14], 6)
|
|
HH128(b, c, d, a, x[ 4], 7)
|
|
HH128(a, b, c, d, x[ 9], 14)
|
|
HH128(d, a, b, c, x[15], 9)
|
|
HH128(c, d, a, b, x[ 8], 13)
|
|
HH128(b, c, d, a, x[ 1], 15)
|
|
HH128(a, b, c, d, x[ 2], 14)
|
|
HH128(d, a, b, c, x[ 7], 8)
|
|
HH128(c, d, a, b, x[ 0], 13)
|
|
HH128(b, c, d, a, x[ 6], 6)
|
|
HH128(a, b, c, d, x[13], 5)
|
|
HH128(d, a, b, c, x[11], 12)
|
|
HH128(c, d, a, b, x[ 5], 7)
|
|
HH128(b, c, d, a, x[12], 5)
|
|
|
|
template LROUND128N4(a, b, c, d, x): void =
|
|
II128(a, b, c, d, x[ 1], 11)
|
|
II128(d, a, b, c, x[ 9], 12)
|
|
II128(c, d, a, b, x[11], 14)
|
|
II128(b, c, d, a, x[10], 15)
|
|
II128(a, b, c, d, x[ 0], 14)
|
|
II128(d, a, b, c, x[ 8], 15)
|
|
II128(c, d, a, b, x[12], 9)
|
|
II128(b, c, d, a, x[ 4], 8)
|
|
II128(a, b, c, d, x[13], 9)
|
|
II128(d, a, b, c, x[ 3], 14)
|
|
II128(c, d, a, b, x[ 7], 5)
|
|
II128(b, c, d, a, x[15], 6)
|
|
II128(a, b, c, d, x[14], 8)
|
|
II128(d, a, b, c, x[ 5], 6)
|
|
II128(c, d, a, b, x[ 6], 5)
|
|
II128(b, c, d, a, x[ 2], 12)
|
|
|
|
template RROUND128N1(a, b, c, d, x): void =
|
|
III128(a, b, c, d, x[ 5], 8)
|
|
III128(d, a, b, c, x[14], 9)
|
|
III128(c, d, a, b, x[ 7], 9)
|
|
III128(b, c, d, a, x[ 0], 11)
|
|
III128(a, b, c, d, x[ 9], 13)
|
|
III128(d, a, b, c, x[ 2], 15)
|
|
III128(c, d, a, b, x[11], 15)
|
|
III128(b, c, d, a, x[ 4], 5)
|
|
III128(a, b, c, d, x[13], 7)
|
|
III128(d, a, b, c, x[ 6], 7)
|
|
III128(c, d, a, b, x[15], 8)
|
|
III128(b, c, d, a, x[ 8], 11)
|
|
III128(a, b, c, d, x[ 1], 14)
|
|
III128(d, a, b, c, x[10], 14)
|
|
III128(c, d, a, b, x[ 3], 12)
|
|
III128(b, c, d, a, x[12], 6)
|
|
|
|
template RROUND128N2(a, b, c, d, x): void =
|
|
HHH128(a, b, c, d, x[ 6], 9)
|
|
HHH128(d, a, b, c, x[11], 13)
|
|
HHH128(c, d, a, b, x[ 3], 15)
|
|
HHH128(b, c, d, a, x[ 7], 7)
|
|
HHH128(a, b, c, d, x[ 0], 12)
|
|
HHH128(d, a, b, c, x[13], 8)
|
|
HHH128(c, d, a, b, x[ 5], 9)
|
|
HHH128(b, c, d, a, x[10], 11)
|
|
HHH128(a, b, c, d, x[14], 7)
|
|
HHH128(d, a, b, c, x[15], 7)
|
|
HHH128(c, d, a, b, x[ 8], 12)
|
|
HHH128(b, c, d, a, x[12], 7)
|
|
HHH128(a, b, c, d, x[ 4], 6)
|
|
HHH128(d, a, b, c, x[ 9], 15)
|
|
HHH128(c, d, a, b, x[ 1], 13)
|
|
HHH128(b, c, d, a, x[ 2], 11)
|
|
|
|
template RROUND128N3(a, b, c, d, x): void =
|
|
GGG128(a, b, c, d, x[15], 9)
|
|
GGG128(d, a, b, c, x[ 5], 7)
|
|
GGG128(c, d, a, b, x[ 1], 15)
|
|
GGG128(b, c, d, a, x[ 3], 11)
|
|
GGG128(a, b, c, d, x[ 7], 8)
|
|
GGG128(d, a, b, c, x[14], 6)
|
|
GGG128(c, d, a, b, x[ 6], 6)
|
|
GGG128(b, c, d, a, x[ 9], 14)
|
|
GGG128(a, b, c, d, x[11], 12)
|
|
GGG128(d, a, b, c, x[ 8], 13)
|
|
GGG128(c, d, a, b, x[12], 5)
|
|
GGG128(b, c, d, a, x[ 2], 14)
|
|
GGG128(a, b, c, d, x[10], 13)
|
|
GGG128(d, a, b, c, x[ 0], 13)
|
|
GGG128(c, d, a, b, x[ 4], 7)
|
|
GGG128(b, c, d, a, x[13], 5)
|
|
|
|
template RROUND128N4(a, b, c, d, x): void =
|
|
FFF128(a, b, c, d, x[ 8], 15)
|
|
FFF128(d, a, b, c, x[ 6], 5)
|
|
FFF128(c, d, a, b, x[ 4], 8)
|
|
FFF128(b, c, d, a, x[ 1], 11)
|
|
FFF128(a, b, c, d, x[ 3], 14)
|
|
FFF128(d, a, b, c, x[11], 14)
|
|
FFF128(c, d, a, b, x[15], 6)
|
|
FFF128(b, c, d, a, x[ 0], 14)
|
|
FFF128(a, b, c, d, x[ 5], 6)
|
|
FFF128(d, a, b, c, x[12], 9)
|
|
FFF128(c, d, a, b, x[ 2], 12)
|
|
FFF128(b, c, d, a, x[13], 9)
|
|
FFF128(a, b, c, d, x[ 9], 12)
|
|
FFF128(d, a, b, c, x[ 7], 5)
|
|
FFF128(c, d, a, b, x[10], 15)
|
|
FFF128(b, c, d, a, x[14], 8)
|
|
|
|
template LROUND160N1(a, b, c, d, e, x): void =
|
|
FF160(a, b, c, d, e, x[ 0], 11)
|
|
FF160(e, a, b, c, d, x[ 1], 14)
|
|
FF160(d, e, a, b, c, x[ 2], 15)
|
|
FF160(c, d, e, a, b, x[ 3], 12)
|
|
FF160(b, c, d, e, a, x[ 4], 5)
|
|
FF160(a, b, c, d, e, x[ 5], 8)
|
|
FF160(e, a, b, c, d, x[ 6], 7)
|
|
FF160(d, e, a, b, c, x[ 7], 9)
|
|
FF160(c, d, e, a, b, x[ 8], 11)
|
|
FF160(b, c, d, e, a, x[ 9], 13)
|
|
FF160(a, b, c, d, e, x[10], 14)
|
|
FF160(e, a, b, c, d, x[11], 15)
|
|
FF160(d, e, a, b, c, x[12], 6)
|
|
FF160(c, d, e, a, b, x[13], 7)
|
|
FF160(b, c, d, e, a, x[14], 9)
|
|
FF160(a, b, c, d, e, x[15], 8)
|
|
|
|
template LROUND160N2(a, b, c, d, e, x): void =
|
|
GG160(e, a, b, c, d, x[ 7], 7)
|
|
GG160(d, e, a, b, c, x[ 4], 6)
|
|
GG160(c, d, e, a, b, x[13], 8)
|
|
GG160(b, c, d, e, a, x[ 1], 13)
|
|
GG160(a, b, c, d, e, x[10], 11)
|
|
GG160(e, a, b, c, d, x[ 6], 9)
|
|
GG160(d, e, a, b, c, x[15], 7)
|
|
GG160(c, d, e, a, b, x[ 3], 15)
|
|
GG160(b, c, d, e, a, x[12], 7)
|
|
GG160(a, b, c, d, e, x[ 0], 12)
|
|
GG160(e, a, b, c, d, x[ 9], 15)
|
|
GG160(d, e, a, b, c, x[ 5], 9)
|
|
GG160(c, d, e, a, b, x[ 2], 11)
|
|
GG160(b, c, d, e, a, x[14], 7)
|
|
GG160(a, b, c, d, e, x[11], 13)
|
|
GG160(e, a, b, c, d, x[ 8], 12)
|
|
|
|
template LROUND160N3(a, b, c, d, e, x): void =
|
|
HH160(d, e, a, b, c, x[ 3], 11)
|
|
HH160(c, d, e, a, b, x[10], 13)
|
|
HH160(b, c, d, e, a, x[14], 6)
|
|
HH160(a, b, c, d, e, x[ 4], 7)
|
|
HH160(e, a, b, c, d, x[ 9], 14)
|
|
HH160(d, e, a, b, c, x[15], 9)
|
|
HH160(c, d, e, a, b, x[ 8], 13)
|
|
HH160(b, c, d, e, a, x[ 1], 15)
|
|
HH160(a, b, c, d, e, x[ 2], 14)
|
|
HH160(e, a, b, c, d, x[ 7], 8)
|
|
HH160(d, e, a, b, c, x[ 0], 13)
|
|
HH160(c, d, e, a, b, x[ 6], 6)
|
|
HH160(b, c, d, e, a, x[13], 5)
|
|
HH160(a, b, c, d, e, x[11], 12)
|
|
HH160(e, a, b, c, d, x[ 5], 7)
|
|
HH160(d, e, a, b, c, x[12], 5)
|
|
|
|
template LROUND160N4(a, b, c, d, e, x): void =
|
|
II160(c, d, e, a, b, x[ 1], 11)
|
|
II160(b, c, d, e, a, x[ 9], 12)
|
|
II160(a, b, c, d, e, x[11], 14)
|
|
II160(e, a, b, c, d, x[10], 15)
|
|
II160(d, e, a, b, c, x[ 0], 14)
|
|
II160(c, d, e, a, b, x[ 8], 15)
|
|
II160(b, c, d, e, a, x[12], 9)
|
|
II160(a, b, c, d, e, x[ 4], 8)
|
|
II160(e, a, b, c, d, x[13], 9)
|
|
II160(d, e, a, b, c, x[ 3], 14)
|
|
II160(c, d, e, a, b, x[ 7], 5)
|
|
II160(b, c, d, e, a, x[15], 6)
|
|
II160(a, b, c, d, e, x[14], 8)
|
|
II160(e, a, b, c, d, x[ 5], 6)
|
|
II160(d, e, a, b, c, x[ 6], 5)
|
|
II160(c, d, e, a, b, x[ 2], 12)
|
|
|
|
template LROUND160N5(a, b, c, d, e, x): void =
|
|
JJ160(b, c, d, e, a, x[ 4], 9)
|
|
JJ160(a, b, c, d, e, x[ 0], 15)
|
|
JJ160(e, a, b, c, d, x[ 5], 5)
|
|
JJ160(d, e, a, b, c, x[ 9], 11)
|
|
JJ160(c, d, e, a, b, x[ 7], 6)
|
|
JJ160(b, c, d, e, a, x[12], 8)
|
|
JJ160(a, b, c, d, e, x[ 2], 13)
|
|
JJ160(e, a, b, c, d, x[10], 12)
|
|
JJ160(d, e, a, b, c, x[14], 5)
|
|
JJ160(c, d, e, a, b, x[ 1], 12)
|
|
JJ160(b, c, d, e, a, x[ 3], 13)
|
|
JJ160(a, b, c, d, e, x[ 8], 14)
|
|
JJ160(e, a, b, c, d, x[11], 11)
|
|
JJ160(d, e, a, b, c, x[ 6], 8)
|
|
JJ160(c, d, e, a, b, x[15], 5)
|
|
JJ160(b, c, d, e, a, x[13], 6)
|
|
|
|
template RROUND160N1(a, b, c, d, e, x): void =
|
|
JJJ160(a, b, c, d, e, x[ 5], 8)
|
|
JJJ160(e, a, b, c, d, x[14], 9)
|
|
JJJ160(d, e, a, b, c, x[ 7], 9)
|
|
JJJ160(c, d, e, a, b, x[ 0], 11)
|
|
JJJ160(b, c, d, e, a, x[ 9], 13)
|
|
JJJ160(a, b, c, d, e, x[ 2], 15)
|
|
JJJ160(e, a, b, c, d, x[11], 15)
|
|
JJJ160(d, e, a, b, c, x[ 4], 5)
|
|
JJJ160(c, d, e, a, b, x[13], 7)
|
|
JJJ160(b, c, d, e, a, x[ 6], 7)
|
|
JJJ160(a, b, c, d, e, x[15], 8)
|
|
JJJ160(e, a, b, c, d, x[ 8], 11)
|
|
JJJ160(d, e, a, b, c, x[ 1], 14)
|
|
JJJ160(c, d, e, a, b, x[10], 14)
|
|
JJJ160(b, c, d, e, a, x[ 3], 12)
|
|
JJJ160(a, b, c, d, e, x[12], 6)
|
|
|
|
template RROUND160N2(a, b, c, d, e, x): void =
|
|
III160(e, a, b, c, d, x[ 6], 9)
|
|
III160(d, e, a, b, c, x[11], 13)
|
|
III160(c, d, e, a, b, x[ 3], 15)
|
|
III160(b, c, d, e, a, x[ 7], 7)
|
|
III160(a, b, c, d, e, x[ 0], 12)
|
|
III160(e, a, b, c, d, x[13], 8)
|
|
III160(d, e, a, b, c, x[ 5], 9)
|
|
III160(c, d, e, a, b, x[10], 11)
|
|
III160(b, c, d, e, a, x[14], 7)
|
|
III160(a, b, c, d, e, x[15], 7)
|
|
III160(e, a, b, c, d, x[ 8], 12)
|
|
III160(d, e, a, b, c, x[12], 7)
|
|
III160(c, d, e, a, b, x[ 4], 6)
|
|
III160(b, c, d, e, a, x[ 9], 15)
|
|
III160(a, b, c, d, e, x[ 1], 13)
|
|
III160(e, a, b, c, d, x[ 2], 11)
|
|
|
|
template RROUND160N3(a, b, c, d, e, x): void =
|
|
HHH160(d, e, a, b, c, x[15], 9)
|
|
HHH160(c, d, e, a, b, x[ 5], 7)
|
|
HHH160(b, c, d, e, a, x[ 1], 15)
|
|
HHH160(a, b, c, d, e, x[ 3], 11)
|
|
HHH160(e, a, b, c, d, x[ 7], 8)
|
|
HHH160(d, e, a, b, c, x[14], 6)
|
|
HHH160(c, d, e, a, b, x[ 6], 6)
|
|
HHH160(b, c, d, e, a, x[ 9], 14)
|
|
HHH160(a, b, c, d, e, x[11], 12)
|
|
HHH160(e, a, b, c, d, x[ 8], 13)
|
|
HHH160(d, e, a, b, c, x[12], 5)
|
|
HHH160(c, d, e, a, b, x[ 2], 14)
|
|
HHH160(b, c, d, e, a, x[10], 13)
|
|
HHH160(a, b, c, d, e, x[ 0], 13)
|
|
HHH160(e, a, b, c, d, x[ 4], 7)
|
|
HHH160(d, e, a, b, c, x[13], 5)
|
|
|
|
template RROUND160N4(a, b, c, d, e, x): void =
|
|
GGG160(c, d, e, a, b, x[ 8], 15)
|
|
GGG160(b, c, d, e, a, x[ 6], 5)
|
|
GGG160(a, b, c, d, e, x[ 4], 8)
|
|
GGG160(e, a, b, c, d, x[ 1], 11)
|
|
GGG160(d, e, a, b, c, x[ 3], 14)
|
|
GGG160(c, d, e, a, b, x[11], 14)
|
|
GGG160(b, c, d, e, a, x[15], 6)
|
|
GGG160(a, b, c, d, e, x[ 0], 14)
|
|
GGG160(e, a, b, c, d, x[ 5], 6)
|
|
GGG160(d, e, a, b, c, x[12], 9)
|
|
GGG160(c, d, e, a, b, x[ 2], 12)
|
|
GGG160(b, c, d, e, a, x[13], 9)
|
|
GGG160(a, b, c, d, e, x[ 9], 12)
|
|
GGG160(e, a, b, c, d, x[ 7], 5)
|
|
GGG160(d, e, a, b, c, x[10], 15)
|
|
GGG160(c, d, e, a, b, x[14], 8)
|
|
|
|
template RROUND160N5(a, b, c, d, e, x): void =
|
|
FFF160(b, c, d, e, a, x[12] , 8)
|
|
FFF160(a, b, c, d, e, x[15] , 5)
|
|
FFF160(e, a, b, c, d, x[10] , 12)
|
|
FFF160(d, e, a, b, c, x[ 4] , 9)
|
|
FFF160(c, d, e, a, b, x[ 1] , 12)
|
|
FFF160(b, c, d, e, a, x[ 5] , 5)
|
|
FFF160(a, b, c, d, e, x[ 8] , 14)
|
|
FFF160(e, a, b, c, d, x[ 7] , 6)
|
|
FFF160(d, e, a, b, c, x[ 6] , 8)
|
|
FFF160(c, d, e, a, b, x[ 2] , 13)
|
|
FFF160(b, c, d, e, a, x[13] , 6)
|
|
FFF160(a, b, c, d, e, x[14] , 5)
|
|
FFF160(e, a, b, c, d, x[ 0] , 15)
|
|
FFF160(d, e, a, b, c, x[ 3] , 13)
|
|
FFF160(c, d, e, a, b, x[ 9] , 11)
|
|
FFF160(b, c, d, e, a, x[11] , 11)
|
|
|
|
proc ripemd128Transform(state: var array[4, uint32], data: ptr byte) =
|
|
var
|
|
aa = state[0]
|
|
bb = state[1]
|
|
cc = state[2]
|
|
dd = state[3]
|
|
aaa = state[0]
|
|
bbb = state[1]
|
|
ccc = state[2]
|
|
ddd = state[3]
|
|
X = cast[ptr UncheckedArray[uint32]](data)
|
|
|
|
LROUND128N1(aa, bb, cc, dd, X)
|
|
LROUND128N2(aa, bb, cc, dd, X)
|
|
LROUND128N3(aa, bb, cc, dd, X)
|
|
LROUND128N4(aa, bb, cc, dd, X)
|
|
RROUND128N1(aaa, bbb, ccc, ddd, X)
|
|
RROUND128N2(aaa, bbb, ccc, ddd, X)
|
|
RROUND128N3(aaa, bbb, ccc, ddd, X)
|
|
RROUND128N4(aaa, bbb, ccc, ddd, X)
|
|
|
|
# combine results
|
|
ddd = ddd + cc + state[1]
|
|
state[1] = state[2] + dd + aaa
|
|
state[2] = state[3] + aa + bbb
|
|
state[3] = state[0] + bb + ccc
|
|
state[0] = ddd
|
|
|
|
proc ripemd256Transform(state: var array[8, uint32], data: ptr byte) =
|
|
var
|
|
aa = state[0]
|
|
bb = state[1]
|
|
cc = state[2]
|
|
dd = state[3]
|
|
aaa = state[4]
|
|
bbb = state[5]
|
|
ccc = state[6]
|
|
ddd = state[7]
|
|
X = cast[ptr UncheckedArray[uint32]](data)
|
|
|
|
LROUND128N1(aa, bb, cc, dd, X)
|
|
RROUND128N1(aaa, bbb, ccc, ddd, X)
|
|
swap(aa, aaa)
|
|
LROUND128N2(aa, bb, cc, dd, X)
|
|
RROUND128N2(aaa, bbb, ccc, ddd, X)
|
|
swap(bb, bbb)
|
|
LROUND128N3(aa, bb, cc, dd, X)
|
|
RROUND128N3(aaa, bbb, ccc, ddd, X)
|
|
swap(cc, ccc)
|
|
LROUND128N4(aa, bb, cc, dd, X)
|
|
RROUND128N4(aaa, bbb, ccc, ddd, X)
|
|
swap(dd, ddd)
|
|
|
|
# combine results
|
|
state[0] = state[0] + aa
|
|
state[1] = state[1] + bb
|
|
state[2] = state[2] + cc
|
|
state[3] = state[3] + dd
|
|
state[4] = state[4] + aaa
|
|
state[5] = state[5] + bbb
|
|
state[6] = state[6] + ccc
|
|
state[7] = state[7] + ddd
|
|
|
|
proc ripemd160Transform(state: var array[5, uint32], data: ptr byte) =
|
|
var
|
|
aa = state[0]
|
|
bb = state[1]
|
|
cc = state[2]
|
|
dd = state[3]
|
|
ee = state[4]
|
|
aaa = state[0]
|
|
bbb = state[1]
|
|
ccc = state[2]
|
|
ddd = state[3]
|
|
eee = state[4]
|
|
X = cast[ptr UncheckedArray[uint32]](data)
|
|
|
|
LROUND160N1(aa, bb, cc, dd, ee, X)
|
|
LROUND160N2(aa, bb, cc, dd, ee, X)
|
|
LROUND160N3(aa, bb, cc, dd, ee, X)
|
|
LROUND160N4(aa, bb, cc, dd, ee, X)
|
|
LROUND160N5(aa, bb, cc, dd, ee, X)
|
|
RROUND160N1(aaa, bbb, ccc, ddd, eee, X)
|
|
RROUND160N2(aaa, bbb, ccc, ddd, eee, X)
|
|
RROUND160N3(aaa, bbb, ccc, ddd, eee, X)
|
|
RROUND160N4(aaa, bbb, ccc, ddd, eee, X)
|
|
RROUND160N5(aaa, bbb, ccc, ddd, eee, X)
|
|
|
|
# combine results
|
|
ddd = ddd + cc + state[1]
|
|
state[1] = state[2] + dd + eee
|
|
state[2] = state[3] + ee + aaa
|
|
state[3] = state[4] + aa + bbb
|
|
state[4] = state[0] + bb + ccc
|
|
state[0] = ddd
|
|
|
|
proc ripemd320Transform(state: var array[10, uint32], data: ptr byte) =
|
|
var
|
|
aa = state[0]
|
|
bb = state[1]
|
|
cc = state[2]
|
|
dd = state[3]
|
|
ee = state[4]
|
|
aaa = state[5]
|
|
bbb = state[6]
|
|
ccc = state[7]
|
|
ddd = state[8]
|
|
eee = state[9]
|
|
X = cast[ptr UncheckedArray[uint32]](data)
|
|
|
|
LROUND160N1(aa, bb, cc, dd, ee, X)
|
|
RROUND160N1(aaa, bbb, ccc, ddd, eee, X)
|
|
swap(aa, aaa)
|
|
LROUND160N2(aa, bb, cc, dd, ee, X)
|
|
RROUND160N2(aaa, bbb, ccc, ddd, eee, X)
|
|
swap(bb, bbb)
|
|
LROUND160N3(aa, bb, cc, dd, ee, X)
|
|
RROUND160N3(aaa, bbb, ccc, ddd, eee, X)
|
|
swap(cc, ccc)
|
|
LROUND160N4(aa, bb, cc, dd, ee, X)
|
|
RROUND160N4(aaa, bbb, ccc, ddd, eee, X)
|
|
swap(dd, ddd)
|
|
LROUND160N5(aa, bb, cc, dd, ee, X)
|
|
RROUND160N5(aaa, bbb, ccc, ddd, eee, X)
|
|
swap(ee, eee)
|
|
|
|
# combine results
|
|
state[0] = state[0] + aa
|
|
state[1] = state[1] + bb
|
|
state[2] = state[2] + cc
|
|
state[3] = state[3] + dd
|
|
state[4] = state[4] + ee
|
|
state[5] = state[5] + aaa
|
|
state[6] = state[6] + bbb
|
|
state[7] = state[7] + ccc
|
|
state[8] = state[8] + ddd
|
|
state[9] = state[9] + eee
|
|
|
|
template sizeDigest*(ctx: RipemdContext): uint =
|
|
(ctx.bits div 8)
|
|
|
|
template sizeBlock*(ctx: RipemdContext): uint =
|
|
(64)
|
|
|
|
template sizeDigest*(r: typedesc[ripemd]): int =
|
|
when r is ripemd128:
|
|
(16)
|
|
elif r is ripemd160:
|
|
(20)
|
|
elif r is ripemd256:
|
|
(32)
|
|
elif r is ripemd320:
|
|
(40)
|
|
|
|
template sizeBlock*(r: typedesc[ripemd]): int =
|
|
(64)
|
|
|
|
proc init*(ctx: var RipemdContext) =
|
|
ctx.count[0] = 0
|
|
ctx.count[1] = 0
|
|
|
|
zeroMem(addr ctx.buffer[0], sizeof(byte) * 64)
|
|
|
|
when ctx.bits == 128:
|
|
ctx.state[0] = 0x67452301'u32
|
|
ctx.state[1] = 0xEFCDAB89'u32
|
|
ctx.state[2] = 0x98BADCFE'u32
|
|
ctx.state[3] = 0x10325476'u32
|
|
elif ctx.bits == 160:
|
|
ctx.state[0] = 0x67452301'u32
|
|
ctx.state[1] = 0xEFCDAB89'u32
|
|
ctx.state[2] = 0x98BADCFE'u32
|
|
ctx.state[3] = 0x10325476'u32
|
|
ctx.state[4] = 0xC3D2E1F0'u32
|
|
elif ctx.bits == 256:
|
|
ctx.state[0] = 0x67452301'u32
|
|
ctx.state[1] = 0xEFCDAB89'u32
|
|
ctx.state[2] = 0x98BADCFE'u32
|
|
ctx.state[3] = 0x10325476'u32
|
|
ctx.state[4] = 0x76543210'u32
|
|
ctx.state[5] = 0xFEDCBA98'u32
|
|
ctx.state[6] = 0x89ABCDEF'u32
|
|
ctx.state[7] = 0x01234567'u32
|
|
elif ctx.bits == 320:
|
|
ctx.state[0] = 0x67452301'u32
|
|
ctx.state[1] = 0xEFCDAB89'u32
|
|
ctx.state[2] = 0x98BADCFE'u32
|
|
ctx.state[3] = 0x10325476'u32
|
|
ctx.state[4] = 0xC3D2E1F0'u32
|
|
ctx.state[5] = 0x76543210'u32
|
|
ctx.state[6] = 0xFEDCBA98'u32
|
|
ctx.state[7] = 0x89ABCDEF'u32
|
|
ctx.state[8] = 0x01234567'u32
|
|
ctx.state[9] = 0x3C2D1E0F'u32
|
|
|
|
proc clear*(ctx: var RipemdContext) {.inline.} =
|
|
burnMem(ctx)
|
|
|
|
proc update*(ctx: var RipemdContext, data: ptr byte, ulen: uint) =
|
|
var pos = 0'u
|
|
var length = ulen
|
|
|
|
while length > 0'u:
|
|
let offset = cast[uint](ctx.count[0] and 0x3F)
|
|
let size = min(64'u - offset, length)
|
|
copyMem(addr(ctx.buffer[offset]),
|
|
cast[pointer](cast[uint](data) + pos), size)
|
|
pos = pos + size
|
|
length = length - size
|
|
ctx.count[0] += cast[uint32](size)
|
|
if ctx.count[0] < cast[uint32](size):
|
|
ctx.count[1] += 1'u32
|
|
if (ctx.count[0] and 0x3F) == 0:
|
|
when ctx.bits == 128:
|
|
ripemd128Transform(ctx.state, addr(ctx.buffer[0]))
|
|
elif ctx.bits == 160:
|
|
ripemd160Transform(ctx.state, addr(ctx.buffer[0]))
|
|
elif ctx.bits == 256:
|
|
ripemd256Transform(ctx.state, addr(ctx.buffer[0]))
|
|
elif ctx.bits == 320:
|
|
ripemd320Transform(ctx.state, addr(ctx.buffer[0]))
|
|
|
|
proc update*[T: bchar](ctx: var RipemdContext, data: openarray[T]) =
|
|
if len(data) == 0:
|
|
ctx.update(nil, 0)
|
|
else:
|
|
ctx.update(cast[ptr byte](unsafeAddr data[0]), cast[uint](len(data)))
|
|
|
|
proc finalize(ctx: var RipemdContext) =
|
|
let size = (ctx.count[0] and 0x3F)
|
|
var buffer = addr(ctx.buffer[0])
|
|
zeroMem(addr(ctx.buffer[size]), 0x40'u - size)
|
|
ctx.buffer[size] = 0x80
|
|
if size > 55'u32:
|
|
when ctx.bits == 128:
|
|
ripemd128Transform(ctx.state, addr(ctx.buffer[0]))
|
|
elif ctx.bits == 160:
|
|
ripemd160Transform(ctx.state, addr(ctx.buffer[0]))
|
|
elif ctx.bits == 256:
|
|
ripemd256Transform(ctx.state, addr(ctx.buffer[0]))
|
|
elif ctx.bits == 320:
|
|
ripemd320Transform(ctx.state, addr(ctx.buffer[0]))
|
|
zeroMem(addr(ctx.buffer[0]), 0x40)
|
|
SET_DWORD(buffer, 14, (ctx.count[0]) shl 3)
|
|
SET_DWORD(buffer, 15, (ctx.count[0] shr 29) or (ctx.count[1] shl 3))
|
|
when ctx.bits == 128:
|
|
ripemd128Transform(ctx.state, addr(ctx.buffer[0]))
|
|
elif ctx.bits == 160:
|
|
ripemd160Transform(ctx.state, addr(ctx.buffer[0]))
|
|
elif ctx.bits == 256:
|
|
ripemd256Transform(ctx.state, addr(ctx.buffer[0]))
|
|
elif ctx.bits == 320:
|
|
ripemd320Transform(ctx.state, addr(ctx.buffer[0]))
|
|
|
|
proc finish*(ctx: var RipemdContext, data: ptr byte, ulen: uint): uint =
|
|
result = 0
|
|
finalize(ctx)
|
|
when ctx.bits == 128:
|
|
if ulen >= 16'u:
|
|
result = sizeDigest(ctx)
|
|
for i in 0..3:
|
|
SET_DWORD(data, i, BSWAP(ctx.state[i]))
|
|
elif ctx.bits == 160:
|
|
if ulen >= 20'u:
|
|
result = sizeDigest(ctx)
|
|
for i in 0..4:
|
|
SET_DWORD(data, i, BSWAP(ctx.state[i]))
|
|
elif ctx.bits == 256:
|
|
if ulen >= 32'u:
|
|
result = sizeDigest(ctx)
|
|
for i in 0..7:
|
|
SET_DWORD(data, i, BSWAP(ctx.state[i]))
|
|
elif ctx.bits == 320:
|
|
if ulen >= 40'u:
|
|
result = sizeDigest(ctx)
|
|
for i in 0..9:
|
|
SET_DWORD(data, i, BSWAP(ctx.state[i]))
|
|
|
|
proc finish*(ctx: var RipemdContext): MDigest[ctx.bits] =
|
|
discard finish(ctx, cast[ptr byte](addr result.data[0]),
|
|
cast[uint](len(result.data)))
|
|
|
|
proc finish*[T: bchar](ctx: var RipemdContext, data: var openarray[T]) =
|
|
assert(uint(len(data)) >= ctx.sizeDigest)
|
|
discard ctx.finish(cast[ptr byte](addr data[0]), cast[uint](len(data)))
|