使用C#CryptoStream的Java等价物加密和解密字符串

我正在寻找用Java开发移动平台操作系统的应用程序。

我已经在C#WPF中为Windows环境开发了一个应用程序。 我正在使用cryptostream来使用以下代码加密和解密字符串。 下面显示的代码只是加密

public string encrypt(string encryptionString) { byte[] clearTextBytes = Encoding.UTF8.GetBytes(encryptionString); SymmetricAlgorithm rijn = SymmetricAlgorithm.Create(); MemoryStream ms = new MemoryStream(); byte[] rgbIV = Encoding.ASCII.GetBytes("ryojvlzmdalyglrj"); byte[] key = Encoding.ASCII.GetBytes("hcxilkqbbhczfeultgbskdmaunivmfuo"); CryptoStream cs = new CryptoStream(ms, rijn.CreateEncryptor(key, rgbIV), CryptoStreamMode.Write); cs.Write(clearTextBytes, 0, clearTextBytes.Length); cs.Close(); return Convert.ToBase64String(ms.ToArray()); } 

加密的字符串存储在在线数据库中。 我需要做的是让java应用程序能够从数据库中读取字符串并使用C#应用程序中的相同加密密钥解密字符串。

谢谢你的帮助。

就个人而言,我喜欢BouncyCastle for Java加密。 这段代码(使用BouncyCastle轻量级API)可以解决这个问题:

 String decrypt(byte[] cryptoBytes, byte[] key, byte[] iv) { BlockCipher cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(new AESEngine())); cipher.init(false, new ParametersWithIV(new KeyParameter(key), iv)); byte[] out = new byte[cipher.getOutputSize(cryptoBytes.length)]; int offset = cipher.processBytes(cryptoBytes, 0, cryptoBytes.length, out, 0); cipher.doFinal(out, offset); return new String(out); } 

我发现BouncyCastle的轻量级API比JCE提供程序的东西更少痛苦,但如果你愿意,可以将它作为提供者使用。

看起来.net SymmetricAlgorithm和BC的PaddedBufferedBlockCipher默认为PKCS7填充,所以你应该可以使用默认值。

您可能想要查看javax.crypto.CipherInputStream和javax.crypto.CipherOutputStream。

http://download.oracle.com/javase/1.5.0/docs/api/javax/crypto/CipherInputStream.html http://download.oracle.com/javase/1.5.0/docs/api/javax/crypto /CipherOutputStream.html

尽管Cipher对象的初始化可能略有不同,但它们的使用方式几乎与上面的示例完全相同。

我使用以下内容在.net和java之间进行加密

在.net中我使用:

  ///  /// DES Encryption method - used to encryp password for the java. ///  ///  ///  public string EncryptData(string plainText) { DES des = new DESCryptoServiceProvider(); des.Mode = CipherMode.ECB; des.Padding = PaddingMode.PKCS7; des.Key = Encoding.UTF8.GetBytes(_secretPhrase.Substring(0, 8)); des.IV = Encoding.UTF8.GetBytes(_secretPhrase.Substring(0, 8)); byte[] bytes = Encoding.UTF8.GetBytes(plainText); byte[] resultBytes = des.CreateEncryptor().TransformFinalBlock(bytes, 0, bytes.Length); return Convert.ToBase64String(resultBytes); } ///  /// DES Decryption method - used the decrypt password encrypted in java ///  ///  ///  public string DecryptData(string encryptedText) { DES des = new DESCryptoServiceProvider(); des.Mode = CipherMode.ECB; des.Padding = PaddingMode.PKCS7; des.Key = Encoding.UTF8.GetBytes(_secretPhrase.Substring(0, 8)); des.IV = System.Text.Encoding.UTF8.GetBytes(_secretPhrase.Substring(0, 8)); byte[] bytes = Convert.FromBase64String(encryptedText); byte[] resultBytes = des.CreateDecryptor().TransformFinalBlock(bytes, 0, bytes.Length); return Encoding.UTF8.GetString(resultBytes); } 

在java中我使用:

public class CryptoUtil {

 public static final Logger LOG = Logger.getLogger(CryptoUtil.class); private Cipher cipher = null; private SecretKey key = null; // This variable holds a string based on which a unique key will be generated private static final String SECRET_PHRASE = "SECRET PHRASE GOES HERE"; // Charset will be used to convert between String and ByteArray private static final String CHARSET = "UTF8"; // The algorithm to be used for encryption/decryption DES(Data Encryption Standard) private static final String ALGORITHM = "DES"; public CryptoUtil() throws DDICryptoException { try { // generate a key from SecretKeyFactory DESKeySpec keySpec = new DESKeySpec(SECRET_PHRASE.getBytes(CHARSET)); SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM); key = keyFactory.generateSecret(keySpec); cipher = Cipher.getInstance(ALGORITHM); } catch (Exception e) { LOG.error(e); throw new DDICryptoException(e); } } /** * This method takes a plain text string and returns encrypted string using DES algorithm * @param plainText * @return String * @throws DDICryptoException */ public String encrypt(String plainText) throws DDICryptoException { String encryptedString = null; try { // initializes the cipher with a key. cipher.init(Cipher.ENCRYPT_MODE, key); byte[] plainTextAsUTF8 = plainText.getBytes(CHARSET); // decrypts data in a single-part or multi-part operation byte[] encryptedBytes = cipher.doFinal(plainTextAsUTF8); encryptedString = new sun.misc.BASE64Encoder().encode(encryptedBytes); } catch (Exception e) { LOG.error(e); throw new DDICryptoException(e); } return encryptedString; } /** * This method takes a plain text string and returns encrypted string using DES algorithm * @param encryptedString * @return * @throws DDICryptoException */ public String decrypt(String encryptedString) throws DDICryptoException { String decryptedString = null; try { byte[] decodedString = new sun.misc.BASE64Decoder().decodeBuffer(encryptedString); // initializes the cipher with a key. cipher.init(Cipher.DECRYPT_MODE, key); // decrypts data in a single-part or multi-part operation byte[] decryptedBytes = cipher.doFinal(decodedString); decryptedString = new String(decryptedBytes, CHARSET); } catch (Exception e) { LOG.error(e); throw new DDICryptoException(e); } return decryptedString; } 

}

我有点设法解决这个问题。 解密现在工作正常。 使用以下代码

  String plainPassword = ""; try { SecretKeySpec key = new SecretKeySpec("hcxilkqbbhczfeultgbskdmaunivmfuo".getBytes("US-ASCII"), "AES"); IvParameterSpec iv = new IvParameterSpec("ryojvlzmdalyglrj".getBytes("US_ASCII")); Cipher cipher = Cipher.getInsta nce("AES/CBC/PKCS7Padding"); cipher.init(Cipher.DECRYPT_MODE, key, iv); byte[] encoded = cipher.doFinal(Base64.decodeBase64(encryptedPassword.getBytes())); plainPassword = new String(encoded); } catch (Exception ex) { Log.d("Decryption Error", ex.toString()); } return plainPassword; 

现在的问题是加密。 我使用相同的代码,除了将密码从解密模式更改为加密模式,但由于某种原因,当我打印出加密的字符串时,它只打印出一堆垃圾,与C#创建的字符串完全不同。 下面是加密的代码

 public String encrypt(String plainPasword) { String password = ""; try { SecretKeySpec key = new SecretKeySpec("hcxilkqbbhczfeultgbskdmaunivmfuo".getBytes("US-ASCII"), "AES"); IvParameterSpec iv = new IvParameterSpec("ryojvlzmdalyglrj".getBytes("US_ASCII")); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding"); cipher.init(Cipher.ENCRYPT_MODE, key, iv); byte[] encoded = cipher.doFinal(plainPasword.getBytes()); password = new String(encoded); } catch (Exception ex) { Log.d("Encryption Error", ex.toString()); } return password; } 

这个似乎有什么问题我无法解决这个问题。 谢谢

  StringBuffer strbuf = new StringBuffer(buf.length * 2); int i; for (i = 0; i < buf.length; i++) { if (((int) buf[i] & 0xff) < 0x10) { strbuf.append("0"); } strbuf.append(Long.toString((int) buf[i] & 0xff, 16)); } 

在将结果字节数组转换为字符串之前,必须对其进行编码。 上面的代码对我有用,而我的实际加密function如下。

 public String encrypt(String data) throws Exception{ try { Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); Key k = new SecretKeySpec(key.getBytes(), 0, key.length(), "AES"); // Calculate ciphertext size. int blocksize = 16; int ciphertextLength = 0; int remainder = data.getBytes().length % blocksize; if (remainder == 0) { ciphertextLength = data.getBytes().length + blocksize; } else { ciphertextLength = data.getBytes().length - remainder + blocksize; } cipher.init(Cipher.ENCRYPT_MODE, k); byte[] buf = new byte[ciphertextLength]; cipher.doFinal(data.getBytes(), 0, data.length(), buf, 0); StringBuffer strbuf = new StringBuffer(buf.length * 2); int i; for (i = 0; i < buf.length; i++) { if (((int) buf[i] & 0xff) < 0x10) { strbuf.append("0"); } strbuf.append(Long.toString((int) buf[i] & 0xff, 16)); } return strbuf.toString(); } catch (Exception e) { Logger.logException(e); } return null; } 

请参阅与Java中的CryptoStream .NET等效的答案#5 ?

一定要阅读底部的评论……

KeySpec ks = new DESKeySpec("key12345".getBytes("UTF-8")); SecretKey key = SecretKeyFactory.getInstance("DES").generateSecret(ks);
IvParameterSpec iv = new IvParameterSpec( Hex.decodeHex("1234567890ABCDEF".toCharArray()));
Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding"); cipher.init(Cipher.DECRYPT_MODE, key, iv);
byte[] decoded = cipher.doFinal(Base64.decodeBase64("B3xogi/Qfsc="));
System.out.println("Decoded: " + new String(decoded, "UTF-8"));

希望这可以帮助…
JK

Cemeron,那里的代码很齐全!

我遇到了一个有趣的情况,我们的客户给了IV钥匙一样的东西

尝试了各种组合,我得到了糟糕的填充exception,有效的解决方案是

 byte[] iv=new byte[8]; // assuming RC2 System.arraycopy(key.getBytes(), 0, iv, 0, key.getBytes().length > iv.length ? key.getBytes().length); // Now decrypt and hopefully this should work 
Interesting Posts