2013-08-06 79 views
0

嗨我想加密和解密在2个系统中使用的数据(一个是C++和另一个Java)我从代码项目中找到了一个Demo项目:Encryption this是C++加密解密功能,当我使用函数实现的代码它的工作原理:C++加密解密函数(Cryptix工具箱)的Java实现

void main() 
{ 
    try 
    { 
     CRijndael oRijndael; 
     oRijndael.MakeKey("abcdefghabcdefgh", "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16, 16); 
     char szDataIn[] = "Password12345678"; 

     char szDataOut[17] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; 

     oRijndael.EncryptBlock(szDataIn, szDataOut); 

     cout << "[" << szDataIn << "]" << endl; 
     cout << "[" << szDataOut << "]" << endl; 
     memset(szDataIn, 0, 16); 

     oRijndael.DecryptBlock(szDataOut, szDataIn); 
     cout << "[" << szDataIn << "]" << endl; 

    } 
    catch(exception& roException) 
    { 
     cout << roException.what() << endl; 
    } 
} 

这使我在控制台以下输出:

enter image description here

对数据进行加密结束解密..

任何人都可以帮我指点一下Java实现的正确方向,以加密和解密获得相同结果的相同数据(在C++中进行加密,然后在Java中进行解密,然后在C++中使用java进行加密)?在帖子中,他们讨论Cryptix工具包?

在此先感谢。

+0

Rijndael也被称为AES。尽管您可能需要深入研究CRijndael以找出它正在使用的参数(比特,密码模式,填充,IV?)等等,但Java的AES还有很多实现。 – Rup

回答

2

此Java代码将加密/解密并生成与编码为十六进制的示例相同的输出。输出看起来是相同的(也应该是),但要100%确定您需要在C++示例中对输出进行十六进制编码。

请注意,虽然您的示例只会加密和解密单个块(16个字节)。如果你想要更多,你需要使用CRijndaelEncryptDecrypt方法(而不是EncryptBlockDecryptBlock)。下面的Java代码可以同时使用,不需要修改它。

public static void main(String[] args) throws DecoderException, InvalidKeyException, 
     NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, 
     IllegalBlockSizeException, BadPaddingException { 
    //Hex encoding/decoding done with Apache Codec 
    byte[] key = "abcdefghabcdefgh".getBytes(); 
    String text = "Password12345678"; 

    byte[] encrypted = encrypt(key, text.getBytes()); 
    byte[] decrypted = decrypt(key, encrypted); 

    System.out.println("Text: " + text); 
    System.out.println("Encrypted: " + Hex.encodeHexString(encrypted)); 
    System.out.println("Decrypted: " + new String(decrypted)); 
} 

public static byte[] encrypt(byte[] key, byte[] unencrypted) throws NoSuchAlgorithmException, 
     NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, 
     IllegalBlockSizeException, BadPaddingException{ 
    //Set up the cipher and encrypt 
    Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding"); 
    cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES")); 
    byte[] encrypted = cipher.doFinal(unencrypted); 

    return encrypted; 
    } 

public static byte[] decrypt(byte[] key, byte[] encrypted) throws NoSuchAlgorithmException, 
     NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, 
     IllegalBlockSizeException, BadPaddingException{ 
    //Decrypt the encrypted text 
    Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding"); 
    cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, "AES")); 
    byte[] decrypted = cipher.doFinal(encrypted); 

    return decrypted; 
} 

输出

Text: Password12345678 
Encrypted: 6c7d800fad2bb8593db92847bbbdbeff 
Decrypted: Password12345678 

虽然警告你的大词,这种加密(ECB,没有填充)是极不安全的,你不应该在实际系统中使用它。你应该真的在使用初始化矢量和PKCS5填充的CBC。

1

请务必不要直接从字符数组中导出加密数据。要么使用固定大小的输出,要么使用字节缓冲区。这是强制性的,因为在加密的字符串中,可能有字节组合,可以解释为控制字符f.e. \0马克。如果是这样,使用...<< szDataOut;打印输出到文件可能会破坏你的加密字符串,并且无法通过第二个应用程序完全读取它(不管是否是java或C++)。