BCDHPublicKey.java revision bdb7b3d37025690a0434040b4e0d0623d9fa74af
116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giropackage org.bouncycastle.jcajce.provider.asymmetric.dh; 216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro 316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport java.io.IOException; 416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport java.io.ObjectInputStream; 516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport java.io.ObjectOutputStream; 616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport java.math.BigInteger; 716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro 816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport javax.crypto.interfaces.DHPublicKey; 916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport javax.crypto.spec.DHParameterSpec; 1016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport javax.crypto.spec.DHPublicKeySpec; 1116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro 1216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.asn1.ASN1Integer; 1316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.asn1.ASN1ObjectIdentifier; 1416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.asn1.ASN1Sequence; 1516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.asn1.pkcs.DHParameter; 1616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; 1716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.asn1.x509.AlgorithmIdentifier; 1816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; 1916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.asn1.x9.DHDomainParameters; 20bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giroimport org.bouncycastle.asn1.x9.DomainParameters; 2116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.asn1.x9.X9ObjectIdentifiers; 2216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.crypto.params.DHPublicKeyParameters; 2316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.jcajce.provider.asymmetric.util.KeyUtil; 2416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro 2516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giropublic class BCDHPublicKey 2616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro implements DHPublicKey 2716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro{ 2816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro static final long serialVersionUID = -216691575254424324L; 2916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro 3016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro private BigInteger y; 3116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro 3216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro private transient DHParameterSpec dhSpec; 3316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro private transient SubjectPublicKeyInfo info; 3416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro 3516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro BCDHPublicKey( 3616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro DHPublicKeySpec spec) 3716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro { 3816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro this.y = spec.getY(); 3916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro this.dhSpec = new DHParameterSpec(spec.getP(), spec.getG()); 4016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro } 4116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro 4216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro BCDHPublicKey( 4316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro DHPublicKey key) 4416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro { 4516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro this.y = key.getY(); 4616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro this.dhSpec = key.getParams(); 4716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro } 4816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro 4916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro BCDHPublicKey( 5016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro DHPublicKeyParameters params) 5116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro { 5216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro this.y = params.getY(); 5316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro this.dhSpec = new DHParameterSpec(params.getParameters().getP(), params.getParameters().getG(), params.getParameters().getL()); 5416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro } 5516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro 5616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro BCDHPublicKey( 5716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro BigInteger y, 5816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro DHParameterSpec dhSpec) 5916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro { 6016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro this.y = y; 6116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro this.dhSpec = dhSpec; 6216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro } 6316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro 6416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro public BCDHPublicKey( 6516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro SubjectPublicKeyInfo info) 6616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro { 6716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro this.info = info; 6816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro 6916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro ASN1Integer derY; 7016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro try 7116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro { 7216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro derY = (ASN1Integer)info.parsePublicKey(); 7316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro } 7416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro catch (IOException e) 7516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro { 7616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro throw new IllegalArgumentException("invalid info structure in DH public key"); 7716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro } 7816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro 7916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro this.y = derY.getValue(); 8016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro 8116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro ASN1Sequence seq = ASN1Sequence.getInstance(info.getAlgorithm().getParameters()); 8216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro ASN1ObjectIdentifier id = info.getAlgorithm().getAlgorithm(); 8316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro 8416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro // we need the PKCS check to handle older keys marked with the X9 oid. 8516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro if (id.equals(PKCSObjectIdentifiers.dhKeyAgreement) || isPKCSParam(seq)) 8616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro { 8716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro DHParameter params = DHParameter.getInstance(seq); 8816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro 8916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro if (params.getL() != null) 9016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro { 9116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro this.dhSpec = new DHParameterSpec(params.getP(), params.getG(), params.getL().intValue()); 9216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro } 9316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro else 9416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro { 9516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro this.dhSpec = new DHParameterSpec(params.getP(), params.getG()); 9616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro } 9716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro } 9816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro else if (id.equals(X9ObjectIdentifiers.dhpublicnumber)) 9916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro { 100bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro DomainParameters params = DomainParameters.getInstance(seq); 10116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro 102bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro this.dhSpec = new DHParameterSpec(params.getP(), params.getG()); 10316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro } 10416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro else 10516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro { 10616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro throw new IllegalArgumentException("unknown algorithm type: " + id); 10716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro } 10816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro } 10916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro 11016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro public String getAlgorithm() 11116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro { 11216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro return "DH"; 11316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro } 11416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro 11516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro public String getFormat() 11616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro { 11716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro return "X.509"; 11816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro } 11916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro 12016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro public byte[] getEncoded() 12116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro { 12216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro if (info != null) 12316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro { 12416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro return KeyUtil.getEncodedSubjectPublicKeyInfo(info); 12516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro } 12616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro 12716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro return KeyUtil.getEncodedSubjectPublicKeyInfo(new AlgorithmIdentifier(PKCSObjectIdentifiers.dhKeyAgreement, new DHParameter(dhSpec.getP(), dhSpec.getG(), dhSpec.getL()).toASN1Primitive()), new ASN1Integer(y)); 12816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro } 12916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro 13016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro public DHParameterSpec getParams() 13116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro { 13216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro return dhSpec; 13316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro } 13416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro 13516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro public BigInteger getY() 13616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro { 13716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro return y; 13816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro } 13916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro 14016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro private boolean isPKCSParam(ASN1Sequence seq) 14116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro { 14216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro if (seq.size() == 2) 14316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro { 14416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro return true; 14516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro } 14616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro 14716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro if (seq.size() > 3) 14816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro { 14916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro return false; 15016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro } 15116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro 15216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro ASN1Integer l = ASN1Integer.getInstance(seq.getObjectAt(2)); 15316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro ASN1Integer p = ASN1Integer.getInstance(seq.getObjectAt(0)); 15416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro 15516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro if (l.getValue().compareTo(BigInteger.valueOf(p.getValue().bitLength())) > 0) 15616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro { 15716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro return false; 15816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro } 15916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro 16016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro return true; 16116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro } 16216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro 16316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro public int hashCode() 16416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro { 16516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro return this.getY().hashCode() ^ this.getParams().getG().hashCode() 16616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro ^ this.getParams().getP().hashCode() ^ this.getParams().getL(); 16716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro } 16816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro 16916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro public boolean equals( 17016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro Object o) 17116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro { 17216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro if (!(o instanceof DHPublicKey)) 17316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro { 17416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro return false; 17516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro } 17616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro 17716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro DHPublicKey other = (DHPublicKey)o; 17816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro 17916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro return this.getY().equals(other.getY()) 18016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro && this.getParams().getG().equals(other.getParams().getG()) 18116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro && this.getParams().getP().equals(other.getParams().getP()) 18216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro && this.getParams().getL() == other.getParams().getL(); 18316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro } 18416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro 18516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro private void readObject( 18616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro ObjectInputStream in) 18716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro throws IOException, ClassNotFoundException 18816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro { 18916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro in.defaultReadObject(); 19016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro 19116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro this.dhSpec = new DHParameterSpec((BigInteger)in.readObject(), (BigInteger)in.readObject(), in.readInt()); 19216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro this.info = null; 19316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro } 19416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro 19516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro private void writeObject( 19616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro ObjectOutputStream out) 19716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro throws IOException 19816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro { 19916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro out.defaultWriteObject(); 20016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro 20116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro out.writeObject(dhSpec.getP()); 20216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro out.writeObject(dhSpec.getG()); 20316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro out.writeInt(dhSpec.getL()); 20416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro } 20516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro} 206