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