7196805: DH Key interoperability testing between SunJCE and JsafeJCE not successful
authorvaleriep
Fri, 05 Jul 2013 13:56:12 -0700
changeset 18809 97f5713a0f1a
parent 18808 b2eaaaaed037
child 18810 76a7cd9041d5
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
jdk/src/share/classes/com/sun/crypto/provider/DHKeyFactory.java
jdk/src/share/classes/com/sun/crypto/provider/DHKeyPairGenerator.java
jdk/src/share/classes/com/sun/crypto/provider/DHPrivateKey.java
jdk/src/share/classes/com/sun/crypto/provider/DHPublicKey.java
jdk/src/share/classes/sun/security/pkcs11/P11Key.java
--- 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