2013-08-19 46 views
1

我不是密码学方面的专家,当我使用下面的加密方法时,我得到了一些有趣的结果。在JAVA中带负号的RSA结果

服务器是.NET C#,客户端运行JAVA。基本上,我们对信用卡信息进行了加密,对于我拥有的12张信用卡,11款信用卡完全符合以下方法。

然而,卡(实VISA信用卡)的结果通过encrypt()返回,并转换为十六进制一个人在字符串的开头一个负号,这样的:

-6d9830a52b2c3add7a78fd9897bca19d.....,它失败的服务器时,试图解密它,我认为它应该在此基础上解释RSA - Encryption with negative exponent

  private static byte[] encrypt(String text, PublicKey pubRSA) throws Exception 
      { 
      Cipher cipher = Cipher.getInstance(RSA); 
      cipher.init(Cipher.ENCRYPT_MODE, pubRSA); 
      return cipher.doFinal(text.getBytes()); 
      } 

      //Using this encryption method one card could not be decrypted by vPAY due to negative (exponential) symbol. 
      //It may have the same affect with other cards 
      public final static byte[] encrypt(String text) 
      { 
      try { 

       KeyFactory keyFactory = KeyFactory.getInstance("RSA"); 
       X509EncodedKeySpec x509Spec = new X509EncodedKeySpec(Base64.decode(pkBase64)); 
       PublicKey pk = keyFactory.generatePublic(x509Spec); 

       return encrypt(text, pk); 
      } 
      catch(Exception e) 
      { 
       e.printStackTrace(); 
      } 
      return null; 
      } 

有没有人遇到类似的东西,发现一个解决办法是积极的不是消极的? 我已经尝试过其他三种算法不同KeySpec和相同的公钥(源为Base64格式的字符串),但没有人可以由服务器甚至与之前,工作卡被解密...

UPDATE 1

这是如何一个转换的加密结果在字节HEX:

  public static String byteToHex(byte[] string) 
       { 
        try { 
         return String.format("%04x", new BigInteger(string)); 
        } catch (Exception e) { 
         // TODO Auto-generated catch block 
         return null; 
        } 
       } 
+0

你如何转换为十六进制?字节被签名为Java。在将其转换为十六进制字符串之前,您可能需要在int中获取无符号值(http://stackoverflow.com/questions/4266756/can-we-make-unsigned-byte-in-java)。 – Kazaag

+0

@Kazaag感谢您的关注....请参阅“更新1”。 – Devester

回答

3

您应该直接从byte[]打印出十六进制字符串。这可以使用以下代码完成:

StringBuilder sb = new StringBuilder(data.length * 2); 
for (int i = 0; i < data.length; i++) { 
    sb.append(String.format("%02X", data[i] & 0xFF)); 
} 
return sb.toString(); 

没有必要使用BigInteger。事实上,使用BigInteger是危险的。其中一个原因是您已经遇到的问题:BigInteger转换为byte[]的转换默认使用带符号的大端编码。另一件事是RSA签名的输出(整数)可能是小于的模数大小(十六进制数)。这就是为什么EJP的解决方案会不时失败的原因。

RSA输出已经以字节定义为一个无符号的大端编码,其编码方式与密钥大小相同(使用标准文档中的八位字节字符串编码整数)。

2

公共静态字符串byteToHex(字节[]串)

A byte[]不是字符串。这是一个字节数组。不要将自己与不适当的变量名称混淆。字符串不是二进制数据的容器。

return String.format("%04x", new BigInteger(string)); 

尝试return new BigInteger(1,string).toString(16),,有一个看的Javadoc,看看为什么这个工程时new BigInteger(string)没有。

+2

这并不总是有效。 BigInteger输出可能小于RSA加密的输出。所以你会错过开始零。没有必要转换成BigInteger或从BigInteger转换。 –