Skip to content

Commit 5bec993

Browse files
author
gefeili
committed
Refactor for Ascon Hash algorithms
1 parent fce766c commit 5bec993

File tree

7 files changed

+188
-598
lines changed

7 files changed

+188
-598
lines changed

core/src/main/java/org/bouncycastle/crypto/digests/AsconCxof128.java

Lines changed: 5 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
import org.bouncycastle.crypto.DataLengthException;
66
import org.bouncycastle.crypto.OutputLengthException;
77
import org.bouncycastle.crypto.Xof;
8-
import org.bouncycastle.util.Pack;
98

109
/**
1110
* ASCON v1.2 XOF, https://ascon.iaik.tugraz.at/ .
@@ -15,83 +14,23 @@
1514
* ASCON v1.2 XOF with reference to C Reference Impl from: https://github.com/ascon/ascon-c .
1615
*/
1716
public class AsconCxof128
17+
extends AsconDefaultDigest
1818
implements Xof
1919
{
2020
public AsconCxof128()
2121
{
2222
reset();
2323
}
2424

25-
private final String algorithmName = "Ascon-XOF-128";
26-
private final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
27-
2825
private final ByteArrayOutputStream customizedString = new ByteArrayOutputStream();
29-
private long x0;
30-
private long x1;
31-
private long x2;
32-
private long x3;
33-
private long x4;
34-
private final int CRYPTO_BYTES = 32;
35-
private final int ASCON_PB_ROUNDS = 12;
36-
private final int ASCON_HASH_RATE = 8;
37-
38-
private long ROR(long x, int n)
39-
{
40-
return x >>> n | x << (64 - n);
41-
}
42-
43-
private void ROUND(long C)
44-
{
45-
long t0 = x0 ^ x1 ^ x2 ^ x3 ^ C ^ (x1 & (x0 ^ x2 ^ x4 ^ C));
46-
long t1 = x0 ^ x2 ^ x3 ^ x4 ^ C ^ ((x1 ^ x2 ^ C) & (x1 ^ x3));
47-
long t2 = x1 ^ x2 ^ x4 ^ C ^ (x3 & x4);
48-
long t3 = x0 ^ x1 ^ x2 ^ C ^ ((~x0) & (x3 ^ x4));
49-
long t4 = x1 ^ x3 ^ x4 ^ ((x0 ^ x4) & x1);
50-
x0 = t0 ^ ROR(t0, 19) ^ ROR(t0, 28);
51-
x1 = t1 ^ ROR(t1, 39) ^ ROR(t1, 61);
52-
x2 = ~(t2 ^ ROR(t2, 1) ^ ROR(t2, 6));
53-
x3 = t3 ^ ROR(t3, 10) ^ ROR(t3, 17);
54-
x4 = t4 ^ ROR(t4, 7) ^ ROR(t4, 41);
55-
}
56-
57-
private void P(int nr)
58-
{
59-
if (nr == 12)
60-
{
61-
ROUND(0xf0L);
62-
ROUND(0xe1L);
63-
ROUND(0xd2L);
64-
ROUND(0xc3L);
65-
}
66-
if (nr >= 8)
67-
{
68-
ROUND(0xb4L);
69-
ROUND(0xa5L);
70-
}
71-
ROUND(0x96L);
72-
ROUND(0x87L);
73-
ROUND(0x78L);
74-
ROUND(0x69L);
75-
ROUND(0x5aL);
76-
ROUND(0x4bL);
77-
}
7826

79-
private long PAD(int i)
80-
{
81-
return 0x01L << (i << 3);
82-
}
8327

8428
@Override
8529
public String getAlgorithmName()
8630
{
87-
return algorithmName;
31+
return "Ascon-XOF-128";
8832
}
8933

90-
@Override
91-
public int getDigestSize()
92-
{
93-
return CRYPTO_BYTES;
94-
}
9534

9635
public void updateCustomizedString(byte in)
9736
{
@@ -107,22 +46,6 @@ public void updateCustomizedString(byte[] input, int inOff, int len)
10746
customizedString.write(input, inOff, len);
10847
}
10948

110-
@Override
111-
public void update(byte in)
112-
{
113-
buffer.write(in);
114-
}
115-
116-
@Override
117-
public void update(byte[] input, int inOff, int len)
118-
{
119-
if ((inOff + len) > input.length)
120-
{
121-
throw new DataLengthException("input buffer too short");
122-
}
123-
buffer.write(input, inOff, len);
124-
}
125-
12649
@Override
12750
public int doOutput(byte[] output, int outOff, int outLen)
12851
{
@@ -138,35 +61,8 @@ public int doOutput(byte[] output, int outOff, int outLen)
13861
absorb(customizedString.toByteArray(), customizedStringLen);
13962
absorb(buffer.toByteArray(), buffer.size());
14063
/* squeeze full output blocks */
141-
int len = CRYPTO_BYTES;
142-
while (len > ASCON_HASH_RATE)
143-
{
144-
Pack.longToLittleEndian(x0, output, outOff, 8);
145-
P(ASCON_PB_ROUNDS);
146-
outOff += ASCON_HASH_RATE;
147-
len -= ASCON_HASH_RATE;
148-
}
149-
/* squeeze final output block */
150-
Pack.longToLittleEndian(x0, output, outOff, len);
151-
reset();
152-
return CRYPTO_BYTES;
153-
}
154-
155-
private void absorb(byte[] input, int len)
156-
{
157-
int inOff = 0;
158-
/* absorb full plaintext blocks */
159-
while (len >= ASCON_HASH_RATE)
160-
{
161-
x0 ^= Pack.littleEndianToLong(input, inOff, 8);
162-
P(ASCON_PB_ROUNDS);
163-
inOff += ASCON_HASH_RATE;
164-
len -= ASCON_HASH_RATE;
165-
}
166-
/* absorb final plaintext block */
167-
x0 ^= Pack.littleEndianToLong(input, inOff, len);
168-
x0 ^= PAD(len);
169-
P(12);
64+
squeeze(output, outOff, outLen);
65+
return outLen;
17066
}
17167

17268
@Override
@@ -181,15 +77,10 @@ public int doFinal(byte[] output, int outOff, int outLen)
18177
return doOutput(output, outOff, outLen);
18278
}
18379

184-
@Override
185-
public int getByteLength()
186-
{
187-
return 8;
188-
}
189-
19080
@Override
19181
public void reset()
19282
{
83+
customizedString.reset();
19384
buffer.reset();
19485
/* initialize */
19586
x0 = 7445901275803737603L;
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
package org.bouncycastle.crypto.digests;
2+
3+
import java.io.ByteArrayOutputStream;
4+
5+
import org.bouncycastle.crypto.DataLengthException;
6+
import org.bouncycastle.crypto.ExtendedDigest;
7+
import org.bouncycastle.crypto.OutputLengthException;
8+
import org.bouncycastle.util.Pack;
9+
10+
abstract class AsconDefaultDigest
11+
implements ExtendedDigest
12+
{
13+
protected long x0;
14+
protected long x1;
15+
protected long x2;
16+
protected long x3;
17+
protected long x4;
18+
protected final int CRYPTO_BYTES = 32;
19+
protected final int ASCON_HASH_RATE = 8;
20+
protected int ASCON_PB_ROUNDS = 12;
21+
22+
protected final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
23+
24+
protected long ROR(long x, int n)
25+
{
26+
return x >>> n | x << (64 - n);
27+
}
28+
29+
protected void ROUND(long C)
30+
{
31+
long t0 = x0 ^ x1 ^ x2 ^ x3 ^ C ^ (x1 & (x0 ^ x2 ^ x4 ^ C));
32+
long t1 = x0 ^ x2 ^ x3 ^ x4 ^ C ^ ((x1 ^ x2 ^ C) & (x1 ^ x3));
33+
long t2 = x1 ^ x2 ^ x4 ^ C ^ (x3 & x4);
34+
long t3 = x0 ^ x1 ^ x2 ^ C ^ ((~x0) & (x3 ^ x4));
35+
long t4 = x1 ^ x3 ^ x4 ^ ((x0 ^ x4) & x1);
36+
x0 = t0 ^ ROR(t0, 19) ^ ROR(t0, 28);
37+
x1 = t1 ^ ROR(t1, 39) ^ ROR(t1, 61);
38+
x2 = ~(t2 ^ ROR(t2, 1) ^ ROR(t2, 6));
39+
x3 = t3 ^ ROR(t3, 10) ^ ROR(t3, 17);
40+
x4 = t4 ^ ROR(t4, 7) ^ ROR(t4, 41);
41+
}
42+
43+
protected void P(int nr)
44+
{
45+
if (nr == 12)
46+
{
47+
ROUND(0xf0L);
48+
ROUND(0xe1L);
49+
ROUND(0xd2L);
50+
ROUND(0xc3L);
51+
}
52+
if (nr >= 8)
53+
{
54+
ROUND(0xb4L);
55+
ROUND(0xa5L);
56+
}
57+
ROUND(0x96L);
58+
ROUND(0x87L);
59+
ROUND(0x78L);
60+
ROUND(0x69L);
61+
ROUND(0x5aL);
62+
ROUND(0x4bL);
63+
}
64+
65+
protected long PAD(int i)
66+
{
67+
return 0x01L << (i << 3);
68+
}
69+
70+
protected long LOADBYTES(final byte[] bytes, int inOff, int n)
71+
{
72+
return Pack.littleEndianToLong(bytes, inOff, n);
73+
}
74+
75+
protected void STOREBYTES(long w, byte[] bytes, int inOff, int n)
76+
{
77+
Pack.longToLittleEndian(w, bytes, inOff, n);
78+
}
79+
80+
@Override
81+
public int getDigestSize()
82+
{
83+
return CRYPTO_BYTES;
84+
}
85+
86+
@Override
87+
public int getByteLength()
88+
{
89+
return 8;
90+
}
91+
92+
@Override
93+
public void update(byte in)
94+
{
95+
buffer.write(in);
96+
}
97+
98+
@Override
99+
public void update(byte[] input, int inOff, int len)
100+
{
101+
if ((inOff + len) > input.length)
102+
{
103+
throw new DataLengthException("input buffer too short");
104+
}
105+
buffer.write(input, inOff, len);
106+
}
107+
108+
protected void absorb(byte[] input, int len)
109+
{
110+
int inOff = 0;
111+
/* absorb full plaintext blocks */
112+
while (len >= ASCON_HASH_RATE)
113+
{
114+
x0 ^= LOADBYTES(input, inOff, 8);
115+
P(ASCON_PB_ROUNDS);
116+
inOff += ASCON_HASH_RATE;
117+
len -= ASCON_HASH_RATE;
118+
}
119+
/* absorb final plaintext block */
120+
x0 ^= LOADBYTES(input, inOff, len);
121+
x0 ^= PAD(len);
122+
P(12);
123+
}
124+
125+
protected void squeeze(byte[] output, int outOff, int len)
126+
{
127+
/* squeeze full output blocks */
128+
while (len > ASCON_HASH_RATE)
129+
{
130+
STOREBYTES(x0, output, outOff, 8);
131+
P(ASCON_PB_ROUNDS);
132+
outOff += ASCON_HASH_RATE;
133+
len -= ASCON_HASH_RATE;
134+
}
135+
/* squeeze final output block */
136+
STOREBYTES(x0, output, outOff, len);
137+
reset();
138+
}
139+
140+
protected int hash(byte[] output, int outOff, int outLen)
141+
{
142+
if (CRYPTO_BYTES + outOff > output.length)
143+
{
144+
throw new OutputLengthException("output buffer is too short");
145+
}
146+
absorb(buffer.toByteArray(), buffer.size());
147+
/* squeeze full output blocks */
148+
squeeze(output, outOff, outLen);
149+
return outLen;
150+
}
151+
}

0 commit comments

Comments
 (0)