Skip to content

Commit d61be28

Browse files
committed
EdDSA improvements from bc-csharp
- reject small order public keys - cofactored verification - perf. opts.: Pornin's basis reduction - hold decoded public point in public keys
1 parent 75260e3 commit d61be28

File tree

17 files changed

+2554
-1096
lines changed

17 files changed

+2554
-1096
lines changed

core/src/main/java/org/bouncycastle/crypto/params/Ed25519PrivateKeyParameters.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,7 @@ public Ed25519PublicKeyParameters generatePublicKey()
6464
{
6565
if (null == cachedPublicKey)
6666
{
67-
byte[] publicKey = new byte[Ed25519.PUBLIC_KEY_SIZE];
68-
Ed25519.generatePublicKey(data, 0, publicKey, 0);
69-
cachedPublicKey = new Ed25519PublicKeyParameters(publicKey, 0);
67+
cachedPublicKey = new Ed25519PublicKeyParameters(Ed25519.generatePublicKey(data, 0));
7068
}
7169

7270
return cachedPublicKey;

core/src/main/java/org/bouncycastle/crypto/params/Ed25519PublicKeyParameters.java

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,14 @@
55
import java.io.InputStream;
66

77
import org.bouncycastle.math.ec.rfc8032.Ed25519;
8-
import org.bouncycastle.util.Arrays;
98
import org.bouncycastle.util.io.Streams;
109

1110
public final class Ed25519PublicKeyParameters
1211
extends AsymmetricKeyParameter
1312
{
1413
public static final int KEY_SIZE = Ed25519.PUBLIC_KEY_SIZE;
1514

16-
private final byte[] data = new byte[KEY_SIZE];
15+
private final Ed25519.PublicPoint publicPoint;
1716

1817
public Ed25519PublicKeyParameters(byte[] buf)
1918
{
@@ -24,27 +23,45 @@ public Ed25519PublicKeyParameters(byte[] buf, int off)
2423
{
2524
super(false);
2625

27-
System.arraycopy(buf, off, data, 0, KEY_SIZE);
26+
this.publicPoint = parse(buf, off);
2827
}
2928

3029
public Ed25519PublicKeyParameters(InputStream input) throws IOException
3130
{
3231
super(false);
3332

33+
byte[] data = new byte[KEY_SIZE];
34+
3435
if (KEY_SIZE != Streams.readFully(input, data))
3536
{
3637
throw new EOFException("EOF encountered in middle of Ed25519 public key");
3738
}
39+
40+
this.publicPoint = parse(data, 0);
41+
}
42+
43+
public Ed25519PublicKeyParameters(Ed25519.PublicPoint publicPoint)
44+
{
45+
super(false);
46+
47+
if (publicPoint == null)
48+
{
49+
throw new NullPointerException("'publicPoint' cannot be null");
50+
}
51+
52+
this.publicPoint = publicPoint;
3853
}
3954

4055
public void encode(byte[] buf, int off)
4156
{
42-
System.arraycopy(data, 0, buf, off, KEY_SIZE);
57+
Ed25519.encodePublicPoint(publicPoint, buf, off);
4358
}
4459

4560
public byte[] getEncoded()
4661
{
47-
return Arrays.clone(data);
62+
byte[] data = new byte[KEY_SIZE];
63+
encode(data, 0);
64+
return data;
4865
}
4966

5067
public boolean verify(int algorithm, byte[] ctx, byte[] msg, int msgOff, int msgLen, byte[] sig, int sigOff)
@@ -58,7 +75,7 @@ public boolean verify(int algorithm, byte[] ctx, byte[] msg, int msgOff, int msg
5875
throw new IllegalArgumentException("ctx");
5976
}
6077

61-
return Ed25519.verify(sig, sigOff, data, 0, msg, msgOff, msgLen);
78+
return Ed25519.verify(sig, sigOff, publicPoint, msg, msgOff, msgLen);
6279
}
6380
case Ed25519.Algorithm.Ed25519ctx:
6481
{
@@ -71,7 +88,7 @@ public boolean verify(int algorithm, byte[] ctx, byte[] msg, int msgOff, int msg
7188
throw new IllegalArgumentException("ctx");
7289
}
7390

74-
return Ed25519.verify(sig, sigOff, data, 0, ctx, msg, msgOff, msgLen);
91+
return Ed25519.verify(sig, sigOff, publicPoint, ctx, msg, msgOff, msgLen);
7592
}
7693
case Ed25519.Algorithm.Ed25519ph:
7794
{
@@ -88,7 +105,7 @@ public boolean verify(int algorithm, byte[] ctx, byte[] msg, int msgOff, int msg
88105
throw new IllegalArgumentException("msgLen");
89106
}
90107

91-
return Ed25519.verifyPrehash(sig, sigOff, data, 0, ctx, msg, msgOff);
108+
return Ed25519.verifyPrehash(sig, sigOff, publicPoint, ctx, msg, msgOff);
92109
}
93110
default:
94111
{
@@ -97,6 +114,16 @@ public boolean verify(int algorithm, byte[] ctx, byte[] msg, int msgOff, int msg
97114
}
98115
}
99116

117+
private static Ed25519.PublicPoint parse(byte[] buf, int off)
118+
{
119+
Ed25519.PublicPoint publicPoint = Ed25519.validatePublicKeyPartialExport(buf, off);
120+
if (publicPoint == null)
121+
{
122+
throw new IllegalArgumentException("invalid public key");
123+
}
124+
return publicPoint;
125+
}
126+
100127
private static byte[] validate(byte[] buf)
101128
{
102129
if (buf.length != KEY_SIZE)

core/src/main/java/org/bouncycastle/crypto/params/Ed448PrivateKeyParameters.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,7 @@ public Ed448PublicKeyParameters generatePublicKey()
6464
{
6565
if (null == cachedPublicKey)
6666
{
67-
byte[] publicKey = new byte[Ed448.PUBLIC_KEY_SIZE];
68-
Ed448.generatePublicKey(data, 0, publicKey, 0);
69-
cachedPublicKey = new Ed448PublicKeyParameters(publicKey, 0);
67+
cachedPublicKey = new Ed448PublicKeyParameters(Ed448.generatePublicKey(data, 0));
7068
}
7169

7270
return cachedPublicKey;

core/src/main/java/org/bouncycastle/crypto/params/Ed448PublicKeyParameters.java

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,14 @@
55
import java.io.InputStream;
66

77
import org.bouncycastle.math.ec.rfc8032.Ed448;
8-
import org.bouncycastle.util.Arrays;
98
import org.bouncycastle.util.io.Streams;
109

1110
public final class Ed448PublicKeyParameters
1211
extends AsymmetricKeyParameter
1312
{
1413
public static final int KEY_SIZE = Ed448.PUBLIC_KEY_SIZE;
1514

16-
private final byte[] data = new byte[KEY_SIZE];
15+
private final Ed448.PublicPoint publicPoint;
1716

1817
public Ed448PublicKeyParameters(byte[] buf)
1918
{
@@ -24,27 +23,45 @@ public Ed448PublicKeyParameters(byte[] buf, int off)
2423
{
2524
super(false);
2625

27-
System.arraycopy(buf, off, data, 0, KEY_SIZE);
26+
this.publicPoint = parse(buf, off);
2827
}
2928

3029
public Ed448PublicKeyParameters(InputStream input) throws IOException
3130
{
3231
super(false);
3332

33+
byte[] data = new byte[KEY_SIZE];
34+
3435
if (KEY_SIZE != Streams.readFully(input, data))
3536
{
3637
throw new EOFException("EOF encountered in middle of Ed448 public key");
3738
}
39+
40+
this.publicPoint = parse(data, 0);
41+
}
42+
43+
public Ed448PublicKeyParameters(Ed448.PublicPoint publicPoint)
44+
{
45+
super(false);
46+
47+
if (publicPoint == null)
48+
{
49+
throw new NullPointerException("'publicPoint' cannot be null");
50+
}
51+
52+
this.publicPoint = publicPoint;
3853
}
3954

4055
public void encode(byte[] buf, int off)
4156
{
42-
System.arraycopy(data, 0, buf, off, KEY_SIZE);
57+
Ed448.encodePublicPoint(publicPoint, buf, off);
4358
}
4459

4560
public byte[] getEncoded()
4661
{
47-
return Arrays.clone(data);
62+
byte[] data = new byte[KEY_SIZE];
63+
encode(data, 0);
64+
return data;
4865
}
4966

5067
public boolean verify(int algorithm, byte[] ctx, byte[] msg, int msgOff, int msgLen, byte[] sig, int sigOff)
@@ -62,7 +79,7 @@ public boolean verify(int algorithm, byte[] ctx, byte[] msg, int msgOff, int msg
6279
throw new IllegalArgumentException("ctx");
6380
}
6481

65-
return Ed448.verify(sig, sigOff, data, 0, ctx, msg, msgOff, msgLen);
82+
return Ed448.verify(sig, sigOff, publicPoint, ctx, msg, msgOff, msgLen);
6683
}
6784
case Ed448.Algorithm.Ed448ph:
6885
{
@@ -79,7 +96,7 @@ public boolean verify(int algorithm, byte[] ctx, byte[] msg, int msgOff, int msg
7996
throw new IllegalArgumentException("msgLen");
8097
}
8198

82-
return Ed448.verifyPrehash(sig, sigOff, data, 0, ctx, msg, msgOff);
99+
return Ed448.verifyPrehash(sig, sigOff, publicPoint, ctx, msg, msgOff);
83100
}
84101
default:
85102
{
@@ -88,6 +105,16 @@ public boolean verify(int algorithm, byte[] ctx, byte[] msg, int msgOff, int msg
88105
}
89106
}
90107

108+
private static Ed448.PublicPoint parse(byte[] buf, int off)
109+
{
110+
Ed448.PublicPoint publicPoint = Ed448.validatePublicKeyPartialExport(buf, off);
111+
if (publicPoint == null)
112+
{
113+
throw new IllegalArgumentException("invalid public key");
114+
}
115+
return publicPoint;
116+
}
117+
91118
private static byte[] validate(byte[] buf)
92119
{
93120
if (buf.length != KEY_SIZE)

core/src/main/java/org/bouncycastle/math/ec/rfc7748/X25519Field.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,13 +152,27 @@ public static void decode(int[] x, int xOff, int[] z)
152152
z[9] &= M24;
153153
}
154154

155+
public static void decode(byte[] x, int[] z)
156+
{
157+
decode128(x, 0, z, 0);
158+
decode128(x, 16, z, 5);
159+
z[9] &= M24;
160+
}
161+
155162
public static void decode(byte[] x, int xOff, int[] z)
156163
{
157164
decode128(x, xOff, z, 0);
158165
decode128(x, xOff + 16, z, 5);
159166
z[9] &= M24;
160167
}
161168

169+
public static void decode(byte[] x, int xOff, int[] z, int zOff)
170+
{
171+
decode128(x, xOff, z, zOff);
172+
decode128(x, xOff + 16, z, zOff + 5);
173+
z[zOff + 9] &= M24;
174+
}
175+
162176
private static void decode128(int[] is, int off, int[] z, int zOff)
163177
{
164178
int t0 = is[off + 0], t1 = is[off + 1], t2 = is[off + 2], t3 = is[off + 3];
@@ -199,12 +213,24 @@ public static void encode(int[] x, int[] z, int zOff)
199213
encode128(x, 5, z, zOff + 4);
200214
}
201215

216+
public static void encode(int[] x, byte[] z)
217+
{
218+
encode128(x, 0, z, 0);
219+
encode128(x, 5, z, 16);
220+
}
221+
202222
public static void encode(int[] x, byte[] z, int zOff)
203223
{
204224
encode128(x, 0, z, zOff);
205225
encode128(x, 5, z, zOff + 16);
206226
}
207227

228+
public static void encode(int[] x, int xOff, byte[] z, int zOff)
229+
{
230+
encode128(x, xOff, z, zOff);
231+
encode128(x, xOff + 5, z, zOff + 16);
232+
}
233+
208234
private static void encode128(int[] x, int xOff, int[] is, int off)
209235
{
210236
int x0 = x[xOff + 0], x1 = x[xOff + 1], x2 = x[xOff + 2], x3 = x[xOff + 3], x4 = x[xOff + 4];

core/src/main/java/org/bouncycastle/math/ec/rfc7748/X448Field.java

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,18 @@ public static void decode(int[] x, int xOff, int[] z)
156156
decode224(x, xOff + 7, z, 8);
157157
}
158158

159+
public static void decode(byte[] x, int[] z)
160+
{
161+
decode56(x, 0, z, 0);
162+
decode56(x, 7, z, 2);
163+
decode56(x, 14, z, 4);
164+
decode56(x, 21, z, 6);
165+
decode56(x, 28, z, 8);
166+
decode56(x, 35, z, 10);
167+
decode56(x, 42, z, 12);
168+
decode56(x, 49, z, 14);
169+
}
170+
159171
public static void decode(byte[] x, int xOff, int[] z)
160172
{
161173
decode56(x, xOff, z, 0);
@@ -168,6 +180,18 @@ public static void decode(byte[] x, int xOff, int[] z)
168180
decode56(x, xOff + 49, z, 14);
169181
}
170182

183+
public static void decode(byte[] x, int xOff, int[] z, int zOff)
184+
{
185+
decode56(x, xOff, z, zOff);
186+
decode56(x, xOff + 7, z, zOff + 2);
187+
decode56(x, xOff + 14, z, zOff + 4);
188+
decode56(x, xOff + 21, z, zOff + 6);
189+
decode56(x, xOff + 28, z, zOff + 8);
190+
decode56(x, xOff + 35, z, zOff + 10);
191+
decode56(x, xOff + 42, z, zOff + 12);
192+
decode56(x, xOff + 49, z, zOff + 14);
193+
}
194+
171195
private static void decode224(int[] x, int xOff, int[] z, int zOff)
172196
{
173197
int x0 = x[xOff + 0], x1 = x[xOff + 1], x2 = x[xOff + 2], x3 = x[xOff + 3];
@@ -214,7 +238,19 @@ public static void encode(int[] x, int[] z, int zOff)
214238
encode224(x, 8, z, zOff + 7);
215239
}
216240

217-
public static void encode(int[] x, byte[] z , int zOff)
241+
public static void encode(int[] x, byte[] z)
242+
{
243+
encode56(x, 0, z, 0);
244+
encode56(x, 2, z, 7);
245+
encode56(x, 4, z, 14);
246+
encode56(x, 6, z, 21);
247+
encode56(x, 8, z, 28);
248+
encode56(x, 10, z, 35);
249+
encode56(x, 12, z, 42);
250+
encode56(x, 14, z, 49);
251+
}
252+
253+
public static void encode(int[] x, byte[] z, int zOff)
218254
{
219255
encode56(x, 0, z, zOff);
220256
encode56(x, 2, z, zOff + 7);
@@ -226,6 +262,18 @@ public static void encode(int[] x, byte[] z , int zOff)
226262
encode56(x, 14, z, zOff + 49);
227263
}
228264

265+
public static void encode(int[] x, int xOff, byte[] z, int zOff)
266+
{
267+
encode56(x, xOff, z, zOff);
268+
encode56(x, xOff + 2, z, zOff + 7);
269+
encode56(x, xOff + 4, z, zOff + 14);
270+
encode56(x, xOff + 6, z, zOff + 21);
271+
encode56(x, xOff + 8, z, zOff + 28);
272+
encode56(x, xOff + 10, z, zOff + 35);
273+
encode56(x, xOff + 12, z, zOff + 42);
274+
encode56(x, xOff + 14, z, zOff + 49);
275+
}
276+
229277
private static void encode224(int[] x, int xOff, int[] is, int off)
230278
{
231279
int x0 = x[xOff + 0], x1 = x[xOff + 1], x2 = x[xOff + 2], x3 = x[xOff + 3];

0 commit comments

Comments
 (0)