1 /* 2 * Copyright (c) 2005, 2018, 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 26 package sun.security.mscapi; 27 28 import java.math.BigInteger; 29 import java.security.KeyException; 30 import java.security.KeyRep; 31 import java.security.ProviderException; 32 33 import sun.security.rsa.RSAUtil.KeyType; 34 import sun.security.rsa.RSAPublicKeyImpl; 35 36 /** 37 * The handle for an RSA public key using the Microsoft Crypto API. 38 * 39 * @since 1.6 40 */ 41 class RSAPublicKey extends Key implements java.security.interfaces.RSAPublicKey 42 { 43 private static final long serialVersionUID = -2289561342425825391L; 44 45 private byte[] publicKeyBlob = null; 46 private byte[] encoding = null; 47 private BigInteger modulus = null; 48 private BigInteger exponent = null; 49 50 /** 51 * Construct an RSAPublicKey object. 52 */ 53 RSAPublicKey(long hCryptProv, long hCryptKey, int keyLength) 54 { 55 super(new NativeHandles(hCryptProv, hCryptKey), keyLength); 56 } 57 58 /** 59 * Construct an RSAPublicKey object. 60 */ 61 RSAPublicKey(NativeHandles handles, int keyLength) 62 { 63 super(handles, keyLength); 64 } 65 66 /** 67 * Returns the standard algorithm name for this key. For 68 * example, "RSA" would indicate that this key is a RSA key. 69 * See Appendix A in the <a href= 70 * "../../../guide/security/CryptoSpec.html#AppA"> 71 * Java Cryptography Architecture API Specification & Reference </a> 72 * for information about standard algorithm names. 73 * 74 * @return the name of the algorithm associated with this key. 75 */ 76 public String getAlgorithm() 77 { 78 return "RSA"; 79 } 80 81 /** 82 * Returns a printable description of the key. 83 */ 84 public String toString() 85 { 86 StringBuffer sb = new StringBuffer(); 87 88 sb.append("RSAPublicKey [size=").append(keyLength) 89 .append(" bits, type=").append(getKeyType(handles.hCryptKey)) 90 .append(", container=").append(getContainerName(handles.hCryptProv)) 91 .append("]\n modulus: ").append(getModulus()) 92 .append("\n public exponent: ").append(getPublicExponent()); 93 94 return sb.toString(); 95 } 96 97 /** 98 * Returns the public exponent. 99 */ 100 public BigInteger getPublicExponent() { 101 102 if (exponent == null) { 103 104 try { 105 publicKeyBlob = getPublicKeyBlob(handles.hCryptKey); 106 exponent = new BigInteger(1, getExponent(publicKeyBlob)); 107 108 } catch (KeyException e) { 109 throw new ProviderException(e); 110 } 111 } 112 113 return exponent; 114 } 115 116 /** 117 * Returns the modulus. 118 */ 119 public BigInteger getModulus() { 120 121 if (modulus == null) { 122 123 try { 124 publicKeyBlob = getPublicKeyBlob(handles.hCryptKey); 125 modulus = new BigInteger(1, getModulus(publicKeyBlob)); 126 127 } catch (KeyException e) { 128 throw new ProviderException(e); 129 } 130 } 131 132 return modulus; 133 } 134 135 /** 136 * Returns the name of the primary encoding format of this key, 137 * or null if this key does not support encoding. 138 * The primary encoding format is 139 * named in terms of the appropriate ASN.1 data format, if an 140 * ASN.1 specification for this key exists. 141 * For example, the name of the ASN.1 data format for public 142 * keys is <I>SubjectPublicKeyInfo</I>, as 143 * defined by the X.509 standard; in this case, the returned format is 144 * <code>"X.509"</code>. Similarly, 145 * the name of the ASN.1 data format for private keys is 146 * <I>PrivateKeyInfo</I>, 147 * as defined by the PKCS #8 standard; in this case, the returned format is 148 * <code>"PKCS#8"</code>. 149 * 150 * @return the primary encoding format of the key. 151 */ 152 public String getFormat() 153 { 154 return "X.509"; 155 } 156 157 /** 158 * Returns the key in its primary encoding format, or null 159 * if this key does not support encoding. 160 * 161 * @return the encoded key, or null if the key does not support 162 * encoding. 163 */ 164 public byte[] getEncoded() 165 { 166 if (encoding == null) { 167 168 try { 169 encoding = RSAPublicKeyImpl.newKey(KeyType.RSA, null, 170 getModulus(), getPublicExponent()).getEncoded(); 171 172 } catch (KeyException e) { 173 // ignore 174 } 175 } 176 return encoding; 177 } 178 179 protected Object writeReplace() throws java.io.ObjectStreamException { 180 return new KeyRep(KeyRep.Type.PUBLIC, 181 getAlgorithm(), 182 getFormat(), 183 getEncoded()); 184 } 185 186 /* 187 * Returns the Microsoft CryptoAPI representation of the key. 188 */ 189 private native byte[] getPublicKeyBlob(long hCryptKey) throws KeyException; 190 191 /* 192 * Returns the key's public exponent (in big-endian 2's complement format). 193 */ 194 private native byte[] getExponent(byte[] keyBlob) throws KeyException; 195 196 /* 197 * Returns the key's modulus (in big-endian 2's complement format). 198 */ 199 private native byte[] getModulus(byte[] keyBlob) throws KeyException; 200 }