Path: blob/master/src/java.base/share/classes/sun/security/rsa/RSASignature.java
41159 views
/*1* Copyright (c) 2003, 2020, 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.nio.ByteBuffer;2930import java.security.*;31import java.security.interfaces.*;32import java.security.spec.AlgorithmParameterSpec;3334import sun.security.rsa.RSAUtil.KeyType;35import sun.security.util.*;36import sun.security.x509.AlgorithmId;3738/**39* PKCS#1 v1.5 RSA signatures with the various message digest algorithms.40* This file contains an abstract base class with all the logic plus41* a nested static class for each of the message digest algorithms42* (see end of the file). We support MD2, MD5, SHA-1, SHA2 family (43* SHA-224, SHA-256, SHA-384, SHA-512, SHA-512/224, and SHA-512/256),44* and SHA3 family (SHA3-224, SHA3-256, SHA3-384, SHA3-512) of digests.45*46* @since 1.547* @author Andreas Sterbenz48*/49public abstract class RSASignature extends SignatureSpi {5051// we sign an ASN.1 SEQUENCE of AlgorithmId and digest52// it has the form 30:xx:30:xx:[digestOID]:05:00:04:xx:[digest]53// this means the encoded length is (8 + digestOID.length + digest.length)54private static final int baseLength = 8;5556// object identifier for the message digest algorithm used57private final ObjectIdentifier digestOID;5859// length of the encoded signature blob60private final int encodedLength;6162// message digest implementation we use63private final MessageDigest md;64// flag indicating whether the digest is reset65private boolean digestReset;6667// private key, if initialized for signing68private RSAPrivateKey privateKey;69// public key, if initialized for verifying70private RSAPublicKey publicKey;7172// padding to use, set when the initSign/initVerify is called73private RSAPadding padding;7475/**76* Construct a new RSASignature. Used by subclasses.77*/78RSASignature(String algorithm, ObjectIdentifier digestOID, int oidLength) {79this.digestOID = digestOID;80try {81md = MessageDigest.getInstance(algorithm);82} catch (NoSuchAlgorithmException e) {83throw new ProviderException(e);84}85digestReset = true;86encodedLength = baseLength + oidLength + md.getDigestLength();87}8889// initialize for verification. See JCA doc90@Override91protected void engineInitVerify(PublicKey publicKey)92throws InvalidKeyException {93RSAPublicKey rsaKey = (RSAPublicKey)RSAKeyFactory.toRSAKey(publicKey);94this.privateKey = null;95this.publicKey = rsaKey;96initCommon(rsaKey, null);97}9899// initialize for signing. See JCA doc100@Override101protected void engineInitSign(PrivateKey privateKey)102throws InvalidKeyException {103engineInitSign(privateKey, null);104}105106// initialize for signing. See JCA doc107@Override108protected void engineInitSign(PrivateKey privateKey, SecureRandom random)109throws InvalidKeyException {110RSAPrivateKey rsaKey =111(RSAPrivateKey)RSAKeyFactory.toRSAKey(privateKey);112this.privateKey = rsaKey;113this.publicKey = null;114initCommon(rsaKey, random);115}116117/**118* Init code common to sign and verify.119*/120private void initCommon(RSAKey rsaKey, SecureRandom random)121throws InvalidKeyException {122try {123RSAUtil.checkParamsAgainstType(KeyType.RSA, rsaKey.getParams());124} catch (ProviderException e) {125throw new InvalidKeyException("Invalid key for RSA signatures", e);126}127resetDigest();128int keySize = RSACore.getByteLength(rsaKey);129try {130padding = RSAPadding.getInstance131(RSAPadding.PAD_BLOCKTYPE_1, keySize, random);132} catch (InvalidAlgorithmParameterException iape) {133throw new InvalidKeyException(iape.getMessage());134}135int maxDataSize = padding.getMaxDataSize();136if (encodedLength > maxDataSize) {137throw new InvalidKeyException138("Key is too short for this signature algorithm");139}140}141142/**143* Reset the message digest if it is not already reset.144*/145private void resetDigest() {146if (digestReset == false) {147md.reset();148digestReset = true;149}150}151152/**153* Return the message digest value.154*/155private byte[] getDigestValue() {156digestReset = true;157return md.digest();158}159160// update the signature with the plaintext data. See JCA doc161@Override162protected void engineUpdate(byte b) throws SignatureException {163md.update(b);164digestReset = false;165}166167// update the signature with the plaintext data. See JCA doc168@Override169protected void engineUpdate(byte[] b, int off, int len)170throws SignatureException {171md.update(b, off, len);172digestReset = false;173}174175// update the signature with the plaintext data. See JCA doc176@Override177protected void engineUpdate(ByteBuffer b) {178md.update(b);179digestReset = false;180}181182// sign the data and return the signature. See JCA doc183@Override184protected byte[] engineSign() throws SignatureException {185if (privateKey == null) {186throw new SignatureException("Missing private key");187}188byte[] digest = getDigestValue();189try {190byte[] encoded = encodeSignature(digestOID, digest);191byte[] padded = padding.pad(encoded);192byte[] encrypted = RSACore.rsa(padded, privateKey, true);193return encrypted;194} catch (GeneralSecurityException e) {195throw new SignatureException("Could not sign data", e);196} catch (IOException e) {197throw new SignatureException("Could not encode data", e);198}199}200201// verify the data and return the result. See JCA doc202// should be reset to the state after engineInitVerify call.203@Override204protected boolean engineVerify(byte[] sigBytes) throws SignatureException {205if (publicKey == null) {206throw new SignatureException("Missing public key");207}208try {209if (sigBytes.length != RSACore.getByteLength(publicKey)) {210throw new SignatureException("Signature length not correct: got " +211sigBytes.length + " but was expecting " +212RSACore.getByteLength(publicKey));213}214byte[] digest = getDigestValue();215byte[] decrypted = RSACore.rsa(sigBytes, publicKey);216byte[] unpadded = padding.unpad(decrypted);217byte[] decodedDigest = decodeSignature(digestOID, unpadded);218return MessageDigest.isEqual(digest, decodedDigest);219} catch (javax.crypto.BadPaddingException e) {220// occurs if the app has used the wrong RSA public key221// or if sigBytes is invalid222// return false rather than propagating the exception for223// compatibility/ease of use224return false;225} catch (IOException e) {226throw new SignatureException("Signature encoding error", e);227} finally {228resetDigest();229}230}231232/**233* Encode the digest, return the to-be-signed data.234* Also used by the PKCS#11 provider.235*/236public static byte[] encodeSignature(ObjectIdentifier oid, byte[] digest)237throws IOException {238DerOutputStream out = new DerOutputStream();239new AlgorithmId(oid).encode(out);240out.putOctetString(digest);241DerValue result =242new DerValue(DerValue.tag_Sequence, out.toByteArray());243return result.toByteArray();244}245246/**247* Decode the signature data. Verify that the object identifier matches248* and return the message digest.249*/250public static byte[] decodeSignature(ObjectIdentifier oid, byte[] sig)251throws IOException {252// Enforce strict DER checking for signatures253DerInputStream in = new DerInputStream(sig, 0, sig.length, false);254DerValue[] values = in.getSequence(2);255if ((values.length != 2) || (in.available() != 0)) {256throw new IOException("SEQUENCE length error");257}258AlgorithmId algId = AlgorithmId.parse(values[0]);259if (algId.getOID().equals(oid) == false) {260throw new IOException("ObjectIdentifier mismatch: "261+ algId.getOID());262}263if (algId.getEncodedParams() != null) {264throw new IOException("Unexpected AlgorithmId parameters");265}266byte[] digest = values[1].getOctetString();267return digest;268}269270// set parameter, not supported. See JCA doc271@Deprecated272@Override273protected void engineSetParameter(String param, Object value)274throws InvalidParameterException {275throw new UnsupportedOperationException("setParameter() not supported");276}277278// See JCA doc279@Override280protected void engineSetParameter(AlgorithmParameterSpec params)281throws InvalidAlgorithmParameterException {282if (params != null) {283throw new InvalidAlgorithmParameterException("No parameters accepted");284}285}286287// get parameter, not supported. See JCA doc288@Deprecated289@Override290protected Object engineGetParameter(String param)291throws InvalidParameterException {292throw new UnsupportedOperationException("getParameter() not supported");293}294295// See JCA doc296@Override297protected AlgorithmParameters engineGetParameters() {298return null;299}300301// Nested class for MD2withRSA signatures302public static final class MD2withRSA extends RSASignature {303public MD2withRSA() {304super("MD2", AlgorithmId.MD2_oid, 10);305}306}307308// Nested class for MD5withRSA signatures309public static final class MD5withRSA extends RSASignature {310public MD5withRSA() {311super("MD5", AlgorithmId.MD5_oid, 10);312}313}314315// Nested class for SHA1withRSA signatures316public static final class SHA1withRSA extends RSASignature {317public SHA1withRSA() {318super("SHA-1", AlgorithmId.SHA_oid, 7);319}320}321322// Nested class for SHA224withRSA signatures323public static final class SHA224withRSA extends RSASignature {324public SHA224withRSA() {325super("SHA-224", AlgorithmId.SHA224_oid, 11);326}327}328329// Nested class for SHA256withRSA signatures330public static final class SHA256withRSA extends RSASignature {331public SHA256withRSA() {332super("SHA-256", AlgorithmId.SHA256_oid, 11);333}334}335336// Nested class for SHA384withRSA signatures337public static final class SHA384withRSA extends RSASignature {338public SHA384withRSA() {339super("SHA-384", AlgorithmId.SHA384_oid, 11);340}341}342343// Nested class for SHA512withRSA signatures344public static final class SHA512withRSA extends RSASignature {345public SHA512withRSA() {346super("SHA-512", AlgorithmId.SHA512_oid, 11);347}348}349350// Nested class for SHA512/224withRSA signatures351public static final class SHA512_224withRSA extends RSASignature {352public SHA512_224withRSA() {353super("SHA-512/224", AlgorithmId.SHA512_224_oid, 11);354}355}356357// Nested class for SHA512/256withRSA signatures358public static final class SHA512_256withRSA extends RSASignature {359public SHA512_256withRSA() {360super("SHA-512/256", AlgorithmId.SHA512_256_oid, 11);361}362}363364// Nested class for SHA3-224withRSA signatures365public static final class SHA3_224withRSA extends RSASignature {366public SHA3_224withRSA() {367super("SHA3-224", AlgorithmId.SHA3_224_oid, 11);368}369}370371// Nested class for SHA3-256withRSA signatures372public static final class SHA3_256withRSA extends RSASignature {373public SHA3_256withRSA() {374super("SHA3-256", AlgorithmId.SHA3_256_oid, 11);375}376}377378// Nested class for SHA3-384withRSA signatures379public static final class SHA3_384withRSA extends RSASignature {380public SHA3_384withRSA() {381super("SHA3-384", AlgorithmId.SHA3_384_oid, 11);382}383}384385// Nested class for SHA3-512withRSA signatures386public static final class SHA3_512withRSA extends RSASignature {387public SHA3_512withRSA() {388super("SHA3-512", AlgorithmId.SHA3_512_oid, 11);389}390}391}392393394