2010-05-28 148 views
1

在我的程序(服务器端 - JAVA)我创建密钥库文件,使用命令:RSA C#加密的Java解密

keytool -genkey -alias myalias -keyalg RSA -validity 10000 -keystore my.keystore 

和出口相关的X509证书有:

keytool -export -alias myalias -file cert.cer -keystore my.keystore 

后,我在客户端(C#)保存cert.cer和我写这篇文章的代码:

X509Certificate2 x509 = new X509Certificate2(); 
byte[] rawData = ReadFile("mycert.cer"); 
x509.Import(rawData); 

RSACryptoServiceProvider rsa = (RSACryptoServiceProvider)x509.PublicKey.Key; 
byte[] plainbytes = System.Text.Encoding.ASCII.GetBytes("My Secret"); 
byte[] cipherbytes = rsa.Encrypt(plainbytes, true); 
String cipherHex = convertToHex(cipherContent); 
byte[] byteArray = encoding.GetBytes(cipherHex); 

.... 

我写在服务器端解决此Java代码:

keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); 
keyStore.load(new FileInputStream("C:\\my.keystore"), "mypass".toCharArray()); 
Key key = keyStore.getKey("myalias", "mypass".toCharArray()); 
if (key instanceof PrivateKey) { 
    Certificate cert = keyStore.getCertificate("myalias"); 
    PublicKey pubKey = cert.getPublicKey(); 
    privKey = (PrivateKey)key; 
} 
byte[] toDecodeBytes = new BigInteger(encodeMessageHex, 16).toByteArray(); 
Cipher decCipher = Cipher.getInstance("RSA"); 
decCipher.init(Cipher.DECRYPT_MODE, privKey); 
byte[] decodeMessageBytes = decCipher.doFinal(toDecodeBytes); 
String decodeMessageString = new String(decodeMessageBytes); 

我收到此错误:

javax.crypto.BadPaddingException: Data must start with zero 

你能帮助我吗? 谢谢,

回答

1

你在Java中己解码的方法,使用的BigInteger因为Java的BigInteger类编码具有这样的额外其高位字节是值> = 128将产生错误的结果大部分时间零字节在前面。使用Apache公共编解码器进行十六进制编码/解码。

编辑:你的C#代码是不正确的。有一个.NET类System.Runtime.Remoting.Metadata.W3cXsd2001.SoapHexBinary,将执行您的C#代码的十六进制编码/解码。下面的C#代码片段应该更好地工作

public static String execute(String content) 
{ 
    ASCIIEncoding encoding = new ASCIIEncoding(); 
    byte[] plainbytes = System.Text.Encoding.ASCII.GetBytes(content); 
    byte[] cipherbytes = rsa.Encrypt(plainbytes, false); 
    SoapHexBinary hexBinary = new SoapHexBinary(cipherbytes); 
    String cipherHex = hexBinary.ToString(); 

    // This String is used on java side to decrypt 
    Console.WriteLine("CIPHER HEX: " + cipherHex); 
    return cipherHex; 
} 

编辑2:

似乎SoapHexBinary类可能不得不在.NET中的一个短暂的生命。在this msdn link有很多很好的解决方案。

+0

您好GregS,感谢您的回答。 我在java中使用了Apache Commons Codec,但我不知道我可以在哪里下载这些用于C#端的地方,我在那里加密我的数据。我尝试在Java端(服务器)上更改这一行: Cipher decCipher = Cipher.getInstance(“RSA”); 与: 密码decCipher = Cipher.getInstance(“RSA/ECB/NoPadding”); 在这种情况下,我没有收到一些例外情况,但字符串解码与原来的完全不同。你可以帮我吗? 谢谢 – CeccoCQ 2010-05-29 08:54:52

+0

你不应该在C#端需要任何东西,假设convertToHex是正确的。在Java方面,正确的填充应该是OAEP填充之一,我不确定哪一个填充。尝试OAEPWITHSHA1ANDMGF1PADDING – 2010-05-29 12:40:26

+0

感谢GregS,我试试这个方法;) 一个问题:如果我改变这一行byte [] cipherbytes = rsa.Encrypt(plainbytes,true)in byte [] cipherbytes = rsa.Encrypt(plainbytes,false)一个PKCS1 v1.5对不对? 我如何在java端管理这个?谢谢 – CeccoCQ 2010-05-29 12:51:32

1

嗯,我还没有完全做你在这里,我有一个我必须做的DES,我得到了同样的错误。诀窍是我必须在两边兼容CipherModes和PaddingModes。对于我的是cSharp端的PaddingMode.PKCS7和CipherMode.CBC,而在java端,我使用了DESede/CBC/PKCS5Padding xform。

HTH 麦克

+0

你是对的。代码不应该依赖模式和填充的默认值。这些应该总是明确的定义。 – laz 2010-05-28 18:07:36

+0

噢耶拉兹:) 但是,我可以设置我的值我在使用RSA算法时在C#端填充和CipherMode? 在我的代码中,我尝试设置RSA/ECB/NoPadding,但我没有收到一些例外,但是我的字符串与原始字符完全不同。 我该如何解决我的问题? 谢谢 – CeccoCQ 2010-05-29 08:58:03

0

感谢GregS的回答,我找到了我的问题的解决方案。现在我发布这个。

C#SIDE(客户端)我加载我的x509证书我打电话给我的执行方法

X509Certificate2 x509 = new X509Certificate2(); 
byte[] rawData = ReadFile("mycert.cer"); 
x509.Import(rawData); 

后:

public static String execute(String content) 
{ 
    ASCIIEncoding encoding = new ASCIIEncoding(); 
    byte[] plainbytes = System.Text.Encoding.ASCII.GetBytes(content); 
    byte[] cipherbytes = rsa.Encrypt(plainbytes, false); 
    SoapHexBinary hexBinary = new SoapHexBinary(cipherbytes); 
    String cipherHex = hexBinary.ToString(); 

    // This String is used on java side to decrypt 
    Console.WriteLine("CIPHER HEX: " + cipherHex); 
    return cipherHex; 
} 

Java方面(服务器端)

keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); 
keyStore.load(new FileInputStream("C:\\my.keystore"), "mypass".toCharArray()); 
Key key = keyStore.getKey("myalias", "mypass".toCharArray()); 
if (key instanceof PrivateKey) { 
    Certificate cert = keyStore.getCertificate("myalias"); 
    PublicKey pubKey = cert.getPublicKey(); 
    privKey = (PrivateKey)key; 
} 
byte[] toDecodeBytes = new BigInteger(encodeMessageHex, 16).toByteArray(); 
Cipher decCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); 
decCipher.init(Cipher.DECRYPT_MODE, privKey); 
byte[] decodeMessageBytes = decCipher.doFinal(toDecodeBytes); 
String decodeMessageString = new String(decodeMessageBytes); 

该pr问题在C#端的Hex-Encryption中,在Java端完全不同。谢谢GregS,你是最棒的;)