在Java中,如何基于数据进行签名,但如何基于哈希进行验证?

在Java中,如何基于数据进行签名,但如何基于哈希进行验证?,java,hash,cryptography,Java,Hash,Cryptography,如何根据数据计算RSA签名,但根据数据的散列验证该签名(和/或反之亦然)?在内部对数据进行签名/验证只是对该数据进行散列,然后在散列上进行操作,在其他平台上我可以完成这一点。但在Java中,我想我似乎无法正确配置签名算法 如何仅使用数据的散列来验证签名 以下是我所拥有的: import java.security.*; public class Main { public static void main(String[] args) throws Exception {

如何根据数据计算RSA签名,但根据数据的散列验证该签名(和/或反之亦然)?在内部对数据进行签名/验证只是对该数据进行散列,然后在散列上进行操作,在其他平台上我可以完成这一点。但在Java中,我想我似乎无法正确配置签名算法

如何仅使用数据的散列来验证签名

以下是我所拥有的:

import java.security.*;

public class Main {
    public static void main(String[] args) throws Exception
    {
        byte[] data = new byte[] {1,2,3};

        MessageDigest digest = MessageDigest.getInstance("SHA1");
        digest.update(data);
        byte[] sha1Hash = digest.digest();

        KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
        kpg.initialize(512);
        KeyPair keyPair = kpg.genKeyPair();

        Signature signingInstance = Signature.getInstance("SHA1withRSA");
        signingInstance.initSign(keyPair.getPrivate());
        signingInstance.update(data);
        byte[] signature = signingInstance.sign();

        Signature dataVerifyingInstance = Signature.getInstance("SHA1withRSA");
        dataVerifyingInstance.initVerify(keyPair.getPublic());
        dataVerifyingInstance.update(data);
        boolean dataVerified = dataVerifyingInstance.verify(signature);

        Signature hashVerifyingInstance = Signature.getInstance("NONEwithRSA");
        hashVerifyingInstance.initVerify(keyPair.getPublic());
        hashVerifyingInstance.update(sha1Hash);
        boolean hashVerified = hashVerifyingInstance.verify(signature);

        System.out.println("Verification based on data: " + dataVerified);
        System.out.println("Verification based on hash: " + hashVerified);
    }
}
运行此程序的输出为:

Verification based on data: true
Verification based on hash: false

您必须首先实现围绕哈希值构建的PKCS#1 v1.5填充(正式命名)。只有在这之后,
“NONEwithRSA”
的技巧才能发挥作用

当然,你可以作弊并查看BouncyCastle的源代码或Java的GPL版本。或者,您可以使用BouncyCastle轻量级API,但您将失去与JCA的兼容性,并添加一个依赖项


JavaCard
确实具有创建散列卡的功能。在功能齐全的PC机上运行的库中不需要这种功能(我在Java 7类中也找不到这种功能)。

为什么不签名哈希呢?我可以。但是,当一方签名,另一方验证时,各方应该能够独立选择如何签名或验证数据。为什么?各方应就数据的签名、验证、散列、加密、格式化、存储和其他任何方式达成一致。关键是,数据应该独立于协议。各方没有理由必须同意是对散列本身进行签名,还是对数据进行散列签名,因为这是同一件事。我的代码应该有用。在其他平台上也是如此。历史:在当时,v1.5(用于签名或用于加密的不同版本)是行业标准PKCS#1文档中使用的唯一填充模式。因此,用于签名生成的RSA被简单地称为“[HASH]withRSA”,而实际上它是“[HASH]withPKCSV1_5andRSA”。新的/更好的PSS方案通过添加配置选项使这一点复杂化。这可以解释当我用公钥“加密”签名时,我在结果的索引16处发现了哈希值。这与您链接到的文档一致。谢谢