v2 / vlib / x / crypto / mldsa / prehash.v
66 lines · 60 sloc · 2.17 KB · 8e35f4d9848f7ad35d857a187dddbfd2eca5e19d
Raw
1// FIPS 204 s. 5.4: Pre-Hash ML-DSA
2// signs PH(M) instead of M directly, prefer using pure ml-dsa when possible
3
4module mldsa
5
6import crypto.sha256
7import crypto.sha512
8import crypto.sha3
9
10// algo. 4/5: DER-encoded OID for each pre-hash function
11// all under arc 2.16.840.1.101.3.4.2
12// joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithm(4) hashAlgs(2)
13fn prehash_oid(ph PreHash) []u8 {
14 suffix := match ph {
15 .sha2_256 { u8(0x01) }
16 .sha2_384 { u8(0x02) }
17 .sha2_512 { u8(0x03) }
18 .sha2_224 { u8(0x04) }
19 .sha2_512_224 { u8(0x05) }
20 .sha2_512_256 { u8(0x06) }
21 .sha3_224 { u8(0x07) }
22 .sha3_256 { u8(0x08) }
23 .sha3_384 { u8(0x09) }
24 .sha3_512 { u8(0x0a) }
25 .shake_128 { u8(0x0b) }
26 .shake_256 { u8(0x0c) }
27 // unreachable, called from mu_prehash, which is called from sign when ph != .none
28 .none { panic('mldsa: prehash_oid called with .none') }
29 }
30
31 return [u8(0x06), 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, suffix]
32}
33
34// algo. 4, lines 10-22: PH(M) for the given hash function
35fn prehash_message(msg []u8, ph PreHash) []u8 {
36 return match ph {
37 .sha2_224 { sha256.sum224(msg) }
38 .sha2_256 { sha256.sum256(msg) }
39 .sha2_384 { sha512.sum384(msg) }
40 .sha2_512 { sha512.sum512(msg) }
41 .sha2_512_224 { sha512.sum512_224(msg) }
42 .sha2_512_256 { sha512.sum512_256(msg) }
43 .sha3_224 { sha3.sum224(msg) }
44 .sha3_256 { sha3.sum256(msg) }
45 .sha3_384 { sha3.sum384(msg) }
46 .sha3_512 { sha3.sum512(msg) }
47 .shake_128 { sha3.shake128(msg, 32) }
48 .shake_256 { sha3.shake256(msg, 64) }
49 // unreachable, called from mu_prehash, which is called from sign when ph != .none
50 .none { panic('mldsa: prehash_message called with .none') }
51 }
52}
53
54// algo. 4, line 23: M' = 0x01 || |ctx| || ctx || OID || PH(M)
55// algo. 7, line 6: mu = H(tr || M')
56// compute_mu_prehash computes mu for prehash mode: H(tr || 0x01 || |ctx| || ctx || OID || PH(msg), 64).
57pub fn compute_mu_prehash(tr []u8, msg []u8, context string, ph PreHash) [64]u8 {
58 mut h := sha3.new_shake256()
59 h.write(tr)
60 h.write([u8(0x01)]) // domain sep
61 h.write([u8(context.len)])
62 h.write(context.bytes())
63 h.write(prehash_oid(ph))
64 h.write(prehash_message(msg, ph))
65 return slice_to_64(h.read(64))
66}
67