1 package org.bouncycastle.jce.provider; 2 3 import java.io.IOException; 4 import java.io.ObjectInputStream; 5 import java.io.ObjectOutputStream; 6 import java.math.BigInteger; 7 8 import javax.crypto.interfaces.DHPublicKey; 9 import javax.crypto.spec.DHParameterSpec; 10 import javax.crypto.spec.DHPublicKeySpec; 11 12 import org.bouncycastle.asn1.ASN1Sequence; 13 import org.bouncycastle.asn1.DERInteger; 14 import org.bouncycastle.asn1.DERObjectIdentifier; 15 import org.bouncycastle.asn1.pkcs.DHParameter; 16 import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; 17 import org.bouncycastle.asn1.x509.AlgorithmIdentifier; 18 import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; 19 import org.bouncycastle.asn1.x9.DHDomainParameters; 20 import org.bouncycastle.asn1.x9.X9ObjectIdentifiers; 21 import org.bouncycastle.crypto.params.DHPublicKeyParameters; 22 23 public class JCEDHPublicKey 24 implements DHPublicKey 25 { 26 static final long serialVersionUID = -216691575254424324L; 27 28 private BigInteger y; 29 private DHParameterSpec dhSpec; 30 private SubjectPublicKeyInfo info; 31 JCEDHPublicKey( DHPublicKeySpec spec)32 JCEDHPublicKey( 33 DHPublicKeySpec spec) 34 { 35 this.y = spec.getY(); 36 this.dhSpec = new DHParameterSpec(spec.getP(), spec.getG()); 37 } 38 JCEDHPublicKey( DHPublicKey key)39 JCEDHPublicKey( 40 DHPublicKey key) 41 { 42 this.y = key.getY(); 43 this.dhSpec = key.getParams(); 44 } 45 JCEDHPublicKey( DHPublicKeyParameters params)46 JCEDHPublicKey( 47 DHPublicKeyParameters params) 48 { 49 this.y = params.getY(); 50 this.dhSpec = new DHParameterSpec(params.getParameters().getP(), params.getParameters().getG(), params.getParameters().getL()); 51 } 52 JCEDHPublicKey( BigInteger y, DHParameterSpec dhSpec)53 JCEDHPublicKey( 54 BigInteger y, 55 DHParameterSpec dhSpec) 56 { 57 this.y = y; 58 this.dhSpec = dhSpec; 59 } 60 JCEDHPublicKey( SubjectPublicKeyInfo info)61 JCEDHPublicKey( 62 SubjectPublicKeyInfo info) 63 { 64 this.info = info; 65 66 DERInteger derY; 67 try 68 { 69 derY = (DERInteger)info.getPublicKey(); 70 } 71 catch (IOException e) 72 { 73 throw new IllegalArgumentException("invalid info structure in DH public key"); 74 } 75 76 this.y = derY.getValue(); 77 78 ASN1Sequence seq = ASN1Sequence.getInstance(info.getAlgorithmId().getParameters()); 79 DERObjectIdentifier id = info.getAlgorithmId().getObjectId(); 80 81 // we need the PKCS check to handle older keys marked with the X9 oid. 82 if (id.equals(PKCSObjectIdentifiers.dhKeyAgreement) || isPKCSParam(seq)) 83 { 84 DHParameter params = new DHParameter(seq); 85 86 if (params.getL() != null) 87 { 88 this.dhSpec = new DHParameterSpec(params.getP(), params.getG(), params.getL().intValue()); 89 } 90 else 91 { 92 this.dhSpec = new DHParameterSpec(params.getP(), params.getG()); 93 } 94 } 95 else if (id.equals(X9ObjectIdentifiers.dhpublicnumber)) 96 { 97 DHDomainParameters params = DHDomainParameters.getInstance(seq); 98 99 this.dhSpec = new DHParameterSpec(params.getP().getValue(), params.getG().getValue()); 100 } 101 else 102 { 103 throw new IllegalArgumentException("unknown algorithm type: " + id); 104 } 105 } 106 getAlgorithm()107 public String getAlgorithm() 108 { 109 return "DH"; 110 } 111 getFormat()112 public String getFormat() 113 { 114 return "X.509"; 115 } 116 getEncoded()117 public byte[] getEncoded() 118 { 119 if (info != null) 120 { 121 return info.getDEREncoded(); 122 } 123 124 SubjectPublicKeyInfo info = new SubjectPublicKeyInfo(new AlgorithmIdentifier(PKCSObjectIdentifiers.dhKeyAgreement, new DHParameter(dhSpec.getP(), dhSpec.getG(), dhSpec.getL()).getDERObject()), new DERInteger(y)); 125 126 return info.getDEREncoded(); 127 } 128 getParams()129 public DHParameterSpec getParams() 130 { 131 return dhSpec; 132 } 133 getY()134 public BigInteger getY() 135 { 136 return y; 137 } 138 isPKCSParam(ASN1Sequence seq)139 private boolean isPKCSParam(ASN1Sequence seq) 140 { 141 if (seq.size() == 2) 142 { 143 return true; 144 } 145 146 if (seq.size() > 3) 147 { 148 return false; 149 } 150 151 DERInteger l = DERInteger.getInstance(seq.getObjectAt(2)); 152 DERInteger p = DERInteger.getInstance(seq.getObjectAt(0)); 153 154 if (l.getValue().compareTo(BigInteger.valueOf(p.getValue().bitLength())) > 0) 155 { 156 return false; 157 } 158 159 return true; 160 } 161 readObject( ObjectInputStream in)162 private void readObject( 163 ObjectInputStream in) 164 throws IOException, ClassNotFoundException 165 { 166 this.y = (BigInteger)in.readObject(); 167 this.dhSpec = new DHParameterSpec((BigInteger)in.readObject(), (BigInteger)in.readObject(), in.readInt()); 168 } 169 writeObject( ObjectOutputStream out)170 private void writeObject( 171 ObjectOutputStream out) 172 throws IOException 173 { 174 out.writeObject(this.getY()); 175 out.writeObject(dhSpec.getP()); 176 out.writeObject(dhSpec.getG()); 177 out.writeInt(dhSpec.getL()); 178 } 179 } 180