java - 使用 SHA256withRSA 签名后如何验证 signatureBytes?

标签 java cryptography digital-signature keystore public-key-encryption

我正在使用“Windows-MY”KeyStore 签署一些文本。 我想使用我的私钥签名并使用公钥验证。

KeyStore keyStore = KeyStore.getInstance("Windows-MY");
                keyStore.load(null, null); 
Enumeration en = keyStore.aliases();
while (en.hasMoreElements()) {   
    KeyStore keyStore = KeyStore.getInstance("Windows-MY");
                keyStore.load(null, null);
    String alias = en.nextElement().toString();
    X509Certificate c = (X509Certificate) keyStore.getCertificate(alias);
    String serialNumber = c.getSerialNumber().toString();
    System.out.println("--" + aliasName);
                PrivateKey privateKey = (PrivateKey) keyStore.getKey(aliasName, null);
                PublicKey publicKey = (PublicKey) c.getPublicKey();
                Certificate[] chain = keyStore.getCertificateChain(aliasName);
    DataOutputStream fout = new DataOutputStream(outstream);
    // -------------------------------------------------------
    String data = "Monika";
    byte[] content = data.getBytes();
    Provider p = keyStore.getProvider();
    // ----------------------signature---start---------------------------

    Signature signature = Signature.getInstance("SHA256withRSA", p);
    System.out.println(" signature.getProvider():"+ signature.getProvider());
    signature.initSign(privateKey);
    signature.update(content);
    byte[] signatureBytes = signature.sign();
    System.out.println("signatureBytes-------------"+ signatureBytes.toString());
    // ----------------------signature----------end------------------

    // ------------------------verification---------------
    Signature signature1 = Signature.getInstance("SHA256withRSA", p);
    System.out.println(" signature1.getProvider():"+ signature1.getProvider());
    signature1.initVerify(publicKey);
    signature1.update(content);
    boolean verifies = signature1.verify(signatureBytes);
    System.out.println("signature verifies: " + verifies);
    // ------------------------------------------------
    fout.close();
} // while

输出:

privateKey:RSAPrivateKey [size=2048 bits, type=Exchange, container=AC0BEBA9-A361-4611-96D9-B365B671FBC3]
 signature.getProvider():SunMSCAPI version 1.6
signatureBytes-------------[B@1402d5a
 signature1.getProvider():SunRsaSign version 1.5
signature verifies: false

注意:

  1. 我的私钥已经是 RSAPrivateKey 。
  2. 签名提供程序是 SunMSCAPI。
  3. 但我不知道 Provider for Verification with PrivateKey。

最佳答案

您的代码有几个问题:

  1. 您只是使用来自您的 Windows keystore 的第一个 证书/公钥。这实际上可能是正确的,但 keystore 中可能有多个证书,然后您使用哪个证书进行验证只是巧合。

    String alias = en.nextElement().toString();
    X509Certificate c = (X509Certificate) keyStore.getCertificate(alias);
    PublicKey publicKey = c.getPublicKey();
    PrivateKey privateKey = (PrivateKey) keyStore.getKey(DSCName, null);
    

    您应该改为编写 keyStore.getCertificate(DSCName) 以确保它与私钥匹配。

  2. 您正在无缘无故地生成一个 key (分别尝试转换现有 key )。您可以完全删除此代码。这也将解决您的 NullPointerException 问题:

    byte[] encodedPrivateKey = privateKey.getEncoded();
    KeyFactory keyFactory = KeyFactory.getInstance("RSA");
    PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encodedPrivateKey);
    RSAPrivateKey privateKey1 = (RSAPrivateKey) keyFactory.generatePrivate(keySpec);
    
  3. 您的问题中有很多不必要的代码,例如加载证书链,但从未使用它。这使得它更难修复。一个最小的(工作)示例如下所示:

    String alias = "myAlias";
    String myData = "data to encrypt";
    
    KeyStore keyStore = KeyStore.getInstance("Windows-MY");
    keyStore.load(null, null);
    
    X509Certificate cert = (X509Certificate) keyStore.getCertificate(alias);
    PrivateKey privateKey = (PrivateKey) keyStore.getKey(alias, null);
    PublicKey publicKey = cert.getPublicKey();
    
    Signature instance = Signature.getInstance("SHA256withRSA");
    instance.initSign(privateKey, new SecureRandom());
    instance.update(myData.getBytes("UTF-8"));
    byte[] signedBytes = instance.sign();
    
    instance.initVerify(publicKey);
    instance.update(myData.getBytes("UTF-8"));
    System.out.println(instance.verify(signedBytes));
    

关于java - 使用 SHA256withRSA 签名后如何验证 signatureBytes?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28042594/

相关文章:

java - 在Swing中获取 "fat header"背景色

security - TLS/SSL 握手中泄露了哪些信息(证书等)?

cryptography - Windows CryptoAPI : CryptSignHash with CALG_SHA_256 and private key from MY keystore

java - 使用itext从pdf中删除签名后出现"AT least one signature is invalid"错误消息

java - 从 BufferedReader (readLine) 读取返回 null?

java网络多线程

java - React Native Amplify AWS 包与 firebase 冲突

java - 存储公钥和主 key 的安全方法是什么?

linux - 我明白/dev/urandom 了吗?

postgresql - 使用 pgcrypto 库计算 postgres 数据库中存在的公共(public)证书的 x5t#s256 指纹