~ehmry/nim_sphincs

ref: adb3c7562b087a342e562bbb0d4347c63101b4f9 nim_sphincs/src/sphincs/private/sphincs_shake256.nim -rw-r--r-- 3.8 KiB
adb3c756Emery Hemingway Give credit for SHA3 library 3 years ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
{.push checks: off.} # painfully slow

include ./sphincsbase.nim

import sha3

proc sha3_update(ctx: var SHA3; adrs: Address) =
  var buf: array[4, byte]
  for w in adrs.items:
    w.toByte(buf)
    sha3_update(ctx, buf)

proc F(pk: PK; adrs: Address; M1: Nbytes): Nbytes =
  var ctx: SHA3
  sha3_init(ctx, SHA3_SHAKE256, n)
  sha3_update(ctx, pk.seed)
  sha3_update(ctx, adrs)
  sha3_final(ctx, result)
    # create a bitmask in result space
  for i in 0..<n:
    result[i] = result[i] xor M1[i]
    # apply bitmask to message
  sha3_init(ctx, SHA3_SHAKE256, n)
  sha3_update(ctx, pk.seed)
  sha3_update(ctx, adrs)
  sha3_update(ctx, result)
    # hash again with bitmasked message
  sha3_final(ctx, result)

proc H(pk: PK; adrs: Address; M1, M2: Nbytes): Nbytes =
  var
    bitmasked: array[2*n, byte]
    ctx: SHA3
  sha3_init(ctx, SHA3_SHAKE256, n*2)
  sha3_update(ctx, pk.seed)
  sha3_update(ctx, adrs)
  sha3_final(ctx, bitmasked)
    # create bitmask
  for i in 0..<n:
    bitmasked[i] = bitmasked[i] xor M1[i]
  for i in n..<n*2:
    bitmasked[i] = bitmasked[i] xor M2[i-n]
    # apply bitmask to messages
  sha3_init(ctx, SHA3_SHAKE256, n)
  sha3_update(ctx, pk.seed)
  sha3_update(ctx, adrs)
  sha3_update(ctx, bitmasked)
    # hash again with bitmasked message
  sha3_final(ctx, result)

proc T_k(pk: PK; adrs: Address; M: array[k, Nbytes]): Nbytes =
  var
    bitmasked: array[M.len*n, byte]
    ctx: SHA3
  sha3_init(ctx, SHA3_SHAKE256, M.len*n)
  sha3_update(ctx, pk.seed)
  sha3_update(ctx, adrs)
  sha3_final(ctx, bitmasked)
    # create bitmask
  var off: int
  for i in 0..<M.len:
    for j in 0..<n:
      bitmasked[off] = bitmasked[off] xor M[i][j]
      inc off
    # apply bitmask to messages
  sha3_init(ctx, SHA3_SHAKE256, n)
  sha3_update(ctx, pk.seed)
  sha3_update(ctx, adrs)
  sha3_update(ctx, bitmasked)
    # hash again with bitmasked message
  sha3_final(ctx, result)

proc T_len(pk: PK; adrs: Address; M: array[wotsLen, Nbytes]): Nbytes =
  var
    bitmasked: array[M.len*n, byte]
    ctx: SHA3
  sha3_init(ctx, SHA3_SHAKE256, M.len*n)
  sha3_update(ctx, pk.seed)
  sha3_update(ctx, adrs)
  sha3_final(ctx, bitmasked)
    # create bitmask
  var off: int
  for i in 0..<M.len:
    for j in 0..<n:
      bitmasked[off] = bitmasked[off] xor M[i][j]
      inc off
    # apply bitmask to messages
  sha3_init(ctx, SHA3_SHAKE256, n)
  sha3_update(ctx, pk.seed)
  sha3_update(ctx, adrs)
  sha3_update(ctx, bitmasked)
    # hash again with bitmasked message
  sha3_final(ctx, result)

proc PRFmsg(sk: SK; optRand: Nbytes; M: string|openArray[byte]): Nbytes =
  ## Pseudorandom function to generate randomness for message compression.
  var ctx: SHA3
  sha3_init(ctx, SHA3_SHAKE256, n)
  sha3_update(ctx, sk.prf)
  sha3_update(ctx, optRand)
  sha3_update(ctx, M, M.len)
  sha3_final(ctx, result)

proc Hmsg(R: Nbytes; pk: PK; M: string|openArray[byte]): (array[partialDigestBytes,byte], int64, int32) =
  ## Keyed hash funcion for compression messages to be signed.
  var
    digest: array[m, byte]
    ctx: SHA3
  sha3_init(ctx, SHA3_SHAKE256, m)
  sha3_update(ctx, R)
  sha3_update(ctx, pk.seed)
  sha3_update(ctx, pk.root)
  sha3_update(ctx, M, M.len)
  sha3_final(ctx, digest)

  copyMem(result[0].addr, digest.addr, partialDigestBytes)

  # take the last bits from the tree and leaf index regions
  bigEndian64(result[1].addr, digest[digest.len-8-leafIndexBytes].addr)
  when h - h div d < 64:
    result[1] = result[1] and (not(int64.high shl (h - h div d)))
  bigEndian32(result[2].addr, digest[digest.len-4].addr)
  result[2] = result[2] and (not(int32.high shl (h div d)))

proc PRF(sk: SK; adrs: Address): Nbytes =
  ## Pseudorandom function for key generation.
  var ctx: SHA3
  sha3_init(ctx, SHA3_SHAKE256, n)
  sha3_update(ctx, sk.seed)
  sha3_update(ctx, adrs)
  sha3_final(ctx, result)

include ./sphincsinstantiate.nim