1package org.bouncycastle.jce.provider; 2 3import java.io.IOException; 4import java.io.ObjectInputStream; 5import java.io.ObjectOutputStream; 6import java.math.BigInteger; 7import java.util.Enumeration; 8 9import javax.crypto.interfaces.DHPrivateKey; 10import javax.crypto.spec.DHParameterSpec; 11import javax.crypto.spec.DHPrivateKeySpec; 12 13import org.bouncycastle.asn1.ASN1Encodable; 14import org.bouncycastle.asn1.ASN1Encoding; 15import org.bouncycastle.asn1.ASN1Integer; 16import org.bouncycastle.asn1.ASN1ObjectIdentifier; 17import org.bouncycastle.asn1.ASN1Sequence; 18import org.bouncycastle.asn1.pkcs.DHParameter; 19import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; 20import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; 21import org.bouncycastle.asn1.x509.AlgorithmIdentifier; 22import org.bouncycastle.asn1.x9.DHDomainParameters; 23import org.bouncycastle.asn1.x9.X9ObjectIdentifiers; 24import org.bouncycastle.crypto.params.DHPrivateKeyParameters; 25import org.bouncycastle.jcajce.provider.asymmetric.util.PKCS12BagAttributeCarrierImpl; 26import org.bouncycastle.jce.interfaces.PKCS12BagAttributeCarrier; 27 28public class JCEDHPrivateKey 29 implements DHPrivateKey, PKCS12BagAttributeCarrier 30{ 31 static final long serialVersionUID = 311058815616901812L; 32 33 BigInteger x; 34 35 private DHParameterSpec dhSpec; 36 private PrivateKeyInfo info; 37 38 private PKCS12BagAttributeCarrier attrCarrier = new PKCS12BagAttributeCarrierImpl(); 39 40 protected JCEDHPrivateKey() 41 { 42 } 43 44 JCEDHPrivateKey( 45 DHPrivateKey key) 46 { 47 this.x = key.getX(); 48 this.dhSpec = key.getParams(); 49 } 50 51 JCEDHPrivateKey( 52 DHPrivateKeySpec spec) 53 { 54 this.x = spec.getX(); 55 this.dhSpec = new DHParameterSpec(spec.getP(), spec.getG()); 56 } 57 58 JCEDHPrivateKey( 59 PrivateKeyInfo info) 60 throws IOException 61 { 62 ASN1Sequence seq = ASN1Sequence.getInstance(info.getAlgorithmId().getParameters()); 63 ASN1Integer derX = ASN1Integer.getInstance(info.parsePrivateKey()); 64 ASN1ObjectIdentifier id = info.getAlgorithmId().getAlgorithm(); 65 66 this.info = info; 67 this.x = derX.getValue(); 68 69 if (id.equals(PKCSObjectIdentifiers.dhKeyAgreement)) 70 { 71 DHParameter params = DHParameter.getInstance(seq); 72 73 if (params.getL() != null) 74 { 75 this.dhSpec = new DHParameterSpec(params.getP(), params.getG(), params.getL().intValue()); 76 } 77 else 78 { 79 this.dhSpec = new DHParameterSpec(params.getP(), params.getG()); 80 } 81 } 82 else if (id.equals(X9ObjectIdentifiers.dhpublicnumber)) 83 { 84 DHDomainParameters params = DHDomainParameters.getInstance(seq); 85 86 this.dhSpec = new DHParameterSpec(params.getP().getValue(), params.getG().getValue()); 87 } 88 else 89 { 90 throw new IllegalArgumentException("unknown algorithm type: " + id); 91 } 92 } 93 94 JCEDHPrivateKey( 95 DHPrivateKeyParameters params) 96 { 97 this.x = params.getX(); 98 this.dhSpec = new DHParameterSpec(params.getParameters().getP(), params.getParameters().getG(), params.getParameters().getL()); 99 } 100 101 public String getAlgorithm() 102 { 103 return "DH"; 104 } 105 106 /** 107 * return the encoding format we produce in getEncoded(). 108 * 109 * @return the string "PKCS#8" 110 */ 111 public String getFormat() 112 { 113 return "PKCS#8"; 114 } 115 116 /** 117 * Return a PKCS8 representation of the key. The sequence returned 118 * represents a full PrivateKeyInfo object. 119 * 120 * @return a PKCS8 representation of the key. 121 */ 122 public byte[] getEncoded() 123 { 124 try 125 { 126 if (info != null) 127 { 128 return info.getEncoded(ASN1Encoding.DER); 129 } 130 131 PrivateKeyInfo info = new PrivateKeyInfo(new AlgorithmIdentifier(PKCSObjectIdentifiers.dhKeyAgreement, new DHParameter(dhSpec.getP(), dhSpec.getG(), dhSpec.getL())), new ASN1Integer(getX())); 132 133 return info.getEncoded(ASN1Encoding.DER); 134 } 135 catch (IOException e) 136 { 137 return null; 138 } 139 } 140 141 public DHParameterSpec getParams() 142 { 143 return dhSpec; 144 } 145 146 public BigInteger getX() 147 { 148 return x; 149 } 150 151 private void readObject( 152 ObjectInputStream in) 153 throws IOException, ClassNotFoundException 154 { 155 x = (BigInteger)in.readObject(); 156 157 this.dhSpec = new DHParameterSpec((BigInteger)in.readObject(), (BigInteger)in.readObject(), in.readInt()); 158 } 159 160 private void writeObject( 161 ObjectOutputStream out) 162 throws IOException 163 { 164 out.writeObject(this.getX()); 165 out.writeObject(dhSpec.getP()); 166 out.writeObject(dhSpec.getG()); 167 out.writeInt(dhSpec.getL()); 168 } 169 170 public void setBagAttribute( 171 ASN1ObjectIdentifier oid, 172 ASN1Encodable attribute) 173 { 174 attrCarrier.setBagAttribute(oid, attribute); 175 } 176 177 public ASN1Encodable getBagAttribute( 178 ASN1ObjectIdentifier oid) 179 { 180 return attrCarrier.getBagAttribute(oid); 181 } 182 183 public Enumeration getBagAttributeKeys() 184 { 185 return attrCarrier.getBagAttributeKeys(); 186 } 187} 188