Skip to content

Commit 1a89243

Browse files
zzzstr4d
authored andcommitted
Implement hashCode() and equals() fully
- Add hashCode() and equals() everywhere it was missing, so we can test keys for equality: Curve, EdDSAParameterSpec, EdDSAPrivateKey, and EdDSAPublicKey - Speedup for GroupElement.equals() Signed-off-by: str4d <[email protected]>
1 parent 57816b6 commit 1a89243

File tree

6 files changed

+79
-2
lines changed

6 files changed

+79
-2
lines changed

src/net/i2p/crypto/eddsa/EdDSAPrivateKey.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import java.security.PrivateKey;
44
import java.security.spec.InvalidKeySpecException;
55
import java.security.spec.PKCS8EncodedKeySpec;
6+
import java.util.Arrays;
67

78
import net.i2p.crypto.eddsa.math.GroupElement;
89
import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable;
@@ -80,7 +81,6 @@ public String getFormat() {
8081
* @return 49 bytes for Ed25519, null for other curves
8182
*/
8283
public byte[] getEncoded() {
83-
// TODO no equals() implemented in spec, but it's essentially a singleton
8484
if (!edDsaSpec.equals(EdDSANamedCurveTable.getByName(EdDSANamedCurveTable.CURVE_ED25519_SHA512)))
8585
return null;
8686
int totlen = 17 + seed.length;
@@ -179,4 +179,20 @@ public GroupElement getA() {
179179
public byte[] getAbyte() {
180180
return Abyte;
181181
}
182+
183+
@Override
184+
public int hashCode() {
185+
return Arrays.hashCode(seed);
186+
}
187+
188+
@Override
189+
public boolean equals(Object o) {
190+
if (o == this)
191+
return true;
192+
if (!(o instanceof EdDSAPrivateKey))
193+
return false;
194+
EdDSAPrivateKey pk = (EdDSAPrivateKey) o;
195+
return Arrays.equals(seed, pk.getSeed()) &&
196+
edDsaSpec.equals(pk.getParams());
197+
}
182198
}

src/net/i2p/crypto/eddsa/EdDSAPublicKey.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import java.security.PublicKey;
44
import java.security.spec.InvalidKeySpecException;
55
import java.security.spec.X509EncodedKeySpec;
6+
import java.util.Arrays;
67

78
import net.i2p.crypto.eddsa.math.GroupElement;
89
import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable;
@@ -65,7 +66,6 @@ public String getFormat() {
6566
* @return 47 bytes for Ed25519, null for other curves
6667
*/
6768
public byte[] getEncoded() {
68-
// TODO no equals() implemented in spec, but it's essentially a singleton
6969
if (!edDsaSpec.equals(EdDSANamedCurveTable.getByName(EdDSANamedCurveTable.CURVE_ED25519_SHA512)))
7070
return null;
7171
int totlen = 15 + Abyte.length;
@@ -146,4 +146,20 @@ public GroupElement getNegativeA() {
146146
public byte[] getAbyte() {
147147
return Abyte;
148148
}
149+
150+
@Override
151+
public int hashCode() {
152+
return Arrays.hashCode(Abyte);
153+
}
154+
155+
@Override
156+
public boolean equals(Object o) {
157+
if (o == this)
158+
return true;
159+
if (!(o instanceof EdDSAPublicKey))
160+
return false;
161+
EdDSAPublicKey pk = (EdDSAPublicKey) o;
162+
return Arrays.equals(Abyte, pk.getAbyte()) &&
163+
edDsaSpec.equals(pk.getParams());
164+
}
149165
}

src/net/i2p/crypto/eddsa/math/Curve.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,4 +67,23 @@ public GroupElement createPoint(byte[] P, boolean precompute) {
6767
ge.precompute(true);
6868
return ge;
6969
}
70+
71+
@Override
72+
public int hashCode() {
73+
return f.hashCode() ^
74+
d.hashCode() ^
75+
I.hashCode();
76+
}
77+
78+
@Override
79+
public boolean equals(Object o) {
80+
if (o == this)
81+
return true;
82+
if (!(o instanceof Curve))
83+
return false;
84+
Curve c = (Curve) o;
85+
return f.equals(c.getField()) &&
86+
d.equals(c.getD()) &&
87+
I.equals(c.getI());
88+
}
7089
}

src/net/i2p/crypto/eddsa/math/FieldElement.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
import java.io.Serializable;
44

5+
/**
6+
* Note: concrete subclasses must implement hashCode() and equals()
7+
*/
58
public abstract class FieldElement implements Serializable {
69
private static final long serialVersionUID = 1239527465875676L;
710

@@ -55,4 +58,6 @@ public FieldElement divide(FieldElement val) {
5558
public abstract FieldElement invert();
5659

5760
public abstract FieldElement pow22523();
61+
62+
// Note: concrete subclasses must implement hashCode() and equals()
5863
}

src/net/i2p/crypto/eddsa/math/GroupElement.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -714,6 +714,8 @@ public int hashCode() {
714714

715715
@Override
716716
public boolean equals(Object obj) {
717+
if (obj == this)
718+
return true;
717719
if (!(obj instanceof GroupElement))
718720
return false;
719721
GroupElement ge = (GroupElement) obj;

src/net/i2p/crypto/eddsa/spec/EdDSAParameterSpec.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,4 +57,23 @@ public ScalarOps getScalarOps() {
5757
public GroupElement getB() {
5858
return B;
5959
}
60+
61+
@Override
62+
public int hashCode() {
63+
return hashAlgo.hashCode() ^
64+
curve.hashCode() ^
65+
B.hashCode();
66+
}
67+
68+
@Override
69+
public boolean equals(Object o) {
70+
if (o == this)
71+
return true;
72+
if (!(o instanceof EdDSAParameterSpec))
73+
return false;
74+
EdDSAParameterSpec s = (EdDSAParameterSpec) o;
75+
return hashAlgo.equals(s.getHashAlgorithm()) &&
76+
curve.equals(s.getCurve()) &&
77+
B.equals(s.getB());
78+
}
6079
}

0 commit comments

Comments
 (0)