java - C# 创建的数字签名与 Java 验证不匹配

标签 java c# rsa digital-signature

我需要在使用“SHA1withRSA”的 JAVA 程序中验证使用“SHA1”算法从 C# 创建的签名。签名字节不匹配。我正在使用 C# 程序生成的公钥来验证存储在文件中的签名。我是密码学新手。下面是创建签名的 C# 代码:

        RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();

        RSA.FromXmlString(privateKey);

        var encoder = new UTF8Encoding();
        byte[] originalData = encoder.GetBytes(message);
        SHA1 sha1 = SHA1.Create();

        byte[] signedBytes = RSA.SignData(originalData, sha1);

        return signedBytes;

我正在尝试验证 Java 程序中的签名,如下所示:

   //read xml file to get modulus and exponent bytes
            File publicKeyFileQA = new File(PUBLIC_KEY_FILE_QA);

            Map<String, BigInteger> publicKeyModulusExponentValues = DSXCRM_3YBP_Global_WebServicesUtil.readXMLFile(publicKeyFileQA);

            BigInteger publicKeyModulus = publicKeyModulusExponentValues.get("modulus");
            BigInteger publicKeyExponent = publicKeyModulusExponentValues.get("exponent");

            System.out.println("BigInteger Modulus : "+ publicKeyModulus + "BigInteger Exponent : " + publicKeyExponent);

            String messageWithSignature = (String) mapDataToPost.get("SignedMessage");
            String encryptedMessage = (String) mapDataToPost.get("EncryptedMessage");

            byte[] signatureBytes = DatatypeConverter.parseBase64Binary(messageWithSignature);

            System.out.println("Signature bytes : "+ new String(signatureBytes));


            byte[] cipherMessage = DatatypeConverter.parseBase64Binary(encryptedMessage);

            System.out.println("Cipher Message : "+ new String(cipherMessage));

            KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
            RSAPublicKeySpec publicKeySpec = new RSAPublicKeySpec(publicKeyModulus, publicKeyExponent);
            PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);
            Signature sig = Signature.getInstance("SHA1withRSA");
            sig.initVerify(publicKey); //public key of sender
            sig.update(cipherMessage);

            boolean isRightSender = sig.verify(signatureBytes);
            System.out.println("isRightSender : "+isRightSender);

但是匹配签名的结果是错误的。我不明白出了什么问题。您能否提供任何建议。是否有其他算法兼容 C# 和 JAVA 以具有相同的签名?谢谢!

最佳答案

您正在读取一个名为“SignedMessage”的字段,将其存储在名为“messageWithSignature”的变量中,然后将其视为签名。该 blob 中实际存在哪些数据?

您将进一步打印二进制数据,就好像它是文本一样(通过new String(byte[]))。您应该在两侧打印 Base64 或十六进制,以查看消息字节(在验证程序中称为 cipherMessage)和签名是否匹配。

如果您切换到静态数据(以避免读取时计算换行符之类的事情),那么这样做应该是有效的

byte[] originalData = Encoding.UTF8.GetBytes("This is a static message test.");
Console.WriteLine(Convert.ToBase64String(rsa.SignData(originalData), "SHA1"));

然后获取该输出,将其放入您的 Java 程序中并验证

byte[] originalData = "This is a static message test.".getBytes("UTF-8");
byte[] signature = Base64.getDecoder().decode(theOutputFromTheCSharpProgram);
Signature verifier = new Signature("SHA1withRSA");
verifier.initVerify(publicKey);
verifier.update(originalData);
System.out.println(verifier.verify(signature));

如果该部分不起作用,那么您一定不能在两侧忠实地表示相同的 key 。

RSA 签名的二进制格式在 C# 和 Java 中是相同的;因此,一旦数据传输排列良好,一切就应该可以正常工作。

关于java - C# 创建的数字签名与 Java 验证不匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40217186/

相关文章:

java - 性能调优 - JDBC 连接时间

java - 将字符串写入大文件

c# - 使用 subselect 优化 linq to sql 查询以获得最新结果

c++ - 使用 WinCrypt/CryptoAPI 验证基于 OpenPGP 的 RSA 签名

JavaMail - 解析电子邮件内容,似乎无法正常工作! (消息.getContent())

java - Android 中的处理程序和线程之间的区别以及处理程序是否创建单独的线程?

c# - 如何在上下文绑定(bind)对象中链接消息接收器(面向方面​​的编程)

c# - 使用错误 : the remote server returned error 530 not logged in 的 ftpWebRequest

jquery - 从 jquery 安全地调用我的 Web api

java - 解密用RSA java加密的 “long”消息