7196805: DH Key interoperability testing between SunJCE and JsafeJCE not successful
Summary: Check equality based on component values instead of encoding which may vary due to optional components
Reviewed-by: weijun
--- a/jdk/src/share/classes/com/sun/crypto/provider/DHKeyFactory.java Fri Jul 05 13:53:37 2013 -0700
+++ b/jdk/src/share/classes/com/sun/crypto/provider/DHKeyFactory.java Fri Jul 05 13:56:12 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -83,7 +83,7 @@
}
} catch (InvalidKeyException e) {
throw new InvalidKeySpecException
- ("Inappropriate key specification");
+ ("Inappropriate key specification", e);
}
}
@@ -118,7 +118,7 @@
}
} catch (InvalidKeyException e) {
throw new InvalidKeySpecException
- ("Inappropriate key specification");
+ ("Inappropriate key specification", e);
}
}
@@ -227,7 +227,7 @@
}
} catch (InvalidKeySpecException e) {
- throw new InvalidKeyException("Cannot translate key");
+ throw new InvalidKeyException("Cannot translate key", e);
}
}
}
--- a/jdk/src/share/classes/com/sun/crypto/provider/DHKeyPairGenerator.java Fri Jul 05 13:53:37 2013 -0700
+++ b/jdk/src/share/classes/com/sun/crypto/provider/DHKeyPairGenerator.java Fri Jul 05 13:56:12 2013 -0700
@@ -167,15 +167,16 @@
BigInteger pMinus2 = p.subtract(BigInteger.valueOf(2));
//
- // Handbook of Applied Cryptography: Menezes, et.al.
- // Repeat if the following does not hold:
- // 1 <= x <= p-2
+ // PKCS#3 section 7.1 "Private-value generation"
+ // Repeat if either of the followings does not hold:
+ // 0 < x < p-1
+ // 2^(lSize-1) <= x < 2^(lSize)
//
do {
// generate random x up to 2^lSize bits long
x = new BigInteger(lSize, random);
} while ((x.compareTo(BigInteger.ONE) < 0) ||
- ((x.compareTo(pMinus2) > 0)));
+ ((x.compareTo(pMinus2) > 0)) || (x.bitLength() != lSize));
// calculate public value y
BigInteger y = g.modPow(x, p);
--- a/jdk/src/share/classes/com/sun/crypto/provider/DHPrivateKey.java Fri Jul 05 13:53:37 2013 -0700
+++ b/jdk/src/share/classes/com/sun/crypto/provider/DHPrivateKey.java Fri Jul 05 13:56:12 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,7 @@
package com.sun.crypto.provider;
import java.io.*;
+import java.util.Objects;
import java.math.BigInteger;
import java.security.KeyRep;
import java.security.PrivateKey;
@@ -67,7 +68,7 @@
// the base generator
private BigInteger g;
- // the private-value length
+ // the private-value length (optional)
private int l;
private int DH_data[] = { 1, 2, 840, 113549, 1, 3, 1 };
@@ -179,20 +180,9 @@
this.key = val.data.getOctetString();
parseKeyBits();
- // ignore OPTIONAL attributes
-
this.encodedKey = encodedKey.clone();
-
- } catch (NumberFormatException e) {
- InvalidKeyException ike = new InvalidKeyException(
- "Private-value length too big");
- ike.initCause(e);
- throw ike;
- } catch (IOException e) {
- InvalidKeyException ike = new InvalidKeyException(
- "Error parsing key encoding: " + e.getMessage());
- ike.initCause(e);
- throw ike;
+ } catch (IOException | NumberFormatException e) {
+ throw new InvalidKeyException("Error parsing key encoding", e);
}
}
@@ -234,8 +224,9 @@
DerOutputStream params = new DerOutputStream();
params.putInteger(this.p);
params.putInteger(this.g);
- if (this.l != 0)
+ if (this.l != 0) {
params.putInteger(this.l);
+ }
// wrap parameters into SEQUENCE
DerValue paramSequence = new DerValue(DerValue.tag_Sequence,
params.toByteArray());
@@ -273,10 +264,11 @@
* @return the key parameters
*/
public DHParameterSpec getParams() {
- if (this.l != 0)
+ if (this.l != 0) {
return new DHParameterSpec(this.p, this.g, this.l);
- else
+ } else {
return new DHParameterSpec(this.p, this.g);
+ }
}
public String toString() {
@@ -312,26 +304,21 @@
* Objects that are equal will also have the same hashcode.
*/
public int hashCode() {
- int retval = 0;
- byte[] enc = getEncoded();
-
- for (int i = 1; i < enc.length; i++) {
- retval += enc[i] * i;
- }
- return(retval);
+ return Objects.hash(x, p, g);
}
public boolean equals(Object obj) {
- if (this == obj)
- return true;
+ if (this == obj) return true;
- if (!(obj instanceof PrivateKey))
+ if (!(obj instanceof javax.crypto.interfaces.DHPrivateKey)) {
return false;
-
- byte[] thisEncoded = this.getEncoded();
- byte[] thatEncoded = ((PrivateKey)obj).getEncoded();
-
- return java.util.Arrays.equals(thisEncoded, thatEncoded);
+ }
+ javax.crypto.interfaces.DHPrivateKey other =
+ (javax.crypto.interfaces.DHPrivateKey) obj;
+ DHParameterSpec otherParams = other.getParams();
+ return ((this.x.compareTo(other.getX()) == 0) &&
+ (this.p.compareTo(otherParams.getP()) == 0) &&
+ (this.g.compareTo(otherParams.getG()) == 0));
}
/**
--- a/jdk/src/share/classes/com/sun/crypto/provider/DHPublicKey.java Fri Jul 05 13:53:37 2013 -0700
+++ b/jdk/src/share/classes/com/sun/crypto/provider/DHPublicKey.java Fri Jul 05 13:56:12 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,7 @@
package com.sun.crypto.provider;
import java.io.*;
+import java.util.Objects;
import java.math.BigInteger;
import java.security.KeyRep;
import java.security.InvalidKeyException;
@@ -64,7 +65,7 @@
// the base generator
private BigInteger g;
- // the private-value length
+ // the private-value length (optional)
private int l;
private int DH_data[] = { 1, 2, 840, 113549, 1, 3, 1 };
@@ -173,13 +174,8 @@
}
this.encodedKey = encodedKey.clone();
-
- } catch (NumberFormatException e) {
- throw new InvalidKeyException("Private-value length too big");
-
- } catch (IOException e) {
- throw new InvalidKeyException(
- "Error parsing key encoding: " + e.toString());
+ } catch (IOException | NumberFormatException e) {
+ throw new InvalidKeyException("Error parsing key encoding", e);
}
}
@@ -212,8 +208,9 @@
DerOutputStream params = new DerOutputStream();
params.putInteger(this.p);
params.putInteger(this.g);
- if (this.l != 0)
+ if (this.l != 0) {
params.putInteger(this.l);
+ }
// wrap parameters into SEQUENCE
DerValue paramSequence = new DerValue(DerValue.tag_Sequence,
params.toByteArray());
@@ -253,10 +250,11 @@
* @return the key parameters
*/
public DHParameterSpec getParams() {
- if (this.l != 0)
+ if (this.l != 0) {
return new DHParameterSpec(this.p, this.g, this.l);
- else
+ } else {
return new DHParameterSpec(this.p, this.g);
+ }
}
public String toString() {
@@ -290,26 +288,22 @@
* Objects that are equal will also have the same hashcode.
*/
public int hashCode() {
- int retval = 0;
- byte[] enc = getEncoded();
-
- for (int i = 1; i < enc.length; i++) {
- retval += enc[i] * i;
- }
- return(retval);
+ return Objects.hash(y, p, g);
}
public boolean equals(Object obj) {
- if (this == obj)
- return true;
+ if (this == obj) return true;
- if (!(obj instanceof PublicKey))
+ if (!(obj instanceof javax.crypto.interfaces.DHPublicKey)) {
return false;
+ }
- byte[] thisEncoded = this.getEncoded();
- byte[] thatEncoded = ((PublicKey)obj).getEncoded();
-
- return java.util.Arrays.equals(thisEncoded, thatEncoded);
+ javax.crypto.interfaces.DHPublicKey other =
+ (javax.crypto.interfaces.DHPublicKey) obj;
+ DHParameterSpec otherParams = other.getParams();
+ return ((this.y.compareTo(other.getY()) == 0) &&
+ (this.p.compareTo(otherParams.getP()) == 0) &&
+ (this.g.compareTo(otherParams.getG()) == 0));
}
/**
--- a/jdk/src/share/classes/sun/security/pkcs11/P11Key.java Fri Jul 05 13:53:37 2013 -0700
+++ b/jdk/src/share/classes/sun/security/pkcs11/P11Key.java Fri Jul 05 13:56:12 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -881,6 +881,29 @@
return super.toString() + "\n x: " + x + "\n p: " + params.getP()
+ "\n g: " + params.getG();
}
+ public int hashCode() {
+ if (token.isValid() == false) {
+ return 0;
+ }
+ fetchValues();
+ return Objects.hash(x, params.getP(), params.getG());
+ }
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+ // equals() should never throw exceptions
+ if (token.isValid() == false) {
+ return false;
+ }
+ if (!(obj instanceof DHPrivateKey)) {
+ return false;
+ }
+ fetchValues();
+ DHPrivateKey other = (DHPrivateKey) obj;
+ DHParameterSpec otherParams = other.getParams();
+ return ((this.x.compareTo(other.getX()) == 0) &&
+ (this.params.getP().compareTo(otherParams.getP()) == 0) &&
+ (this.params.getG().compareTo(otherParams.getG()) == 0));
+ }
}
private static final class P11DHPublicKey extends P11Key
@@ -945,6 +968,29 @@
return super.toString() + "\n y: " + y + "\n p: " + params.getP()
+ "\n g: " + params.getG();
}
+ public int hashCode() {
+ if (token.isValid() == false) {
+ return 0;
+ }
+ fetchValues();
+ return Objects.hash(y, params.getP(), params.getG());
+ }
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+ // equals() should never throw exceptions
+ if (token.isValid() == false) {
+ return false;
+ }
+ if (!(obj instanceof DHPublicKey)) {
+ return false;
+ }
+ fetchValues();
+ DHPublicKey other = (DHPublicKey) obj;
+ DHParameterSpec otherParams = other.getParams();
+ return ((this.y.compareTo(other.getY()) == 0) &&
+ (this.params.getP().compareTo(otherParams.getP()) == 0) &&
+ (this.params.getG().compareTo(otherParams.getG()) == 0));
+ }
}
private static final class P11ECPrivateKey extends P11Key