1b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallampackage org.bouncycastle.jce.provider;
2b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
36e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstromimport java.io.IOException;
46e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstromimport java.io.ObjectInputStream;
56e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstromimport java.io.ObjectOutputStream;
66e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstromimport java.math.BigInteger;
76e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstromimport java.util.Enumeration;
86e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
96e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstromimport javax.crypto.interfaces.DHPrivateKey;
106e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstromimport javax.crypto.spec.DHParameterSpec;
116e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstromimport javax.crypto.spec.DHPrivateKeySpec;
126e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
134c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.asn1.ASN1Encodable;
144c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.asn1.ASN1Encoding;
154c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.asn1.ASN1ObjectIdentifier;
16b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.ASN1Sequence;
17b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.DERInteger;
18b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.DERObjectIdentifier;
19b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.pkcs.DHParameter;
20b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
21b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
22b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.x509.AlgorithmIdentifier;
236e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstromimport org.bouncycastle.asn1.x9.DHDomainParameters;
246e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstromimport org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
25b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.crypto.params.DHPrivateKeyParameters;
264c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.jcajce.provider.asymmetric.util.PKCS12BagAttributeCarrierImpl;
27b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.jce.interfaces.PKCS12BagAttributeCarrier;
28b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
29b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallampublic class JCEDHPrivateKey
30b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    implements DHPrivateKey, PKCS12BagAttributeCarrier
31b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam{
32c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    static final long serialVersionUID = 311058815616901812L;
33c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
34b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    BigInteger      x;
35b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
366e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    private DHParameterSpec dhSpec;
376e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    private PrivateKeyInfo  info;
38b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
39c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    private PKCS12BagAttributeCarrier attrCarrier = new PKCS12BagAttributeCarrierImpl();
40b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
41b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    protected JCEDHPrivateKey()
42b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
43b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
44b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
45b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    JCEDHPrivateKey(
46b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        DHPrivateKey    key)
47b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
48b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        this.x = key.getX();
49b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        this.dhSpec = key.getParams();
50b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
51b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
52b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    JCEDHPrivateKey(
53b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        DHPrivateKeySpec    spec)
54b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
55b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        this.x = spec.getX();
56b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        this.dhSpec = new DHParameterSpec(spec.getP(), spec.getG());
57b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
58b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
59b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    JCEDHPrivateKey(
60b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        PrivateKeyInfo  info)
614c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        throws IOException
62b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
636e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        ASN1Sequence    seq = ASN1Sequence.getInstance(info.getAlgorithmId().getParameters());
644c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        DERInteger      derX = DERInteger.getInstance(info.parsePrivateKey());
654c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        DERObjectIdentifier id = info.getAlgorithmId().getAlgorithm();
66b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
676e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        this.info = info;
68b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        this.x = derX.getValue();
696e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
706e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        if (id.equals(PKCSObjectIdentifiers.dhKeyAgreement))
716e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        {
724c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            DHParameter params = DHParameter.getInstance(seq);
736e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
746e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            if (params.getL() != null)
756e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            {
766e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                this.dhSpec = new DHParameterSpec(params.getP(), params.getG(), params.getL().intValue());
776e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            }
786e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            else
796e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            {
806e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                this.dhSpec = new DHParameterSpec(params.getP(), params.getG());
816e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            }
826e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        }
836e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        else if (id.equals(X9ObjectIdentifiers.dhpublicnumber))
84b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
856e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            DHDomainParameters params = DHDomainParameters.getInstance(seq);
866e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
876e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            this.dhSpec = new DHParameterSpec(params.getP().getValue(), params.getG().getValue());
88b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
89b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        else
90b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
916e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            throw new IllegalArgumentException("unknown algorithm type: " + id);
92b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
93b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
94b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
95b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    JCEDHPrivateKey(
96b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        DHPrivateKeyParameters  params)
97b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
98b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        this.x = params.getX();
99c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        this.dhSpec = new DHParameterSpec(params.getParameters().getP(), params.getParameters().getG(), params.getParameters().getL());
100b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
101b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
102b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public String getAlgorithm()
103b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
104b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        return "DH";
105b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
106b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
107b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    /**
108b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * return the encoding format we produce in getEncoded().
109b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     *
110b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * @return the string "PKCS#8"
111b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     */
112b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public String getFormat()
113b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
114b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        return "PKCS#8";
115b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
116b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
117b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    /**
118b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * Return a PKCS8 representation of the key. The sequence returned
119b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * represents a full PrivateKeyInfo object.
120b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     *
121b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * @return a PKCS8 representation of the key.
122b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     */
123b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public byte[] getEncoded()
124b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
1254c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        try
1266e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        {
1274c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            if (info != null)
1284c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
1294c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                return info.getEncoded(ASN1Encoding.DER);
1304c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
131b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1324c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            PrivateKeyInfo          info = new PrivateKeyInfo(new AlgorithmIdentifier(PKCSObjectIdentifiers.dhKeyAgreement, new DHParameter(dhSpec.getP(), dhSpec.getG(), dhSpec.getL())), new DERInteger(getX()));
1334c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1344c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            return info.getEncoded(ASN1Encoding.DER);
1354c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
1364c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        catch (IOException e)
1374c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
1384c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            return null;
1394c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
140b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
141b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
142b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public DHParameterSpec getParams()
143b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
144b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        return dhSpec;
145b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
146b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
147b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public BigInteger getX()
148b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
149b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        return x;
150b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
151b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
152b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    private void readObject(
153b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        ObjectInputStream   in)
154b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        throws IOException, ClassNotFoundException
155b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
156b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        x = (BigInteger)in.readObject();
157b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
158b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        this.dhSpec = new DHParameterSpec((BigInteger)in.readObject(), (BigInteger)in.readObject(), in.readInt());
159b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
160b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
161b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    private void writeObject(
162b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        ObjectOutputStream  out)
163b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        throws IOException
164b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
165b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        out.writeObject(this.getX());
166b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        out.writeObject(dhSpec.getP());
167b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        out.writeObject(dhSpec.getG());
168b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        out.writeInt(dhSpec.getL());
169b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
170b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
171b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public void setBagAttribute(
1724c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        ASN1ObjectIdentifier oid,
1734c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        ASN1Encodable attribute)
174b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
175c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        attrCarrier.setBagAttribute(oid, attribute);
176b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
177b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1784c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    public ASN1Encodable getBagAttribute(
17970c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom        ASN1ObjectIdentifier oid)
180b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
181c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        return attrCarrier.getBagAttribute(oid);
182b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
183b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
184b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public Enumeration getBagAttributeKeys()
185b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
186c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        return attrCarrier.getBagAttributeKeys();
187b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
188b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam}
189