1package org.bouncycastle.jce.provider;
2
3import org.bouncycastle.asn1.ASN1Sequence;
4import org.bouncycastle.asn1.DERNull;
5import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
6import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
7import org.bouncycastle.asn1.pkcs.RSAPrivateKeyStructure;
8import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
9import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
10
11import java.math.BigInteger;
12import java.security.interfaces.RSAPrivateCrtKey;
13import java.security.spec.RSAPrivateCrtKeySpec;
14
15/**
16 * A provider representation for a RSA private key, with CRT factors included.
17 */
18public class JCERSAPrivateCrtKey
19    extends JCERSAPrivateKey
20    implements RSAPrivateCrtKey
21{
22    static final long serialVersionUID = 7834723820638524718L;
23
24    private BigInteger  publicExponent;
25    private BigInteger  primeP;
26    private BigInteger  primeQ;
27    private BigInteger  primeExponentP;
28    private BigInteger  primeExponentQ;
29    private BigInteger  crtCoefficient;
30
31    /**
32     * construct a private key from it's org.bouncycastle.crypto equivalent.
33     *
34     * @param key the parameters object representing the private key.
35     */
36    JCERSAPrivateCrtKey(
37        RSAPrivateCrtKeyParameters key)
38    {
39        super(key);
40
41        this.publicExponent = key.getPublicExponent();
42        this.primeP = key.getP();
43        this.primeQ = key.getQ();
44        this.primeExponentP = key.getDP();
45        this.primeExponentQ = key.getDQ();
46        this.crtCoefficient = key.getQInv();
47    }
48
49    /**
50     * construct a private key from an RSAPrivateCrtKeySpec
51     *
52     * @param spec the spec to be used in construction.
53     */
54    JCERSAPrivateCrtKey(
55        RSAPrivateCrtKeySpec spec)
56    {
57        this.modulus = spec.getModulus();
58        this.publicExponent = spec.getPublicExponent();
59        this.privateExponent = spec.getPrivateExponent();
60        this.primeP = spec.getPrimeP();
61        this.primeQ = spec.getPrimeQ();
62        this.primeExponentP = spec.getPrimeExponentP();
63        this.primeExponentQ = spec.getPrimeExponentQ();
64        this.crtCoefficient = spec.getCrtCoefficient();
65    }
66
67    /**
68     * construct a private key from another RSAPrivateCrtKey.
69     *
70     * @param key the object implementing the RSAPrivateCrtKey interface.
71     */
72    JCERSAPrivateCrtKey(
73        RSAPrivateCrtKey key)
74    {
75        this.modulus = key.getModulus();
76        this.publicExponent = key.getPublicExponent();
77        this.privateExponent = key.getPrivateExponent();
78        this.primeP = key.getPrimeP();
79        this.primeQ = key.getPrimeQ();
80        this.primeExponentP = key.getPrimeExponentP();
81        this.primeExponentQ = key.getPrimeExponentQ();
82        this.crtCoefficient = key.getCrtCoefficient();
83    }
84
85    /**
86     * construct an RSA key from a private key info object.
87     */
88    JCERSAPrivateCrtKey(
89        PrivateKeyInfo  info)
90    {
91        this(new RSAPrivateKeyStructure((ASN1Sequence)info.getPrivateKey()));
92    }
93
94    /**
95     * construct an RSA key from a ASN.1 RSA private key object.
96     */
97    JCERSAPrivateCrtKey(
98        RSAPrivateKeyStructure  key)
99    {
100        this.modulus = key.getModulus();
101        this.publicExponent = key.getPublicExponent();
102        this.privateExponent = key.getPrivateExponent();
103        this.primeP = key.getPrime1();
104        this.primeQ = key.getPrime2();
105        this.primeExponentP = key.getExponent1();
106        this.primeExponentQ = key.getExponent2();
107        this.crtCoefficient = key.getCoefficient();
108    }
109
110    /**
111     * return the encoding format we produce in getEncoded().
112     *
113     * @return the encoding format we produce in getEncoded().
114     */
115    public String getFormat()
116    {
117        return "PKCS#8";
118    }
119
120    /**
121     * Return a PKCS8 representation of the key. The sequence returned
122     * represents a full PrivateKeyInfo object.
123     *
124     * @return a PKCS8 representation of the key.
125     */
126    public byte[] getEncoded()
127    {
128        // BEGIN android-changed
129        PrivateKeyInfo          info = new PrivateKeyInfo(new AlgorithmIdentifier(PKCSObjectIdentifiers.rsaEncryption, DERNull.INSTANCE), new RSAPrivateKeyStructure(getModulus(), getPublicExponent(), getPrivateExponent(), getPrimeP(), getPrimeQ(), getPrimeExponentP(), getPrimeExponentQ(), getCrtCoefficient()).getDERObject());
130        // END android-changed
131
132        return info.getDEREncoded();
133    }
134
135    /**
136     * return the public exponent.
137     *
138     * @return the public exponent.
139     */
140    public BigInteger getPublicExponent()
141    {
142        return publicExponent;
143    }
144
145    /**
146     * return the prime P.
147     *
148     * @return the prime P.
149     */
150    public BigInteger getPrimeP()
151    {
152        return primeP;
153    }
154
155    /**
156     * return the prime Q.
157     *
158     * @return the prime Q.
159     */
160    public BigInteger getPrimeQ()
161    {
162        return primeQ;
163    }
164
165    /**
166     * return the prime exponent for P.
167     *
168     * @return the prime exponent for P.
169     */
170    public BigInteger getPrimeExponentP()
171    {
172        return primeExponentP;
173    }
174
175    /**
176     * return the prime exponent for Q.
177     *
178     * @return the prime exponent for Q.
179     */
180    public BigInteger getPrimeExponentQ()
181    {
182        return primeExponentQ;
183    }
184
185    /**
186     * return the CRT coefficient.
187     *
188     * @return the CRT coefficient.
189     */
190    public BigInteger getCrtCoefficient()
191    {
192        return crtCoefficient;
193    }
194
195    public int hashCode()
196    {
197        return this.getModulus().hashCode()
198               ^ this.getPublicExponent().hashCode()
199               ^ this.getPrivateExponent().hashCode();
200    }
201
202    public boolean equals(Object o)
203    {
204        if (o == this)
205        {
206            return true;
207        }
208
209        if (!(o instanceof RSAPrivateCrtKey))
210        {
211            return false;
212        }
213
214        RSAPrivateCrtKey key = (RSAPrivateCrtKey)o;
215
216        return this.getModulus().equals(key.getModulus())
217         && this.getPublicExponent().equals(key.getPublicExponent())
218         && this.getPrivateExponent().equals(key.getPrivateExponent())
219         && this.getPrimeP().equals(key.getPrimeP())
220         && this.getPrimeQ().equals(key.getPrimeQ())
221         && this.getPrimeExponentP().equals(key.getPrimeExponentP())
222         && this.getPrimeExponentQ().equals(key.getPrimeExponentQ())
223         && this.getCrtCoefficient().equals(key.getCrtCoefficient());
224    }
225
226    public String toString()
227    {
228        StringBuffer    buf = new StringBuffer();
229        String          nl = System.getProperty("line.separator");
230
231        buf.append("RSA Private CRT Key").append(nl);
232        buf.append("            modulus: ").append(this.getModulus().toString(16)).append(nl);
233        buf.append("    public exponent: ").append(this.getPublicExponent().toString(16)).append(nl);
234        buf.append("   private exponent: ").append(this.getPrivateExponent().toString(16)).append(nl);
235        buf.append("             primeP: ").append(this.getPrimeP().toString(16)).append(nl);
236        buf.append("             primeQ: ").append(this.getPrimeQ().toString(16)).append(nl);
237        buf.append("     primeExponentP: ").append(this.getPrimeExponentP().toString(16)).append(nl);
238        buf.append("     primeExponentQ: ").append(this.getPrimeExponentQ().toString(16)).append(nl);
239        buf.append("     crtCoefficient: ").append(this.getCrtCoefficient().toString(16)).append(nl);
240
241        return buf.toString();
242    }
243}
244