From f73f93be5a76e641c31b87e456c632c914bc7d6c Mon Sep 17 00:00:00 2001 From: valeriep Date: Fri, 5 Jul 2013 13:56:12 -0700 Subject: [PATCH] 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 --- .../com/sun/crypto/provider/DHKeyFactory.java | 8 +-- .../crypto/provider/DHKeyPairGenerator.java | 9 ++-- .../com/sun/crypto/provider/DHPrivateKey.java | 53 +++++++------------ .../com/sun/crypto/provider/DHPublicKey.java | 46 +++++++--------- .../classes/sun/security/pkcs11/P11Key.java | 48 ++++++++++++++++- 5 files changed, 96 insertions(+), 68 deletions(-) diff --git a/src/share/classes/com/sun/crypto/provider/DHKeyFactory.java b/src/share/classes/com/sun/crypto/provider/DHKeyFactory.java index 38e7d36f3..273d49eb0 100644 --- a/src/share/classes/com/sun/crypto/provider/DHKeyFactory.java +++ b/src/share/classes/com/sun/crypto/provider/DHKeyFactory.java @@ -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 @@ public final class DHKeyFactory extends KeyFactorySpi { } } catch (InvalidKeyException e) { throw new InvalidKeySpecException - ("Inappropriate key specification"); + ("Inappropriate key specification", e); } } @@ -118,7 +118,7 @@ public final class DHKeyFactory extends KeyFactorySpi { } } catch (InvalidKeyException e) { throw new InvalidKeySpecException - ("Inappropriate key specification"); + ("Inappropriate key specification", e); } } @@ -227,7 +227,7 @@ public final class DHKeyFactory extends KeyFactorySpi { } } catch (InvalidKeySpecException e) { - throw new InvalidKeyException("Cannot translate key"); + throw new InvalidKeyException("Cannot translate key", e); } } } diff --git a/src/share/classes/com/sun/crypto/provider/DHKeyPairGenerator.java b/src/share/classes/com/sun/crypto/provider/DHKeyPairGenerator.java index 6ae39e25e..c71d6ab3f 100644 --- a/src/share/classes/com/sun/crypto/provider/DHKeyPairGenerator.java +++ b/src/share/classes/com/sun/crypto/provider/DHKeyPairGenerator.java @@ -167,15 +167,16 @@ public final class DHKeyPairGenerator extends KeyPairGeneratorSpi { 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); diff --git a/src/share/classes/com/sun/crypto/provider/DHPrivateKey.java b/src/share/classes/com/sun/crypto/provider/DHPrivateKey.java index 1653a2399..e3254c4fc 100644 --- a/src/share/classes/com/sun/crypto/provider/DHPrivateKey.java +++ b/src/share/classes/com/sun/crypto/provider/DHPrivateKey.java @@ -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 @@ javax.crypto.interfaces.DHPrivateKey, Serializable { // 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 @@ javax.crypto.interfaces.DHPrivateKey, Serializable { 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 @@ javax.crypto.interfaces.DHPrivateKey, Serializable { 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 @@ javax.crypto.interfaces.DHPrivateKey, Serializable { * @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 @@ javax.crypto.interfaces.DHPrivateKey, Serializable { * 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)); } /** diff --git a/src/share/classes/com/sun/crypto/provider/DHPublicKey.java b/src/share/classes/com/sun/crypto/provider/DHPublicKey.java index a9062e507..7293c9457 100644 --- a/src/share/classes/com/sun/crypto/provider/DHPublicKey.java +++ b/src/share/classes/com/sun/crypto/provider/DHPublicKey.java @@ -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 @@ javax.crypto.interfaces.DHPublicKey, Serializable { // 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 @@ javax.crypto.interfaces.DHPublicKey, Serializable { } 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 @@ javax.crypto.interfaces.DHPublicKey, Serializable { 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 @@ javax.crypto.interfaces.DHPublicKey, Serializable { * @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 @@ javax.crypto.interfaces.DHPublicKey, Serializable { * 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)); } /** diff --git a/src/share/classes/sun/security/pkcs11/P11Key.java b/src/share/classes/sun/security/pkcs11/P11Key.java index dd0ec5f7e..ae9264779 100644 --- a/src/share/classes/sun/security/pkcs11/P11Key.java +++ b/src/share/classes/sun/security/pkcs11/P11Key.java @@ -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 @@ abstract class P11Key implements Key, Length { 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 @@ abstract class P11Key implements Key, Length { 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 -- GitLab