Java中等同于.NET RSACryptoServiceProvider.SignData的方法

4
我目前正在创建一个签名哈希,通过使用公钥加密数据,然后使用RSACryptoServiceProvider.SignData方法进行签名。
String data = "some string here";
// **Step 1: encrypt data with public key**
Byte[] encryptedData = publicKeyRsa.Encrypt(System.Text.Encoding.UTF8.GetBytes(data), false);

// **Step 2: sign the encrypted data with private key**
Byte[] sign = privateKeyRsa.SignData(encryptedData, new SHA1CryptoServiceProvider());

// **Step 3: get hash for sign**
String signHash = System.Web.HttpServerUtility.UrlTokenEncode(sign);

我无法成功地在Java中实现相同的算法。 这是我目前拥有的。

    Base64 base64Encoder = new Base64();

    // initialize cipher to encrypt
    Cipher cipher = Cipher.getInstance("RSA");
    cipher.init(Cipher.ENCRYPT_MODE, pubKey);

    // **Step 1: encrypt data with public key**
    byte[] encBytes = cipher.doFinal(VALUE.getBytes("UTF-8"));
    byte[] encryptedData  = base64Encoder.encode(encBytes);
    String encryptedDataString = bytes2String(encryptedData);
    System.out.println("data encrypted: " + encryptedData);

    // **Step 2: sign the encrypted data with private key**
    Signature sig = Signature.getInstance("SHA1WithRSA");
    sig.initSign(privKey);
    sig.update(encryptedData);
    byte[] signData = sig.sign();

    // **Step 3: get hash for sign**
    byte[] signDataEncrypted = base64Encoder.encode(signData);
    String signDataString = bytes2String(signDataEncrypted);
    System.out.println("hash: "+signDataString);

我对bytes2String的实现来自于这里

使用java.security.Signature与MessageDigest和Cipher相比,使用SHA1和RSA

private static String bytes2String(byte[] bytes) {
    StringBuilder string = new StringBuilder();
    for (byte b : bytes) {
        String hexString = Integer.toHexString(0x00FF & b);
        string.append(hexString.length() == 1 ? "0" + hexString : hexString);
    }
    return string.toString();
}

C#代码运行完美,但Java代码未提供“正确的值”(根据服务器)。Java代码看起来正确吗?与C#代码相比,我做错了什么吗?
谢谢

这可能是RSA算法实现不匹配的问题。请在C#中编辑并添加RSA对象创建的代码。另外,您确定两个加密器都使用相同的密钥吗? - Camilo Terevinto
你是否已经在encryptedDataString或者仅在哈希值中看到了不匹配的情况? - jHilscher
@jHilscher,对于相同的值(在.NET和Java实现中),哈希和加密数据每次都不同,因此无法确认。您是否怀疑Java端与代码的.NET版本相比做错了什么? - Dexter
encryptedData = base64Encoder.encode(encBytes) - 你为什么要对加密数据进行Base64编码? - mkl
1
经过进一步的研究,我认为如果没有base64编码调用(在您的c#代码中我看不到相应的操作),加密操作看起来是正确的。为了确保,我还会明确使用块链模式和密码填充,但您不必选择BouncyCastle提供程序。 - mkl
显示剩余2条评论
1个回答

2
我终于成功地解决了这个问题。:) 感谢大家的帮助!
以下是修复的内容。
问题1: 加密算法不正确
我将加密算法从"RSA"更改为"RSA/ECB/PKCS1Padding"
问题2: bytes2String()方法
我用这个逻辑替换了我的bytes2String()方法
public String bytes2String(byte[] bytes) {
  return Base64.encodeBase64URLSafeString(bytes);
}

问题3:C#的UrlTokenEncode方法

我原以为Java和C#将对象转换为字符串的方法是相同的。实际上,C#会添加额外的填充字符,如此处所述(http://infospace.com/partners/sdk/csr/signingSample.html)。

希望这能帮到有需要的人!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接