0N/A/*
3002N/A * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/Apackage sun.security.rsa;
0N/A
0N/Aimport java.io.IOException;
0N/Aimport java.nio.ByteBuffer;
0N/Aimport java.math.BigInteger;
0N/Aimport java.util.Arrays;
0N/A
0N/Aimport java.security.*;
0N/Aimport java.security.interfaces.*;
0N/A
0N/Aimport sun.security.util.*;
0N/Aimport sun.security.x509.AlgorithmId;
0N/A
0N/A/**
0N/A * PKCS#1 RSA signatures with the various message digest algorithms.
0N/A * This file contains an abstract base class with all the logic plus
0N/A * a nested static class for each of the message digest algorithms
0N/A * (see end of the file). We support MD2, MD5, SHA-1, SHA-256, SHA-384,
0N/A * and SHA-512.
0N/A *
0N/A * @since 1.5
0N/A * @author Andreas Sterbenz
0N/A */
0N/Apublic abstract class RSASignature extends SignatureSpi {
0N/A
0N/A // we sign an ASN.1 SEQUENCE of AlgorithmId and digest
3002N/A // it has the form 30:xx:30:xx:[digestOID]:05:00:04:xx:[digest]
0N/A // this means the encoded length is (8 + digestOID.length + digest.length)
0N/A private static final int baseLength = 8;
0N/A
0N/A // object identifier for the message digest algorithm used
0N/A private final ObjectIdentifier digestOID;
0N/A
0N/A // length of the encoded signature blob
0N/A private final int encodedLength;
0N/A
0N/A // message digest implementation we use
0N/A private final MessageDigest md;
0N/A // flag indicating whether the digest is reset
0N/A private boolean digestReset;
0N/A
0N/A // private key, if initialized for signing
0N/A private RSAPrivateKey privateKey;
0N/A // public key, if initialized for verifying
0N/A private RSAPublicKey publicKey;
0N/A
0N/A // padding to use, set when the initSign/initVerify is called
0N/A private RSAPadding padding;
0N/A
0N/A /**
0N/A * Construct a new RSASignature. Used by subclasses.
0N/A */
0N/A RSASignature(String algorithm, ObjectIdentifier digestOID, int oidLength) {
0N/A this.digestOID = digestOID;
0N/A try {
0N/A md = MessageDigest.getInstance(algorithm);
0N/A } catch (NoSuchAlgorithmException e) {
0N/A throw new ProviderException(e);
0N/A }
0N/A digestReset = true;
0N/A encodedLength = baseLength + oidLength + md.getDigestLength();
0N/A }
0N/A
0N/A // initialize for verification. See JCA doc
0N/A protected void engineInitVerify(PublicKey publicKey)
0N/A throws InvalidKeyException {
0N/A RSAPublicKey rsaKey = (RSAPublicKey)RSAKeyFactory.toRSAKey(publicKey);
0N/A this.privateKey = null;
0N/A this.publicKey = rsaKey;
0N/A initCommon(rsaKey, null);
0N/A }
0N/A
0N/A // initialize for signing. See JCA doc
0N/A protected void engineInitSign(PrivateKey privateKey)
0N/A throws InvalidKeyException {
0N/A engineInitSign(privateKey, null);
0N/A }
0N/A
0N/A // initialize for signing. See JCA doc
0N/A protected void engineInitSign(PrivateKey privateKey, SecureRandom random)
0N/A throws InvalidKeyException {
3002N/A RSAPrivateKey rsaKey =
3002N/A (RSAPrivateKey)RSAKeyFactory.toRSAKey(privateKey);
0N/A this.privateKey = rsaKey;
0N/A this.publicKey = null;
0N/A initCommon(rsaKey, random);
0N/A }
0N/A
0N/A /**
0N/A * Init code common to sign and verify.
0N/A */
0N/A private void initCommon(RSAKey rsaKey, SecureRandom random)
0N/A throws InvalidKeyException {
0N/A resetDigest();
0N/A int keySize = RSACore.getByteLength(rsaKey);
0N/A try {
0N/A padding = RSAPadding.getInstance
0N/A (RSAPadding.PAD_BLOCKTYPE_1, keySize, random);
0N/A } catch (InvalidAlgorithmParameterException iape) {
0N/A throw new InvalidKeyException(iape.getMessage());
0N/A }
0N/A int maxDataSize = padding.getMaxDataSize();
0N/A if (encodedLength > maxDataSize) {
0N/A throw new InvalidKeyException
0N/A ("Key is too short for this signature algorithm");
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Reset the message digest if it is not already reset.
0N/A */
0N/A private void resetDigest() {
0N/A if (digestReset == false) {
0N/A md.reset();
0N/A digestReset = true;
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Return the message digest value.
0N/A */
0N/A private byte[] getDigestValue() {
0N/A digestReset = true;
0N/A return md.digest();
0N/A }
0N/A
0N/A // update the signature with the plaintext data. See JCA doc
0N/A protected void engineUpdate(byte b) throws SignatureException {
0N/A md.update(b);
0N/A digestReset = false;
0N/A }
0N/A
0N/A // update the signature with the plaintext data. See JCA doc
0N/A protected void engineUpdate(byte[] b, int off, int len)
0N/A throws SignatureException {
0N/A md.update(b, off, len);
0N/A digestReset = false;
0N/A }
0N/A
0N/A // update the signature with the plaintext data. See JCA doc
0N/A protected void engineUpdate(ByteBuffer b) {
0N/A md.update(b);
0N/A digestReset = false;
0N/A }
0N/A
0N/A // sign the data and return the signature. See JCA doc
0N/A protected byte[] engineSign() throws SignatureException {
0N/A byte[] digest = getDigestValue();
0N/A try {
0N/A byte[] encoded = encodeSignature(digestOID, digest);
0N/A byte[] padded = padding.pad(encoded);
0N/A byte[] encrypted = RSACore.rsa(padded, privateKey);
0N/A return encrypted;
0N/A } catch (GeneralSecurityException e) {
0N/A throw new SignatureException("Could not sign data", e);
0N/A } catch (IOException e) {
0N/A throw new SignatureException("Could not encode data", e);
0N/A }
0N/A }
0N/A
0N/A // verify the data and return the result. See JCA doc
0N/A protected boolean engineVerify(byte[] sigBytes) throws SignatureException {
3211N/A if (sigBytes.length != RSACore.getByteLength(publicKey)) {
3211N/A throw new SignatureException("Signature length not correct: got " +
3211N/A sigBytes.length + " but was expecting " +
3211N/A RSACore.getByteLength(publicKey));
3211N/A }
0N/A byte[] digest = getDigestValue();
0N/A try {
0N/A byte[] decrypted = RSACore.rsa(sigBytes, publicKey);
0N/A byte[] unpadded = padding.unpad(decrypted);
0N/A byte[] decodedDigest = decodeSignature(digestOID, unpadded);
0N/A return Arrays.equals(digest, decodedDigest);
0N/A } catch (javax.crypto.BadPaddingException e) {
0N/A // occurs if the app has used the wrong RSA public key
0N/A // or if sigBytes is invalid
0N/A // return false rather than propagating the exception for
0N/A // compatibility/ease of use
0N/A return false;
0N/A } catch (GeneralSecurityException e) {
0N/A throw new SignatureException("Signature verification failed", e);
0N/A } catch (IOException e) {
0N/A throw new SignatureException("Signature encoding error", e);
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Encode the digest, return the to-be-signed data.
0N/A * Also used by the PKCS#11 provider.
0N/A */
0N/A public static byte[] encodeSignature(ObjectIdentifier oid, byte[] digest)
0N/A throws IOException {
0N/A DerOutputStream out = new DerOutputStream();
0N/A new AlgorithmId(oid).encode(out);
0N/A out.putOctetString(digest);
3002N/A DerValue result =
3002N/A new DerValue(DerValue.tag_Sequence, out.toByteArray());
0N/A return result.toByteArray();
0N/A }
0N/A
0N/A /**
0N/A * Decode the signature data. Verify that the object identifier matches
0N/A * and return the message digest.
0N/A */
0N/A public static byte[] decodeSignature(ObjectIdentifier oid, byte[] signature)
0N/A throws IOException {
0N/A DerInputStream in = new DerInputStream(signature);
0N/A DerValue[] values = in.getSequence(2);
0N/A if ((values.length != 2) || (in.available() != 0)) {
0N/A throw new IOException("SEQUENCE length error");
0N/A }
0N/A AlgorithmId algId = AlgorithmId.parse(values[0]);
0N/A if (algId.getOID().equals(oid) == false) {
3002N/A throw new IOException("ObjectIdentifier mismatch: "
3002N/A + algId.getOID());
0N/A }
0N/A if (algId.getEncodedParams() != null) {
0N/A throw new IOException("Unexpected AlgorithmId parameters");
0N/A }
0N/A byte[] digest = values[1].getOctetString();
0N/A return digest;
0N/A }
0N/A
0N/A // set parameter, not supported. See JCA doc
0N/A protected void engineSetParameter(String param, Object value)
0N/A throws InvalidParameterException {
0N/A throw new UnsupportedOperationException("setParameter() not supported");
0N/A }
0N/A
0N/A // get parameter, not supported. See JCA doc
0N/A protected Object engineGetParameter(String param)
0N/A throws InvalidParameterException {
0N/A throw new UnsupportedOperationException("getParameter() not supported");
0N/A }
0N/A
0N/A // Nested class for MD2withRSA signatures
0N/A public static final class MD2withRSA extends RSASignature {
0N/A public MD2withRSA() {
0N/A super("MD2", AlgorithmId.MD2_oid, 10);
0N/A }
0N/A }
0N/A
0N/A // Nested class for MD5withRSA signatures
0N/A public static final class MD5withRSA extends RSASignature {
0N/A public MD5withRSA() {
0N/A super("MD5", AlgorithmId.MD5_oid, 10);
0N/A }
0N/A }
0N/A
0N/A // Nested class for SHA1withRSA signatures
0N/A public static final class SHA1withRSA extends RSASignature {
0N/A public SHA1withRSA() {
0N/A super("SHA-1", AlgorithmId.SHA_oid, 7);
0N/A }
0N/A }
0N/A
0N/A // Nested class for SHA256withRSA signatures
0N/A public static final class SHA256withRSA extends RSASignature {
0N/A public SHA256withRSA() {
0N/A super("SHA-256", AlgorithmId.SHA256_oid, 11);
0N/A }
0N/A }
0N/A
0N/A // Nested class for SHA384withRSA signatures
0N/A public static final class SHA384withRSA extends RSASignature {
0N/A public SHA384withRSA() {
0N/A super("SHA-384", AlgorithmId.SHA384_oid, 11);
0N/A }
0N/A }
0N/A
0N/A // Nested class for SHA512withRSA signatures
0N/A public static final class SHA512withRSA extends RSASignature {
0N/A public SHA512withRSA() {
0N/A super("SHA-512", AlgorithmId.SHA512_oid, 11);
0N/A }
0N/A }
0N/A
0N/A}