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 & 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