JAVA中的签名验证和签名长度

时间:2018-04-09 11:50:59

标签: java rsa digital-signature bouncycastle pem

我开发了一个java应用程序,如下所示,它从PEM文件中读取公钥,然后验证签名。我从外面(公司)收到了这个签名,它是使用RSA2048生成的。但是我收到以下错误消息:

“签名长度不正确:得到384但是期待256。”

我必须在验证前对此签名进行一些修改吗?

 package read_key_pck;

import static java.nio.charset.StandardCharsets.UTF_8;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Security;
import java.security.Signature;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

public class Main {

    //protected final static Logger LOGGER = Logger.getLogger(Main.class);

    public final static String RESOURCES_DIR = "C:\\Users\\KX5710\\eclipse-workspace\\read_key\\src\\read_key_pck\\";

    public static boolean verify(String plainText, String signature, PublicKey publicKey) throws Exception {
        Signature publicSignature = Signature.getInstance("SHA256withRSA");
        publicSignature.initVerify(publicKey);
        publicSignature.update(plainText.getBytes(UTF_8));

        byte[] signatureBytes = Base64.getDecoder().decode(signature);

        return publicSignature.verify(signatureBytes);
    }

    public static void main(String[] args) throws Exception {
        Security.addProvider(new BouncyCastleProvider());

        PublicKey pub = null;
        KeyFactory factory = KeyFactory.getInstance("RSA", "BC");
        try {
            /*PrivateKey priv = generatePrivateKey(factory, RESOURCES_DIR
                    + "id_rsa");*/


            pub = generatePublicKey(factory, RESOURCES_DIR
                    + "rsa_2048_pub.pem");

        } catch (InvalidKeySpecException e) {
            e.printStackTrace();
        }
        String encodedPublicKey = Base64.getEncoder().encodeToString(pub.getEncoded());
        System.out.println("publickey: " + encodedPublicKey);

        boolean isCorrect = verify("         5   5.00   1.80", "12c1d454cde1c3ca07f179fc3c8d1e739b482b0447cd2c60342455a10db15ee8657e73e7f9195f7e33d93db8fc1cda236d41bf2a804be0f860c16ebf952c02e89f254a19daf54b66d1383ebe5aaf049e7c48ecd33a98f771165cb8b7b0323d81508c6260109c8f622655f363bbf638802d92c985e8ab982eebc7167c979cde4755b7afcc880e32118c3e6b72eecbd0ebf680da84a59c8cc523051c3a8ec12595ec6bdc0856b9faf9562919c315e78655c8f35f759899f27d729e56a96ec8bd85fe6221441dd91f9facd5f5eadcb4b7fac08a9ddab29f18d353e6762e0769068077fea7bc94d6df405a86c9e98096e8e50e59ec7263ce6c4e88bb96ab3c663baa", pub);
        System.out.println("Signature verification: " + isCorrect);
    }

    private static PublicKey generatePublicKey(KeyFactory factory,
            String filename) throws InvalidKeySpecException,
            FileNotFoundException, IOException {
        PemFile pemFile = new PemFile(filename);
        byte[] content = pemFile.getPemObject().getContent();
        X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(content);
        return factory.generatePublic(pubKeySpec);
    }
}


package read_key_pck;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import org.bouncycastle.util.io.pem.PemObject;
import org.bouncycastle.util.io.pem.PemReader;

public class PemFile {

    private PemObject pemObject;

    public PemFile(String filename) throws FileNotFoundException, IOException {
        PemReader pemReader = new PemReader(new InputStreamReader(
                new FileInputStream(filename)));
        try {
            this.pemObject = pemReader.readPemObject();
        } finally {
            pemReader.close();
        }
    }

    public PemObject getPemObject() {
        return pemObject;
    }
}

1 个答案:

答案 0 :(得分:2)

您的签名编码为HEX而不是BASE64。 改变

byte[] signatureBytes = Base64.getDecoder().decode(signature); 

byte[] signatureBytes = DatatypeConverter.parseHexBinary(signature)