Я пытаюсь использовать один и тот же ключ и VI для шифрования и дешифрования одного и того же сообщения, скажем, [email protected]
, Длина ключа составляет 128 бит, так как я знаю, что в Java / Android 256 нелегко реализовать.
Вот моя функция для шифрования AES с использованием Crypto ++
string encryptString(string toBeEncrypted) {
//
// Create Cipher Text
//
CryptoPP::AES::Encryption aesEncryption(key, CryptoPP::AES::DEFAULT_KEYLENGTH);
CryptoPP::CBC_Mode_ExternalCipher::Encryption cbcEncryption(aesEncryption, iv);
std::string ciphertext;
std::cout << "To be encrypted (" << toBeEncrypted.size() << " bytes)" << std::endl;
std::cout << toBeEncrypted;
std::cout << std::endl << std::endl;
CryptoPP::StreamTransformationFilter stfEncryptor(cbcEncryption, new CryptoPP::StringSink(ciphertext), CryptoPP::StreamTransformationFilter::PKCS_PADDING);
stfEncryptor.Put(reinterpret_cast<const unsigned char*> (toBeEncrypted.c_str()), toBeEncrypted.length() + 1);
stfEncryptor.MessageEnd();
}
ключ «4ff539a893fed04840749287bb3e4152», а IV «79f564e83be16711759ac7c730072bd0».
Они хранятся в двоичном виде в Ubuntu, работающем в VMWare на Windows x86.
Функция для преобразования key
а также iv
из байта в шестнадцатеричный массив это:
std::string hexToStr(unsigned char *data, int len)
{
std::stringstream ss;
ss<<std::hex;
for(int i(0);i<len;++i){
ss<<std::setfill('0')<<std::setw(2)<<(int)data[i];
}
return ss.str();
}
Я проверил шестнадцатеричную строку против памяти байтового массива key
а также iv
и они совпадают.
Результаты для шифрования [email protected]
является c08a50b45ff16650542e290e05390a6c6fe533e11e9f802ad7d47681fd41f964
из C ++.
Я получил это, передав возвращаемую строку ciphertext
в функцию hexToStr
лайк cout<<TFFHelper::hexStr((unsigned char *)ciphertext.c_str(), ciphertext.length())<<endl;
Я также могу расшифровать его с помощью следующей функции, и я передал в эту функцию необработанную строку, а не шестнадцатеричную строку.
string TFFEncryption::decryptString(string toBeDecrypted) {
string decryptedtext;
CryptoPP::AES::Decryption aesDecryption(key, CryptoPP::AES::DEFAULT_KEYLENGTH);
CryptoPP::CBC_Mode_ExternalCipher::Decryption cbcDecryption(aesDecryption, iv);
CryptoPP::StreamTransformationFilter stfDecryptor(cbcDecryption, new CryptoPP::StringSink(decryptedtext), CryptoPP::StreamTransformationFilter::PKCS_PADDING);
stfDecryptor.Put(reinterpret_cast<const unsigned char*> (toBeDecrypted.c_str()), toBeDecrypted.size());
stfDecryptor.MessageEnd();
return decryptedtext;
}
Я вставил те же VI и KEY в мой код Android, и попытался зашифровать. Это заканчивается в половине соответствия результатов после шифрования.
Код Android выглядит следующим образом:
public class myAES {
private static final String key = "4ff539a893fed04840749287bb3e4152";
private static final String initVector = "79f564e83be16711759ac7c730072bd0";
private final static char[] hexArray = "0123456789ABCDEF".toCharArray();
public static byte[] hexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+ Character.digit(s.charAt(i+1), 16));
}
return data;
}
public static String bytesToHex(byte[] bytes) {
char[] hexChars = new char[bytes.length * 2];
for ( int j = 0; j < bytes.length; j++ ) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = hexArray[v >>> 4];
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
}
return new String(hexChars);
}
public static byte[] encrypt(String value) {
try {
IvParameterSpec iv = new IvParameterSpec(hexStringToByteArray(initVector));
SecretKeySpec skeySpec = new SecretKeySpec(hexStringToByteArray(key), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
byte[] encrypted = cipher.doFinal(value.getBytes());
Log.v("Encryption successful", bytesToHex(encrypted));
return encrypted;
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
public static String decrypt(byte[] encrypted) {
try {
IvParameterSpec iv = new IvParameterSpec(hexStringToByteArray(initVector));
SecretKeySpec skeySpec = new SecretKeySpec(hexStringToByteArray(key), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
byte[] original = cipher.doFinal(encrypted);
Log.v("Decryption successful", new String(original, "UTF-8"));
return new String(original);
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
}
Я получил результат C08A50B45FF16650542E290E05390A6CFE5466FC480F0667517B248410930B69
,
Я использовал тот же кусок кода в Netbeans на Java8, работающий на той же самой Ubuntu кода C ++, и получил те же результаты, что и в предыдущей строке (результаты Android). Я не думаю, что это зависит от ОС, но, вероятно, я сделал что-то не так с Java или C ++ в моем коде.
Таким образом, первая половина шестнадцатеричных строк совпадает, а вторая половина — нет. Я пытался уменьшить фразу [email protected]
в [email protected]
, что приводит к полному отличным результатам от C ++ против Java (Ubuntu против Android).
Однако, если я расшифрую этот двоичный массив в Java, я получу оригинальную фразу [email protected]
или же [email protected]
,
У меня есть следующие вопросы.
const char *
в unsigned char *
? Я думаю, что все должно быть в порядке, так как я получаю шестнадцатеричную строку двоичного файлаЭлектронная почта в Crypto ++ сообщение '0'
прекращено, но сообщение в Джава не является.
Как AES это блочный шифр с длиной блока 128 бит (16 байт), а ваша электронная почта имеет длину ровно 16 байт, первый блок шифруется одинаково в обеих реализациях. '0'
в первой позиции второй блок дает разницу во втором блоке шифрования.
Обратите внимание на дополнительные '00'
на скриншоте ниже, используя этот онлайн инструмент. Все '0f'
следуя '00'
это PKCS5 Padding что этот инструмент не удалили здесь ..
Других решений пока нет …