1/*
2 * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package sun.security.mscapi;
27
28import java.math.BigInteger;
29import java.security.KeyException;
30import java.security.KeyRep;
31import java.security.ProviderException;
32
33import sun.security.rsa.RSAPublicKeyImpl;
34
35/**
36 * The handle for an RSA public key using the Microsoft Crypto API.
37 *
38 * @since 1.6
39 */
40class RSAPublicKey extends Key implements java.security.interfaces.RSAPublicKey
41{
42    private static final long serialVersionUID = -2289561342425825391L;
43
44    private byte[] publicKeyBlob = null;
45    private byte[] encoding = null;
46    private BigInteger modulus = null;
47    private BigInteger exponent = null;
48
49    /**
50     * Construct an RSAPublicKey object.
51     */
52    RSAPublicKey(long hCryptProv, long hCryptKey, int keyLength)
53    {
54        super(new NativeHandles(hCryptProv, hCryptKey), keyLength);
55    }
56
57    /**
58     * Construct an RSAPublicKey object.
59     */
60    RSAPublicKey(NativeHandles handles, int keyLength)
61    {
62        super(handles, keyLength);
63    }
64
65    /**
66     * Returns the standard algorithm name for this key. For
67     * example, "RSA" would indicate that this key is a RSA key.
68     * See Appendix A in the <a href=
69     * "../../../guide/security/CryptoSpec.html#AppA">
70     * Java Cryptography Architecture API Specification &amp; Reference </a>
71     * for information about standard algorithm names.
72     *
73     * @return the name of the algorithm associated with this key.
74     */
75    public String getAlgorithm()
76    {
77        return "RSA";
78    }
79
80    /**
81     * Returns a printable description of the key.
82     */
83    public String toString()
84    {
85        StringBuffer sb = new StringBuffer();
86
87        sb.append("RSAPublicKey [size=").append(keyLength)
88            .append(" bits, type=").append(getKeyType(handles.hCryptKey))
89            .append(", container=").append(getContainerName(handles.hCryptProv))
90            .append("]\n  modulus: ").append(getModulus())
91            .append("\n  public exponent: ").append(getPublicExponent());
92
93        return sb.toString();
94    }
95
96    /**
97     * Returns the public exponent.
98     */
99    public BigInteger getPublicExponent() {
100
101        if (exponent == null) {
102
103            try {
104                publicKeyBlob = getPublicKeyBlob(handles.hCryptKey);
105                exponent = new BigInteger(1, getExponent(publicKeyBlob));
106
107            } catch (KeyException e) {
108                throw new ProviderException(e);
109            }
110        }
111
112        return exponent;
113    }
114
115    /**
116     * Returns the modulus.
117     */
118    public BigInteger getModulus() {
119
120        if (modulus == null) {
121
122            try {
123                publicKeyBlob = getPublicKeyBlob(handles.hCryptKey);
124                modulus = new BigInteger(1, getModulus(publicKeyBlob));
125
126            } catch (KeyException e) {
127                throw new ProviderException(e);
128            }
129        }
130
131        return modulus;
132    }
133
134    /**
135     * Returns the name of the primary encoding format of this key,
136     * or null if this key does not support encoding.
137     * The primary encoding format is
138     * named in terms of the appropriate ASN.1 data format, if an
139     * ASN.1 specification for this key exists.
140     * For example, the name of the ASN.1 data format for public
141     * keys is <I>SubjectPublicKeyInfo</I>, as
142     * defined by the X.509 standard; in this case, the returned format is
143     * <code>"X.509"</code>. Similarly,
144     * the name of the ASN.1 data format for private keys is
145     * <I>PrivateKeyInfo</I>,
146     * as defined by the PKCS #8 standard; in this case, the returned format is
147     * <code>"PKCS#8"</code>.
148     *
149     * @return the primary encoding format of the key.
150     */
151    public String getFormat()
152    {
153        return "X.509";
154    }
155
156    /**
157     * Returns the key in its primary encoding format, or null
158     * if this key does not support encoding.
159     *
160     * @return the encoded key, or null if the key does not support
161     * encoding.
162     */
163    public byte[] getEncoded()
164    {
165        if (encoding == null) {
166
167            try {
168                encoding = new RSAPublicKeyImpl(getModulus(),
169                    getPublicExponent()).getEncoded();
170
171            } catch (KeyException e) {
172                // ignore
173            }
174        }
175        return encoding;
176    }
177
178    protected Object writeReplace() throws java.io.ObjectStreamException {
179        return new KeyRep(KeyRep.Type.PUBLIC,
180                        getAlgorithm(),
181                        getFormat(),
182                        getEncoded());
183    }
184
185    /*
186     * Returns the Microsoft CryptoAPI representation of the key.
187     */
188    private native byte[] getPublicKeyBlob(long hCryptKey) throws KeyException;
189
190    /*
191     * Returns the key's public exponent (in big-endian 2's complement format).
192     */
193    private native byte[] getExponent(byte[] keyBlob) throws KeyException;
194
195    /*
196     * Returns the key's modulus (in big-endian 2's complement format).
197     */
198    private native byte[] getModulus(byte[] keyBlob) throws KeyException;
199}
200