Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AES 256 encryption - Qt equivalent for Java

I have my AES 256 encryption method implemented and working fine in Java as follows!

  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;  
}  

The byte array that is returned from the above method is finally converted to a HEX string using the following toHex method.

      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 = "0123456789ABCDEF";  
private static void appendHex(StringBuffer sb, byte b) {  
    sb.append(HEX.charAt((b>>4)&0x0f)).append(HEX.charAt(b&0x0f));  
}  

So the end result using Java AES 256 encryption code is a HEX String.

Now for the Qt part,

  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);
} 

And from the main method i call the above function

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

where "result" is a QByteArray that I pass to encrypt as done similarly in java.

The byte arrays in both cases Java and Qt are obtained the same. I have verified that.

My problem

The encryption logic for Qt especially is failing somewhere due to which the HEX result obtained via Java and Qt don't match.

Can anyone tell me what I am doing wrong in the Qt part. Am I not using the IV or the QByteArray result correctly?

like image 594
Parth Doshi Avatar asked Feb 23 '14 06:02

Parth Doshi


1 Answers

I guess your Java implementation misses a hash step on the key. I'm using a SHA256 hash of the key. To test c++ implementation, change code to this:

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);
} 
like image 181
sorush-r Avatar answered Sep 19 '22 10:09

sorush-r