2014-02-23 92 views
4

我有我的AES 256加密方法實現並在Java中正常工作,如下所示!AES 256加密-Qt等同於Java

private static final byte[] IV = { 
    0, 2, 4, 8, 16, 32, 64, 127, 
    127, 64, 32, 16, 8, 4, 2, 0 
}; 

    //actual encryption over here 
    private static byte[] encrypt(byte[] raw, byte[] clear) throws 
Exception { 
    SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); 
    Cipher cipher = null; 

    if(isIVUsedForCrypto) { 
     cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
     cipher.init(Cipher.ENCRYPT_MODE, skeySpec, new IvParameterSpec(IV)); 
    } 
    else 
    { 
     cipher = Cipher.getInstance("AES"); 
     cipher.init(Cipher.ENCRYPT_MODE, skeySpec); 
    } 
    byte[] encrypted = cipher.doFinal(clear); 
    return encrypted; 
} 

是從上述方法返回的字節數組最終轉換成使用以下toHex方法的HEX字符串。

 public static String toHex(byte[] buf) { 
    if (buf == null) 
     return ""; 
    StringBuffer result = new StringBuffer(2*buf.length); 
    for (int i = 0; i < buf.length; i++) { 
     appendHex(result, buf[i]); 
    } 
    return result.toString(); 
} 
private final static String HEX = "ABCDEF"; 
private static void appendHex(StringBuffer sb, byte b) { 
    sb.append(HEX.charAt((b>>4)&0x0f)).append(HEX.charAt(b&0x0f)); 
} 

所以使用Java AES 256加密代碼的最終結果是一個十六進制字符串。

現在爲Qt的一部分,

QByteArray IV("0, 2, 4, 8, 16, 32, 64, 127,127, 64, 32, 16, 8, 4, 2, 0"); 


QString encrypt(QByteArray r, const QString &password) 
{ 
const char *sample = r.data(); 
string plain = password.toStdString(); 
string ciphertext; 
// Generate Cipher, Key, and CBC 
byte key[ AES::MAX_KEYLENGTH ], iv[ AES::BLOCKSIZE ]; 
StringSource(reinterpret_cast<const char *>(sample), true, 
       new HashFilter(*(new SHA256), new ArraySink(key, AES::MAX_KEYLENGTH))); 
memset(iv, 0x00, AES::BLOCKSIZE); 
CBC_Mode<AES>::Encryption Encryptor(key, sizeof(key), iv); 
StringSource(plain, true, new StreamTransformationFilter(Encryptor, 
       new HexEncoder(new StringSink(ciphertext)))); 
return QString::fromStdString(ciphertext); 
} 

並從主方法我調用上述功能

 QString encrypted = encrypt(result, "test"); 

其中「結果」是類似地在做了QByteArray我傳給加密java的。

在這兩種情況下Java和Qt的字節數組都是相同的。我已經證實了這一點。

我的問題

Qt的特別的地方是由於它通過Java和Qt獲得的HEX結果不匹配失敗的加密邏輯。

任何人都可以告訴我我在做什麼錯誤的Qt部分。我沒有正確使用IVQByteArrayresult

+0

當創建與'SecretKeySpec skeySpec =關鍵新SecretKeySpec(原 「AES」);',如何*究竟*不Java結構從'原始密鑰'使用'AES'? – jww

+0

'Cipher.getInstance(「AES/CBC/PKCS5Padding」);' - 我相信這是默認使用AES-128。也許你應該嘗試'「AES256/CBC/PKCS5Padding」'。請參閱Java的[密碼算法名稱](http://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html#Cipher)。 – jww

回答

2

我猜你的Java實現會遺漏密鑰上的散列步驟。我正在使用密鑰的SHA256散列。爲了測試C++實現,改變代碼如下:

QString encrypt(QByteArray r, const QString &password) 
{ 
const char *sample = r.data(); 
string plain = password.toStdString(); 
string ciphertext; 
// Generate Cipher, Key, and CBC 
byte key[ AES::MAX_KEYLENGTH ], iv[ AES::BLOCKSIZE ]; 
//StringSource(reinterpret_cast<const char *>(sample), true, 
//    new HashFilter(*(new SHA256), new ArraySink(key, AES::MAX_KEYLENGTH))); 
for(int i=0; i< AES::MAX_KEYLENGTH; ++i){ 
    key[i] = reinterpret_cast<const char *>(decodedKey)[i]; 
} 
memset(iv, 0x00, AES::BLOCKSIZE); 
CBC_Mode<AES>::Encryption Encryptor(key, sizeof(key), iv); 
StringSource(plain, true, new StreamTransformationFilter(Encryptor, 
       new HexEncoder(new StringSink(ciphertext)))); 
return QString::fromStdString(ciphertext); 
} 
+0

是的感謝它的工作現在好...如果萬一我在將來遇到任何問題,我會在這裏添加評論 –

2

初始化向量是在Java代碼中不同和Qt:

private static final byte[] IV = { 
    0, 2, 4, 8, 16, 32, 64, 127, 
    127, 64, 32, 16, 8, 4, 2, 0 
}; 

而在C++:

memset(iv, 0x00, AES::BLOCKSIZE); // ==> This fills the iv array with 0s 

所以你需要使用相同的IV兩種方案。

更新:

爲了提供AES的CBC模式下的IV,你需要指定IV如您在Java做:

byte iv[ AES::BLOCKSIZE ] = {0, 2, 4, 8, 16, 32, 64, 127, 
          127, 64, 32, 16, 8, 4, 2, 0}; 

注意,AES :: BLOCKSIZE的定義在庫標題中,它是16

+0

再次感謝sorush-r。它會正常工作嗎?怎麼樣qbytearray ...我正確地使用它。對不起,我是Java開發人員,所以這就是爲什麼發現很難理解C++ –

+0

這意味着我應該做memset(iv,IV,AES :: BLOCKSIZE);對? –

+0

請加入這個聊天室:http://chat.stackoverflow.com/rooms/48187/qt –