1
0
Fork 0
mirror of synced 2025-09-23 04:08:33 +00:00

Fix keccak padding issue, allow arbitrary input size

This commit is contained in:
dark64 2022-04-28 15:46:54 +02:00
parent 7fae54d598
commit 4980565e9d
15 changed files with 322 additions and 82 deletions

View file

@ -1,4 +1,7 @@
import "hashes/keccak/keccak" as keccak
from "hashes/keccak/keccak" import keccak, main as keccak_u8
def keccak256<N>(u8[N] input) -> u64[4]:
return keccak_u8::<_, 256>(input, 0x0000000000000001)[..4]
def main<N>(u64[N] input) -> u64[4]:
return keccak::<_, 256>(input, 0x0000000000000001)[..4]

View file

@ -1,4 +1,7 @@
import "hashes/keccak/keccak" as keccak
from "hashes/keccak/keccak" import keccak, main as keccak_u8
def keccak384<N>(u8[N] input) -> u64[6]:
return keccak_u8::<_, 384>(input, 0x0000000000000001)[..6]
def main<N>(u64[N] input) -> u64[6]:
return keccak::<_, 384>(input, 0x0000000000000001)[..6]

View file

@ -1,4 +1,7 @@
import "hashes/keccak/keccak" as keccak
from "hashes/keccak/keccak" import keccak, main as keccak_u8
def keccak512<N>(u8[N] input) -> u64[8]:
return keccak_u8::<_, 512>(input, 0x0000000000000001)[..8]
def main<N>(u64[N] input) -> u64[8]:
return keccak::<_, 512>(input, 0x0000000000000001)[..8]

View file

@ -1,6 +1,9 @@
// https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf
// based on keccak-f[1600] permutation
import "utils/casts/u64_from_bits"
import "utils/casts/u8_to_bits"
const u32[24] RHO = [
1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14,
27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44
@ -76,7 +79,7 @@ def keccakf(u64[25] st) -> u64[25]:
endfor
return st
def main<N, W>(u64[N] input, u64 pad) -> u64[25]:
def keccak<N, W>(u64[N] input, u64 pad) -> u64[25]:
u64[25] q = [0; 25]
u32 rate = (200 - (W / 4)) / 8
u32 pt = 0
@ -93,6 +96,8 @@ def main<N, W>(u64[N] input, u64 pad) -> u64[25]:
q = if pt == 0 then keccakf(q) else q fi
endfor
pt = if (pad & 0x00000000000000ff) != 0 then pt else pt - 1 fi
// finalize
q[pt] = q[pt] ^ pad
q[rate - 1] = q[rate - 1] ^ 0x8000000000000000
@ -103,4 +108,32 @@ def main<N, W>(u64[N] input, u64 pad) -> u64[25]:
q[i] = swap_u64(q[i])
endfor
return q
return q
def u8_array_to_u64(u8[8] input) -> u64:
bool[64] bits = [
...u8_to_bits(input[0]),
...u8_to_bits(input[1]),
...u8_to_bits(input[2]),
...u8_to_bits(input[3]),
...u8_to_bits(input[4]),
...u8_to_bits(input[5]),
...u8_to_bits(input[6]),
...u8_to_bits(input[7])
]
return u64_from_bits(bits)
def main<N, W>(u8[N] input, u64 pad) -> u64[25]:
u32 L = N / 8
u32 R = if L * 8 == N then 0 else 1 fi
u32 len = L + R
u8[len * 8] padded = [...input, ...[0; len * 8 - N]]
u64[len] input_u64 = [0; len]
for u32 i in 0..len do
u32 j = i * 8
input_u64[i] = u8_array_to_u64(padded[j..j+8])
endfor
return keccak::<_, W>(input_u64, pad << ((N % 8) * 8))

View file

@ -1,4 +1,7 @@
import "hashes/keccak/keccak" as keccak
from "hashes/keccak/keccak" import keccak, main as keccak_u8
def sha3_256<N>(u8[N] input) -> u64[4]:
return keccak_u8::<_, 256>(input, 0x0000000000000006)[..4]
def main<N>(u64[N] input) -> (u64[4]):
return keccak::<_, 256>(input, 0x0000000000000006)[..4]

View file

@ -1,4 +1,7 @@
import "hashes/keccak/keccak" as keccak
from "hashes/keccak/keccak" import keccak, main as keccak_u8
def sha3_384<N>(u8[N] input) -> u64[6]:
return keccak_u8::<_, 384>(input, 0x0000000000000006)[..6]
def main<N>(u64[N] input) -> (u64[6]):
return keccak::<_, 384>(input, 0x0000000000000006)[..6]

View file

@ -1,4 +1,7 @@
import "hashes/keccak/keccak" as keccak
from "hashes/keccak/keccak" import keccak, main as keccak_u8
def sha3_512<N>(u8[N] input) -> u64[8]:
return keccak_u8::<_, 512>(input, 0x0000000000000006)[..8]
def main<N>(u64[N] input) -> (u64[8]):
return keccak::<_, 512>(input, 0x0000000000000006)[..8]

View file

@ -1,14 +1,37 @@
import "hashes/keccak/256bit" as keccak256
// Python code:
// >>> from Crypto.Hash import keccak
// >>> digest = keccak.new(digest_bits=256)
// >>> digest.update(b'\x00\x00\x00\x00\x00\x00\x00\x2A' * 20)
// >>> digest.hexdigest()
// '33d0141407fee6e5d9caf6ae44e840bc67a37da55e3c845fbc2b4a6dce1f02f0'
from "hashes/keccak/256bit" import keccak256
def main():
u64[4] h = keccak256::<20>([42; 20])
assert(h == [0x33D0141407FEE6E5, 0xD9CAF6AE44E840BC, 0x67A37DA55E3C845F, 0xBC2B4A6DCE1F02F0])
// Python:
// >>> from Crypto.Hash import keccak
// >>> digest = keccak.new(digest_bits=256)
// >>> digest.update(b'\x2a')
// >>> digest.hexdigest()
// '04994f67dc55b09e814ab7ffc8df3686b4afb2bb53e60eae97ef043fe03fb829'
u64[4] h1 = keccak256::<1>([0x2a])
assert(h1 == [0x04994f67dc55b09e, 0x814ab7ffc8df3686, 0xb4afb2bb53e60eae, 0x97ef043fe03fb829])
// Python:
// >>> from Crypto.Hash import keccak
// >>> digest = keccak.new(digest_bits=256)
// >>> digest.update(b'\x2a' * 8)
// >>> digest.hexdigest()
// '4d57ecea94f7735c23ae7c02845a500a815c21fc6d6046d2d7d518fad6bebf89'
u64[4] h2 = keccak256::<8>([0x2a; 8])
assert(h2 == [0x4d57ecea94f7735c, 0x23ae7c02845a500a, 0x815c21fc6d6046d2, 0xd7d518fad6bebf89])
// Python:
// >>> from Crypto.Hash import keccak
// >>> input = "hello world".encode()
// >>> input.hex()
// '68656c6c6f20776f726c64'
// >>> digest = keccak.new(digest_bits=256)
// >>> digest.update(input)
// >>> digest.hexdigest()
// '47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad'
u64[4] h3 = keccak256::<11>([0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64])
assert(h3 == [0x47173285a8d7341e, 0x5e972fc677286384, 0xf802f8ef42a5ec5f, 0x03bbfa254cb01fad])
return

View file

@ -1,17 +1,45 @@
import "hashes/keccak/384bit" as keccak384
// Python code:
// >>> from Crypto.Hash import keccak
// >>> digest = keccak.new(digest_bits=384)
// >>> digest.update(b'\x00\x00\x00\x00\x00\x00\x00\x2A' * 20)
// >>> digest.hexdigest()
// 'a944b9b859c1e69d66b52d4cf1f678b24ed8a9ccb0a32bbe882af8a3a1acbd3b68eed9c628307e5d3789f1a64a50e8e7'
from "hashes/keccak/384bit" import keccak384
def main():
u64[6] h = keccak384([42; 20])
assert(h == [
0xA944B9B859C1E69D, 0x66B52D4CF1F678B2, 0x4ED8A9CCB0A32BBE,
0x882AF8A3A1ACBD3B, 0x68EED9C628307E5D, 0x3789F1A64A50E8E7
// Python:
// >>> from Crypto.Hash import keccak
// >>> digest = keccak.new(digest_bits=384)
// >>> digest.update(b'\x2a')
// >>> digest.hexdigest()
// '53403c11270822eebdccc9aca81e0582996de74333909598a4e4c409967fb9da14a1506264996c855eb5d9a42fd21a08'
u64[6] h1 = keccak384::<1>([0x2a])
assert(h1 == [
0x53403c11270822ee, 0xbdccc9aca81e0582, 0x996de74333909598,
0xa4e4c409967fb9da, 0x14a1506264996c85, 0x5eb5d9a42fd21a08
])
// Python:
// >>> from Crypto.Hash import keccak
// >>> digest = keccak.new(digest_bits=384)
// >>> digest.update(b'\x2a' * 8)
// >>> digest.hexdigest()
// 'ec7216058c28201daeb6fd1599b81fdbd40e229b31bea3b6b3190f21db81b01baf3d000e40801ab59551133efbac6cce'
u64[6] h2 = keccak384::<8>([0x2a; 8])
assert(h2 == [
0xec7216058c28201d, 0xaeb6fd1599b81fdb, 0xd40e229b31bea3b6,
0xb3190f21db81b01b, 0xaf3d000e40801ab5, 0x9551133efbac6cce
])
// Python:
// >>> from Crypto.Hash import keccak
// >>> input = "hello world".encode()
// >>> input.hex()
// '68656c6c6f20776f726c64'
// >>> digest = keccak.new(digest_bits=384)
// >>> digest.update(input)
// >>> digest.hexdigest()
// '65fc99339a2a40e99d3c40d695b22f278853ca0f925cde4254bcae5e22ece47e6441f91b6568425adc9d95b0072eb49f'
u64[6] h3 = keccak384::<11>([0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64])
assert(h3 == [
0x65fc99339a2a40e9, 0x9d3c40d695b22f27, 0x8853ca0f925cde42,
0x54bcae5e22ece47e, 0x6441f91b6568425a, 0xdc9d95b0072eb49f
])
return

View file

@ -1,17 +1,45 @@
import "hashes/keccak/512bit" as keccak512
// Python code:
// >>> from Crypto.Hash import keccak
// >>> digest = keccak.new(digest_bits=512)
// >>> digest.update(b'\x00\x00\x00\x00\x00\x00\x00\x2A' * 20)
// >>> digest.hexdigest()
// '5451affca80019c7ac9a7ff647ca073b56e19d55857031df14e00bb1d36ed18a05bdac99bcc0417240dea0cf3fddd19144b8d1e9618fd3f6c8f1a79f7e489eb8'
from "hashes/keccak/512bit" import keccak512
def main():
u64[8] h = keccak512::<20>([42; 20])
assert(h == [
0x5451AFFCA80019C7, 0xAC9A7FF647CA073B, 0x56E19D55857031DF, 0x14E00BB1D36ED18A,
0x05BDAC99BCC04172, 0x40DEA0CF3FDDD191, 0x44B8D1E9618FD3F6, 0xC8F1A79F7E489EB8
// Python:
// >>> from Crypto.Hash import keccak
// >>> digest = keccak.new(digest_bits=512)
// >>> digest.update(b'\x2a')
// >>> digest.hexdigest()
// 'a470459552991801eca017c8bfeedb376469c9b642a2cca455a3271c5751ad3be53d9f4ddce99613515e954bd3d80d218a2f43f953141ec6bdcaf7ba4a4bad67'
u64[8] h1 = keccak512::<1>([0x2a])
assert(h1 == [
0xa470459552991801, 0xeca017c8bfeedb37, 0x6469c9b642a2cca4, 0x55a3271c5751ad3b,
0xe53d9f4ddce99613, 0x515e954bd3d80d21, 0x8a2f43f953141ec6, 0xbdcaf7ba4a4bad67
])
// Python:
// >>> from Crypto.Hash import keccak
// >>> digest = keccak.new(digest_bits=512)
// >>> digest.update(b'\x2a' * 8)
// >>> digest.hexdigest()
// '91e7b4ca7569fb43a180354878bcd807578e207c0dec866d7bc7569d86996a86bce7bd05ab32138797693e76882475a819352919cd81585110e5dfb1c8710337'
u64[8] h2 = keccak512::<8>([0x2a; 8])
assert(h2 == [
0x91e7b4ca7569fb43, 0xa180354878bcd807, 0x578e207c0dec866d, 0x7bc7569d86996a86,
0xbce7bd05ab321387, 0x97693e76882475a8, 0x19352919cd815851, 0x10e5dfb1c8710337
])
// Python:
// >>> from Crypto.Hash import keccak
// >>> input = "hello world".encode()
// >>> input.hex()
// '68656c6c6f20776f726c64'
// >>> digest = keccak.new(digest_bits=512)
// >>> digest.update(input)
// >>> digest.hexdigest()
// '3ee2b40047b8060f68c67242175660f4174d0af5c01d47168ec20ed619b0b7c42181f40aa1046f39e2ef9efc6910782a998e0013d172458957957fac9405b67d'
u64[8] h3 = keccak512::<11>([0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64])
assert(h3 == [
0x3ee2b40047b8060f, 0x68c67242175660f4, 0x174d0af5c01d4716, 0x8ec20ed619b0b7c4,
0x2181f40aa1046f39, 0xe2ef9efc6910782a, 0x998e0013d1724589, 0x57957fac9405b67d
])
return

View file

@ -0,0 +1,15 @@
{
"entry_point": "./tests/tests/hashes/keccak/keccak.zok",
"tests": [
{
"input": {
"values": []
},
"output": {
"Ok": {
"values": []
}
}
}
]
}

View file

@ -0,0 +1,14 @@
from "hashes/keccak/keccak" import keccak
def main():
// Python:
// >>> from Crypto.Hash import keccak
// >>> digest = keccak.new(digest_bits=256)
// >>> digest.update(b'\x7a\x6f\x6b\x72\x61\x74\x65\x73')
// >>> digest.hexdigest()
// 'ca85d1976d40dcb6ca3becc8c6596e83c0774f4185cf016a05834f5856a37f39'
u64[4] h = keccak::<1, 256>([0x7a6f6b7261746573], 0x0000000000000001)[..4]
assert(h == [0xca85d1976d40dcb6, 0xca3becc8c6596e83, 0xc0774f4185cf016a, 0x05834f5856a37f39])
return

View file

@ -1,14 +1,37 @@
import "hashes/sha3/256bit" as sha3_256
// Python code:
// >>> from Crypto.Hash import SHA3_256
// >>> digest = SHA3_256.new()
// >>> digest.update(b'\x00\x00\x00\x00\x00\x00\x00\x2A' * 20)
// >>> digest.hexdigest()
// '18d00c9e97cd5516243b67b243ede9e2cf0d45d3a844d33340bfc4efc9165100'
from "hashes/sha3/256bit" import sha3_256
def main():
u64[4] h = sha3_256([42; 20])
assert(h == [0x18D00C9E97CD5516, 0x243B67B243EDE9E2, 0xCF0D45D3A844D333, 0x40BFC4EFC9165100])
// Python:
// >>> from Crypto.Hash import SHA3_256
// >>> digest = SHA3_256.new()
// >>> digest.update(b'\x2a')
// >>> digest.hexdigest()
// '82283b4b030589a7aa0ca28b8e933ac0bd89738a0df509806c864366deec31d7'
u64[4] h1 = sha3_256::<1>([0x2a])
assert(h1 == [0x82283b4b030589a7, 0xaa0ca28b8e933ac0, 0xbd89738a0df50980, 0x6c864366deec31d7])
// Python:
// >>> from Crypto.Hash import SHA3_256
// >>> digest = SHA3_256.new()
// >>> digest.update(b'\x2a' * 8)
// >>> digest.hexdigest()
// '02794645c5d54624a86e237cda0cbe980075f3908ccb00fd67befd2a0bbe0b35'
u64[4] h2 = sha3_256::<8>([0x2a; 8])
assert(h2 == [0x02794645c5d54624, 0xa86e237cda0cbe98, 0x0075f3908ccb00fd, 0x67befd2a0bbe0b35])
// Python:
// >>> from Crypto.Hash import SHA3_256
// >>> input = "hello world".encode()
// >>> input.hex()
// '68656c6c6f20776f726c64'
// >>> digest = SHA3_256.new()
// >>> digest.update(input)
// >>> digest.hexdigest()
// '644bcc7e564373040999aac89e7622f3ca71fba1d972fd94a31c3bfbf24e3938'
u64[4] h3 = sha3_256::<11>([0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64])
assert(h3 == [0x644bcc7e56437304, 0x0999aac89e7622f3, 0xca71fba1d972fd94, 0xa31c3bfbf24e3938])
return

View file

@ -1,17 +1,46 @@
import "hashes/sha3/384bit" as sha3_384
// Python code:
// >>> from Crypto.Hash import SHA3_384
// >>> digest = SHA3_384.new()
// >>> digest.update(b'\x00\x00\x00\x00\x00\x00\x00\x2A' * 20)
// >>> digest.hexdigest()
// 'fbb5abd69915e316836d438f0e833a3ebd0f2d8a11e17e248c96c77210b183aab0874eaaef37609d2c4a9a37a6e9740f'
from "hashes/sha3/384bit" import sha3_384
def main():
u64[6] h = sha3_384::<20>([42; 20])
assert(h == [
0xFBB5ABD69915E316, 0x836D438F0E833A3E, 0xBD0F2D8A11E17E24,
0x8C96C77210B183AA, 0xB0874EAAEF37609D, 0x2C4A9A37A6E9740F
// Python:
// >>> from Crypto.Hash import SHA3_384
// >>> digest = SHA3_384.new()
// >>> digest.update(b'\x2a')
// >>> digest.hexdigest()
// '386f0e977e65e7609217714a7cd450e145efbc645ad7c7c78d6c9f12b52cb4df22729b2330b7f5267bac9a5750d9130e'
u64[6] h1 = sha3_384::<1>([0x2a])
assert(h1 == [
0x386f0e977e65e760, 0x9217714a7cd450e1, 0x45efbc645ad7c7c7,
0x8d6c9f12b52cb4df, 0x22729b2330b7f526, 0x7bac9a5750d9130e
])
// Python:
// >>> from Crypto.Hash import SHA3_384
// >>> digest = SHA3_384.new()
// >>> digest.update(b'\x2a' * 8)
// >>> digest.hexdigest()
// 'b5e5109aa62d1633ca3b4c8fcf90b71192b7ebbca1159a65546be6bea5a53f748c513f97556e86d3516b3f9384ff4380'
u64[6] h2 = sha3_384::<8>([0x2a; 8])
assert(h2 == [
0xb5e5109aa62d1633, 0xca3b4c8fcf90b711, 0x92b7ebbca1159a65,
0x546be6bea5a53f74, 0x8c513f97556e86d3, 0x516b3f9384ff4380
])
// Python:
// >>> from Crypto.Hash import SHA3_384
// >>> input = "hello world".encode()
// >>> input.hex()
// '68656c6c6f20776f726c64'
// >>> digest = SHA3_384.new()
// >>> digest.update(input)
// >>> digest.hexdigest()
// '83bff28dde1b1bf5810071c6643c08e5b05bdb836effd70b403ea8ea0a634dc4997eb1053aa3593f590f9c63630dd90b'
u64[6] h3 = sha3_384::<11>([0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64])
assert(h3 == [
0x83bff28dde1b1bf5, 0x810071c6643c08e5, 0xb05bdb836effd70b,
0x403ea8ea0a634dc4, 0x997eb1053aa3593f, 0x590f9c63630dd90b
])
return

View file

@ -1,17 +1,46 @@
import "hashes/sha3/512bit" as sha3_512
// Python code:
// >>> from Crypto.Hash import SHA3_512
// >>> digest = SHA3_512.new()
// >>> digest.update(b'\x00\x00\x00\x00\x00\x00\x00\x2A' * 20)
// >>> digest.hexdigest()
// '73a0967b68de5ce1093cbd7482fd4de9ccc9c782e2edc71b583d26fe16fb19e3322a2a024b7f6e163fbb1a15161686dd3a39233f9cf8616e7c74e91fa1aa3b2b'
from "hashes/sha3/512bit" import sha3_512
def main():
u64[8] h = sha3_512([42; 20])
assert(h == [
0x73A0967B68DE5CE1, 0x093CBD7482FD4DE9, 0xCCC9C782E2EDC71B, 0x583D26FE16FB19E3,
0x322A2A024B7F6E16, 0x3FBB1A15161686DD, 0x3A39233F9CF8616E, 0x7C74E91FA1AA3B2B
// Python:
// >>> from Crypto.Hash import SHA3_512
// >>> digest = SHA3_512.new()
// >>> digest.update(b'\x2a')
// >>> digest.hexdigest()
// '0f8e235b563113abb8a914eb6efc4a31280f1d2341920dfb88bdd20a00d7e47d601a353e5821142acf0dd9ec53bfe4bfe9a2a16f98933142e1c6938c8939b3a0'
u64[8] h1 = sha3_512::<1>([0x2a])
assert(h1 == [
0x0f8e235b563113ab, 0xb8a914eb6efc4a31, 0x280f1d2341920dfb, 0x88bdd20a00d7e47d,
0x601a353e5821142a, 0xcf0dd9ec53bfe4bf, 0xe9a2a16f98933142, 0xe1c6938c8939b3a0
])
// Python:
// >>> from Crypto.Hash import SHA3_512
// >>> digest = SHA3_512.new()
// >>> digest.update(b'\x2a' * 8)
// >>> digest.hexdigest()
// '5e908c2962bcd38fddd1ae4ed4c44eb3396cad53eb36564881979435e18a8e71eda1cbea2fe0fc6ded0672756312b12f8dad38e7528af173ea10095a28cd5555'
u64[8] h2 = sha3_512::<8>([0x2a; 8])
assert(h2 == [
0x5e908c2962bcd38f, 0xddd1ae4ed4c44eb3, 0x396cad53eb365648, 0x81979435e18a8e71,
0xeda1cbea2fe0fc6d, 0xed0672756312b12f, 0x8dad38e7528af173, 0xea10095a28cd5555
])
// Python:
// >>> from Crypto.Hash import SHA3_512
// >>> input = "hello world".encode()
// >>> input.hex()
// '68656c6c6f20776f726c64'
// >>> digest = SHA3_512.new()
// >>> digest.update(input)
// >>> digest.hexdigest()
// '840006653e9ac9e95117a15c915caab81662918e925de9e004f774ff82d7079a40d4d27b1b372657c61d46d470304c88c788b3a4527ad074d1dccbee5dbaa99a'
u64[8] h3 = sha3_512::<11>([0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64])
assert(h3 == [
0x840006653e9ac9e9, 0x5117a15c915caab8, 0x1662918e925de9e0, 0x04f774ff82d7079a,
0x40d4d27b1b372657, 0xc61d46d470304c88, 0xc788b3a4527ad074, 0xd1dccbee5dbaa99a
])
return