Path: blob/master/src/java.base/share/classes/sun/security/rsa/RSAPublicKeyImpl.java
41159 views
/*1* Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.security.rsa;2627import java.io.IOException;28import java.math.BigInteger;2930import java.security.*;31import java.security.spec.*;32import java.security.interfaces.*;3334import sun.security.util.*;35import sun.security.x509.X509Key;3637import sun.security.rsa.RSAUtil.KeyType;3839/**40* RSA public key implementation for "RSA", "RSASSA-PSS" algorithms.41*42* Note: RSA keys must be at least 512 bits long43*44* @see RSAPrivateCrtKeyImpl45* @see RSAPrivateKeyImpl46* @see RSAKeyFactory47*48* @since 1.549* @author Andreas Sterbenz50*/51public final class RSAPublicKeyImpl extends X509Key implements RSAPublicKey {5253@java.io.Serial54private static final long serialVersionUID = 2644735423591199609L;55private static final BigInteger THREE = BigInteger.valueOf(3);5657private BigInteger n; // modulus58private BigInteger e; // public exponent5960private transient KeyType type;6162// optional parameters associated with this RSA key63// specified in the encoding of its AlgorithmId64// must be null for "RSA" keys.65private transient AlgorithmParameterSpec keyParams;6667/**68* Generate a new RSAPublicKey from the specified type, format, and69* encoding.70* Also used by SunPKCS11 provider.71*/72public static RSAPublicKey newKey(KeyType type, String format,73byte[] encoded) throws InvalidKeyException {74RSAPublicKey key;75switch (format) {76case "X.509":77key = new RSAPublicKeyImpl(encoded);78RSAKeyFactory.checkKeyAlgo(key, type.keyAlgo);79break;80case "PKCS#1":81try {82BigInteger[] comps = parseASN1(encoded);83key = new RSAPublicKeyImpl(type, null, comps[0], comps[1]);84} catch (IOException ioe) {85throw new InvalidKeyException("Invalid PKCS#1 encoding", ioe);86}87break;88default:89throw new InvalidKeyException("Unsupported RSA PublicKey format: " +90format);91}92return key;93}9495/**96* Generate a new RSAPublicKey from the specified type and components.97* Also used by SunPKCS11 provider.98*/99public static RSAPublicKey newKey(KeyType type,100AlgorithmParameterSpec params, BigInteger n, BigInteger e)101throws InvalidKeyException {102return new RSAPublicKeyImpl(type, params, n, e);103}104105/**106* Construct a RSA key from the specified type and components. Used by107* RSAKeyFactory and RSAKeyPairGenerator.108*/109RSAPublicKeyImpl(KeyType type, AlgorithmParameterSpec keyParams,110BigInteger n, BigInteger e) throws InvalidKeyException {111112RSAKeyFactory.checkRSAProviderKeyLengths(n.bitLength(), e);113checkExponentRange(n, e);114115this.n = n;116this.e = e;117118try {119// validate and generate algid encoding120algid = RSAUtil.createAlgorithmId(type, keyParams);121} catch (ProviderException pe) {122throw new InvalidKeyException(pe);123}124125this.type = type;126this.keyParams = keyParams;127128try {129// generate the key encoding130DerOutputStream out = new DerOutputStream();131out.putInteger(n);132out.putInteger(e);133byte[] keyArray =134new DerValue(DerValue.tag_Sequence,135out.toByteArray()).toByteArray();136setKey(new BitArray(keyArray.length*8, keyArray));137} catch (IOException exc) {138// should never occur139throw new InvalidKeyException(exc);140}141}142143/**144* Construct a key from its encoding.145*/146private RSAPublicKeyImpl(byte[] encoded) throws InvalidKeyException {147if (encoded == null || encoded.length == 0) {148throw new InvalidKeyException("Missing key encoding");149}150decode(encoded); // this sets n and e value151RSAKeyFactory.checkRSAProviderKeyLengths(n.bitLength(), e);152checkExponentRange(n, e);153154try {155// check the validity of oid and params156Object[] o = RSAUtil.getTypeAndParamSpec(algid);157this.type = (KeyType) o[0];158this.keyParams = (AlgorithmParameterSpec) o[1];159} catch (ProviderException e) {160throw new InvalidKeyException(e);161}162}163164// pkg private utility method for checking RSA modulus and public exponent165static void checkExponentRange(BigInteger mod, BigInteger exp)166throws InvalidKeyException {167// the exponent should be smaller than the modulus168if (exp.compareTo(mod) >= 0) {169throw new InvalidKeyException("exponent is larger than modulus");170}171172// the exponent should be at least 3173if (exp.compareTo(THREE) < 0) {174throw new InvalidKeyException("exponent is smaller than 3");175}176}177178// see JCA doc179@Override180public String getAlgorithm() {181return type.keyAlgo;182}183184// see JCA doc185@Override186public BigInteger getModulus() {187return n;188}189190// see JCA doc191@Override192public BigInteger getPublicExponent() {193return e;194}195196// see JCA doc197@Override198public AlgorithmParameterSpec getParams() {199return keyParams;200}201202// utility method for parsing DER encoding of RSA public keys in PKCS#1203// format as defined in RFC 8017 Appendix A.1.1, i.e. SEQ of n and e.204private static BigInteger[] parseASN1(byte[] raw) throws IOException {205DerValue derValue = new DerValue(raw);206if (derValue.tag != DerValue.tag_Sequence) {207throw new IOException("Not a SEQUENCE");208}209BigInteger[] result = new BigInteger[2]; // n, e210result[0] = derValue.data.getPositiveBigInteger();211result[1] = derValue.data.getPositiveBigInteger();212if (derValue.data.available() != 0) {213throw new IOException("Extra data available");214}215return result;216}217218/**219* Parse the key. Called by X509Key.220*/221protected void parseKeyBits() throws InvalidKeyException {222try {223BigInteger[] comps = parseASN1(getKey().toByteArray());224n = comps[0];225e = comps[1];226} catch (IOException e) {227throw new InvalidKeyException("Invalid RSA public key", e);228}229}230231// return a string representation of this key for debugging232@Override233public String toString() {234return "Sun " + type.keyAlgo + " public key, " + n.bitLength()235+ " bits" + "\n params: " + keyParams + "\n modulus: " + n236+ "\n public exponent: " + e;237}238239@java.io.Serial240protected Object writeReplace() throws java.io.ObjectStreamException {241return new KeyRep(KeyRep.Type.PUBLIC,242getAlgorithm(),243getFormat(),244getEncoded());245}246}247248249