Skip to content

Commit

Permalink
EdDSA improvements from bc-csharp
Browse files Browse the repository at this point in the history
- reject small order public keys
- cofactored verification
- perf. opts.: Pornin's basis reduction
- hold decoded public point in public keys
  • Loading branch information
peterdettman committed Nov 27, 2022
1 parent b2d3c12 commit 1b9fd9b
Show file tree
Hide file tree
Showing 17 changed files with 2,554 additions and 1,096 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,7 @@ public Ed25519PublicKeyParameters generatePublicKey()
{
if (null == cachedPublicKey)
{
byte[] publicKey = new byte[Ed25519.PUBLIC_KEY_SIZE];
Ed25519.generatePublicKey(data, 0, publicKey, 0);
cachedPublicKey = new Ed25519PublicKeyParameters(publicKey, 0);
cachedPublicKey = new Ed25519PublicKeyParameters(Ed25519.generatePublicKey(data, 0));
}

return cachedPublicKey;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,14 @@
import java.io.InputStream;

import org.bouncycastle.math.ec.rfc8032.Ed25519;
import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.io.Streams;

public final class Ed25519PublicKeyParameters
extends AsymmetricKeyParameter
{
public static final int KEY_SIZE = Ed25519.PUBLIC_KEY_SIZE;

private final byte[] data = new byte[KEY_SIZE];
private final Ed25519.PublicPoint publicPoint;

public Ed25519PublicKeyParameters(byte[] buf)
{
Expand All @@ -24,27 +23,45 @@ public Ed25519PublicKeyParameters(byte[] buf, int off)
{
super(false);

System.arraycopy(buf, off, data, 0, KEY_SIZE);
this.publicPoint = parse(buf, off);
}

public Ed25519PublicKeyParameters(InputStream input) throws IOException
{
super(false);

byte[] data = new byte[KEY_SIZE];

if (KEY_SIZE != Streams.readFully(input, data))
{
throw new EOFException("EOF encountered in middle of Ed25519 public key");
}

this.publicPoint = parse(data, 0);
}

public Ed25519PublicKeyParameters(Ed25519.PublicPoint publicPoint)
{
super(false);

if (publicPoint == null)
{
throw new NullPointerException("'publicPoint' cannot be null");
}

this.publicPoint = publicPoint;
}

public void encode(byte[] buf, int off)
{
System.arraycopy(data, 0, buf, off, KEY_SIZE);
Ed25519.encodePublicPoint(publicPoint, buf, off);
}

public byte[] getEncoded()
{
return Arrays.clone(data);
byte[] data = new byte[KEY_SIZE];
encode(data, 0);
return data;
}

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

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

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

return Ed25519.verifyPrehash(sig, sigOff, data, 0, ctx, msg, msgOff);
return Ed25519.verifyPrehash(sig, sigOff, publicPoint, ctx, msg, msgOff);
}
default:
{
Expand All @@ -97,6 +114,16 @@ public boolean verify(int algorithm, byte[] ctx, byte[] msg, int msgOff, int msg
}
}

private static Ed25519.PublicPoint parse(byte[] buf, int off)
{
Ed25519.PublicPoint publicPoint = Ed25519.validatePublicKeyPartialExport(buf, off);
if (publicPoint == null)
{
throw new IllegalArgumentException("invalid public key");
}
return publicPoint;
}

private static byte[] validate(byte[] buf)
{
if (buf.length != KEY_SIZE)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,7 @@ public Ed448PublicKeyParameters generatePublicKey()
{
if (null == cachedPublicKey)
{
byte[] publicKey = new byte[Ed448.PUBLIC_KEY_SIZE];
Ed448.generatePublicKey(data, 0, publicKey, 0);
cachedPublicKey = new Ed448PublicKeyParameters(publicKey, 0);
cachedPublicKey = new Ed448PublicKeyParameters(Ed448.generatePublicKey(data, 0));
}

return cachedPublicKey;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,14 @@
import java.io.InputStream;

import org.bouncycastle.math.ec.rfc8032.Ed448;
import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.io.Streams;

public final class Ed448PublicKeyParameters
extends AsymmetricKeyParameter
{
public static final int KEY_SIZE = Ed448.PUBLIC_KEY_SIZE;

private final byte[] data = new byte[KEY_SIZE];
private final Ed448.PublicPoint publicPoint;

public Ed448PublicKeyParameters(byte[] buf)
{
Expand All @@ -24,27 +23,45 @@ public Ed448PublicKeyParameters(byte[] buf, int off)
{
super(false);

System.arraycopy(buf, off, data, 0, KEY_SIZE);
this.publicPoint = parse(buf, off);
}

public Ed448PublicKeyParameters(InputStream input) throws IOException
{
super(false);

byte[] data = new byte[KEY_SIZE];

if (KEY_SIZE != Streams.readFully(input, data))
{
throw new EOFException("EOF encountered in middle of Ed448 public key");
}

this.publicPoint = parse(data, 0);
}

public Ed448PublicKeyParameters(Ed448.PublicPoint publicPoint)
{
super(false);

if (publicPoint == null)
{
throw new NullPointerException("'publicPoint' cannot be null");
}

this.publicPoint = publicPoint;
}

public void encode(byte[] buf, int off)
{
System.arraycopy(data, 0, buf, off, KEY_SIZE);
Ed448.encodePublicPoint(publicPoint, buf, off);
}

public byte[] getEncoded()
{
return Arrays.clone(data);
byte[] data = new byte[KEY_SIZE];
encode(data, 0);
return data;
}

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

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

return Ed448.verifyPrehash(sig, sigOff, data, 0, ctx, msg, msgOff);
return Ed448.verifyPrehash(sig, sigOff, publicPoint, ctx, msg, msgOff);
}
default:
{
Expand All @@ -88,6 +105,16 @@ public boolean verify(int algorithm, byte[] ctx, byte[] msg, int msgOff, int msg
}
}

private static Ed448.PublicPoint parse(byte[] buf, int off)
{
Ed448.PublicPoint publicPoint = Ed448.validatePublicKeyPartialExport(buf, off);
if (publicPoint == null)
{
throw new IllegalArgumentException("invalid public key");
}
return publicPoint;
}

private static byte[] validate(byte[] buf)
{
if (buf.length != KEY_SIZE)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,13 +152,27 @@ public static void decode(int[] x, int xOff, int[] z)
z[9] &= M24;
}

public static void decode(byte[] x, int[] z)
{
decode128(x, 0, z, 0);
decode128(x, 16, z, 5);
z[9] &= M24;
}

public static void decode(byte[] x, int xOff, int[] z)
{
decode128(x, xOff, z, 0);
decode128(x, xOff + 16, z, 5);
z[9] &= M24;
}

public static void decode(byte[] x, int xOff, int[] z, int zOff)
{
decode128(x, xOff, z, zOff);
decode128(x, xOff + 16, z, zOff + 5);
z[zOff + 9] &= M24;
}

private static void decode128(int[] is, int off, int[] z, int zOff)
{
int t0 = is[off + 0], t1 = is[off + 1], t2 = is[off + 2], t3 = is[off + 3];
Expand Down Expand Up @@ -199,12 +213,24 @@ public static void encode(int[] x, int[] z, int zOff)
encode128(x, 5, z, zOff + 4);
}

public static void encode(int[] x, byte[] z)
{
encode128(x, 0, z, 0);
encode128(x, 5, z, 16);
}

public static void encode(int[] x, byte[] z, int zOff)
{
encode128(x, 0, z, zOff);
encode128(x, 5, z, zOff + 16);
}

public static void encode(int[] x, int xOff, byte[] z, int zOff)
{
encode128(x, xOff, z, zOff);
encode128(x, xOff + 5, z, zOff + 16);
}

private static void encode128(int[] x, int xOff, int[] is, int off)
{
int x0 = x[xOff + 0], x1 = x[xOff + 1], x2 = x[xOff + 2], x3 = x[xOff + 3], x4 = x[xOff + 4];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,18 @@ public static void decode(int[] x, int xOff, int[] z)
decode224(x, xOff + 7, z, 8);
}

public static void decode(byte[] x, int[] z)
{
decode56(x, 0, z, 0);
decode56(x, 7, z, 2);
decode56(x, 14, z, 4);
decode56(x, 21, z, 6);
decode56(x, 28, z, 8);
decode56(x, 35, z, 10);
decode56(x, 42, z, 12);
decode56(x, 49, z, 14);
}

public static void decode(byte[] x, int xOff, int[] z)
{
decode56(x, xOff, z, 0);
Expand All @@ -168,6 +180,18 @@ public static void decode(byte[] x, int xOff, int[] z)
decode56(x, xOff + 49, z, 14);
}

public static void decode(byte[] x, int xOff, int[] z, int zOff)
{
decode56(x, xOff, z, zOff);
decode56(x, xOff + 7, z, zOff + 2);
decode56(x, xOff + 14, z, zOff + 4);
decode56(x, xOff + 21, z, zOff + 6);
decode56(x, xOff + 28, z, zOff + 8);
decode56(x, xOff + 35, z, zOff + 10);
decode56(x, xOff + 42, z, zOff + 12);
decode56(x, xOff + 49, z, zOff + 14);
}

private static void decode224(int[] x, int xOff, int[] z, int zOff)
{
int x0 = x[xOff + 0], x1 = x[xOff + 1], x2 = x[xOff + 2], x3 = x[xOff + 3];
Expand Down Expand Up @@ -214,7 +238,19 @@ public static void encode(int[] x, int[] z, int zOff)
encode224(x, 8, z, zOff + 7);
}

public static void encode(int[] x, byte[] z , int zOff)
public static void encode(int[] x, byte[] z)
{
encode56(x, 0, z, 0);
encode56(x, 2, z, 7);
encode56(x, 4, z, 14);
encode56(x, 6, z, 21);
encode56(x, 8, z, 28);
encode56(x, 10, z, 35);
encode56(x, 12, z, 42);
encode56(x, 14, z, 49);
}

public static void encode(int[] x, byte[] z, int zOff)
{
encode56(x, 0, z, zOff);
encode56(x, 2, z, zOff + 7);
Expand All @@ -226,6 +262,18 @@ public static void encode(int[] x, byte[] z , int zOff)
encode56(x, 14, z, zOff + 49);
}

public static void encode(int[] x, int xOff, byte[] z, int zOff)
{
encode56(x, xOff, z, zOff);
encode56(x, xOff + 2, z, zOff + 7);
encode56(x, xOff + 4, z, zOff + 14);
encode56(x, xOff + 6, z, zOff + 21);
encode56(x, xOff + 8, z, zOff + 28);
encode56(x, xOff + 10, z, zOff + 35);
encode56(x, xOff + 12, z, zOff + 42);
encode56(x, xOff + 14, z, zOff + 49);
}

private static void encode224(int[] x, int xOff, int[] is, int off)
{
int x0 = x[xOff + 0], x1 = x[xOff + 1], x2 = x[xOff + 2], x3 = x[xOff + 3];
Expand Down
Loading

0 comments on commit 1b9fd9b

Please sign in to comment.