14c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrompackage org.bouncycastle.jcajce.provider.asymmetric.dh; 24c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom 34c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport java.io.IOException; 44c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport java.io.ObjectInputStream; 54c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport java.io.ObjectOutputStream; 64c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport java.math.BigInteger; 74c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom 84c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport javax.crypto.interfaces.DHPublicKey; 94c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport javax.crypto.spec.DHParameterSpec; 104c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport javax.crypto.spec.DHPublicKeySpec; 114c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom 124c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.asn1.ASN1Integer; 134c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.asn1.ASN1ObjectIdentifier; 144c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.asn1.ASN1Sequence; 154c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.asn1.pkcs.DHParameter; 164c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; 174c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.asn1.x509.AlgorithmIdentifier; 184c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; 194c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.asn1.x9.DHDomainParameters; 204c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.asn1.x9.X9ObjectIdentifiers; 214c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.crypto.params.DHPublicKeyParameters; 224c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.jcajce.provider.asymmetric.util.KeyUtil; 234c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom 244c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrompublic class BCDHPublicKey 254c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom implements DHPublicKey 264c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom{ 274c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom static final long serialVersionUID = -216691575254424324L; 284c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom 294c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom private BigInteger y; 304c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom 314c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom private transient DHParameterSpec dhSpec; 324c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom private transient SubjectPublicKeyInfo info; 334c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom 344c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom BCDHPublicKey( 354c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom DHPublicKeySpec spec) 364c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom { 374c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom this.y = spec.getY(); 384c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom this.dhSpec = new DHParameterSpec(spec.getP(), spec.getG()); 394c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom } 404c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom 414c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom BCDHPublicKey( 424c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom DHPublicKey key) 434c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom { 444c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom this.y = key.getY(); 454c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom this.dhSpec = key.getParams(); 464c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom } 474c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom 484c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom BCDHPublicKey( 494c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom DHPublicKeyParameters params) 504c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom { 514c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom this.y = params.getY(); 524c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom this.dhSpec = new DHParameterSpec(params.getParameters().getP(), params.getParameters().getG(), params.getParameters().getL()); 534c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom } 544c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom 554c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom BCDHPublicKey( 564c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom BigInteger y, 574c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom DHParameterSpec dhSpec) 584c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom { 594c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom this.y = y; 604c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom this.dhSpec = dhSpec; 614c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom } 624c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom 634c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom public BCDHPublicKey( 644c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom SubjectPublicKeyInfo info) 654c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom { 664c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom this.info = info; 674c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom 684c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom ASN1Integer derY; 694c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom try 704c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom { 714c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom derY = (ASN1Integer)info.parsePublicKey(); 724c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom } 734c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom catch (IOException e) 744c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom { 754c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom throw new IllegalArgumentException("invalid info structure in DH public key"); 764c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom } 774c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom 784c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom this.y = derY.getValue(); 794c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom 804c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom ASN1Sequence seq = ASN1Sequence.getInstance(info.getAlgorithm().getParameters()); 814c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom ASN1ObjectIdentifier id = info.getAlgorithm().getAlgorithm(); 824c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom 834c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom // we need the PKCS check to handle older keys marked with the X9 oid. 844c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom if (id.equals(PKCSObjectIdentifiers.dhKeyAgreement) || isPKCSParam(seq)) 854c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom { 864c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom DHParameter params = DHParameter.getInstance(seq); 874c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom 884c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom if (params.getL() != null) 894c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom { 904c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom this.dhSpec = new DHParameterSpec(params.getP(), params.getG(), params.getL().intValue()); 914c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom } 924c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom else 934c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom { 944c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom this.dhSpec = new DHParameterSpec(params.getP(), params.getG()); 954c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom } 964c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom } 974c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom else if (id.equals(X9ObjectIdentifiers.dhpublicnumber)) 984c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom { 994c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom DHDomainParameters params = DHDomainParameters.getInstance(seq); 1004c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom 1014c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom this.dhSpec = new DHParameterSpec(params.getP().getValue(), params.getG().getValue()); 1024c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom } 1034c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom else 1044c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom { 1054c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom throw new IllegalArgumentException("unknown algorithm type: " + id); 1064c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom } 1074c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom } 1084c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom 1094c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom public String getAlgorithm() 1104c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom { 1114c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom return "DH"; 1124c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom } 1134c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom 1144c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom public String getFormat() 1154c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom { 1164c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom return "X.509"; 1174c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom } 1184c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom 1194c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom public byte[] getEncoded() 1204c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom { 1214c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom if (info != null) 1224c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom { 1234c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom return KeyUtil.getEncodedSubjectPublicKeyInfo(info); 1244c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom } 1254c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom 1264c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom return KeyUtil.getEncodedSubjectPublicKeyInfo(new AlgorithmIdentifier(PKCSObjectIdentifiers.dhKeyAgreement, new DHParameter(dhSpec.getP(), dhSpec.getG(), dhSpec.getL()).toASN1Primitive()), new ASN1Integer(y)); 1274c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom } 1284c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom 1294c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom public DHParameterSpec getParams() 1304c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom { 1314c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom return dhSpec; 1324c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom } 1334c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom 1344c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom public BigInteger getY() 1354c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom { 1364c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom return y; 1374c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom } 1384c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom 1394c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom private boolean isPKCSParam(ASN1Sequence seq) 1404c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom { 1414c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom if (seq.size() == 2) 1424c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom { 1434c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom return true; 1444c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom } 1454c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom 1464c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom if (seq.size() > 3) 1474c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom { 1484c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom return false; 1494c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom } 1504c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom 1514c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom ASN1Integer l = ASN1Integer.getInstance(seq.getObjectAt(2)); 1524c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom ASN1Integer p = ASN1Integer.getInstance(seq.getObjectAt(0)); 1534c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom 1544c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom if (l.getValue().compareTo(BigInteger.valueOf(p.getValue().bitLength())) > 0) 1554c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom { 1564c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom return false; 1574c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom } 1584c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom 1594c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom return true; 1604c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom } 1614c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom 1624c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom public int hashCode() 1634c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom { 1644c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom return this.getY().hashCode() ^ this.getParams().getG().hashCode() 1654c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom ^ this.getParams().getP().hashCode() ^ this.getParams().getL(); 1664c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom } 1674c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom 1684c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom public boolean equals( 1694c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom Object o) 1704c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom { 1714c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom if (!(o instanceof DHPublicKey)) 1724c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom { 1734c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom return false; 1744c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom } 1754c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom 1764c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom DHPublicKey other = (DHPublicKey)o; 1774c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom 1784c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom return this.getY().equals(other.getY()) 1794c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom && this.getParams().getG().equals(other.getParams().getG()) 1804c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom && this.getParams().getP().equals(other.getParams().getP()) 1814c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom && this.getParams().getL() == other.getParams().getL(); 1824c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom } 1834c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom 1844c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom private void readObject( 1854c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom ObjectInputStream in) 1864c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom throws IOException, ClassNotFoundException 1874c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom { 1884c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom in.defaultReadObject(); 1894c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom 1904c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom this.dhSpec = new DHParameterSpec((BigInteger)in.readObject(), (BigInteger)in.readObject(), in.readInt()); 1914c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom this.info = null; 1924c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom } 1934c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom 1944c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom private void writeObject( 1954c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom ObjectOutputStream out) 1964c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom throws IOException 1974c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom { 1984c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom out.defaultWriteObject(); 1994c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom 2004c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom out.writeObject(dhSpec.getP()); 2014c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom out.writeObject(dhSpec.getG()); 2024c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom out.writeInt(dhSpec.getL()); 2034c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom } 2044c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom} 205