Intereting Posts
Неожиданный результат при инициализации массива с использованием совместно используемых методов «Элемент по элементу» и «Назначенный» Как выполнить qsort массив указателей, которые используют структуры? Персистентность команд streamа OpenMP по всем функциям Что такое тип данных указателя в c? беззнаковое длинное шестнадцатеричное представление Как избежать использования глобальной переменной при использовании nftw Назначение значений в 2D-массив, созданный с помощью malloc Какова временная сложность инициализации массива? Компилирование программ из Emacs? ЬурейеЕ, # определить Типы данных, используемые в C Типы цепочки с фиксированной шириной C99 Как получить ширину / высоту файла jpeg без использования библиотеки? Проблема использования modulo с отрицательными числами в программе дешифрования В чем причина неспособности делить числа в GCC

CTR-AES256 Шифрование не соответствует OpenSSL -aes-256-ctr

Моя проблема заключается в том, что я не могу получить вывод CES AES 256 из приведенного ниже кода C, чтобы он соответствовал выводам команды OpenSSL ниже.

Код C производит следующее:

5f b7 18 d1 28 62 7f 50 35 ba e9 67 a7 17 ab 22 f9 e4 09 ce 23 26 7b 93 82 02 d3 87 eb 01 26 ac 96 2c 01 8c c8 af f3 de a4 18 7f 29 46 00 2e 00 

Командная строка OpenSSL создает следующее:

 5f b7 18 d1 28 62 7f 50 35 ba e9 67 a7 17 ab 22 3c 01 11 bd 39 14 74 76 31 57 a6 53 f9 00 09 b4 6f a9 49 bc 6d 00 77 24 2d ef b9 c4 

Обратите внимание, что первые 16 байтов одинаковы, потому что nonceIV был одинаковым, однако, когда nonceIV обновляется на следующей итерации, тогда XOR’d с открытым текстом, следующие 16 байт отличаются и так далее …?

Я не понимаю, почему это происходит? Кто-нибудь знает, почему шестнадцатеричные коды отличаются после первого 16-байтового куска?

Отказ от ответственности: я не эксперт по C.

Спасибо!!

Fox.txt

 The quick brown fox jumped over the lazy dog 

Затем запустите следующую команду OpenSSL, чтобы создать файл foxy.exe

 openssl enc -aes-256-ctr -in fox.txt -out foxy.exe -K 603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4 -iv f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff -nosalt -nopad -p 

Вот что содержит файл foxy.exe :

 5f b7 18 d1 28 62 7f 50 35 ba e9 67 a7 17 ab 22 3c 01 11 bd 39 14 74 76 31 57 a6 53 f9 00 09 b4 6f a9 49 bc 6d 00 77 24 2d ef b9 c4 

Вот код.

  #include  // What is AES CTR // // AES - CTR (counter) mode is another popular symmetric encryption algorithm. // // It is advantageous because of a few features : // 1. The data size does not have to be multiple of 16 bytes. // 2. The encryption or decryption for all blocks of the data can happen in parallel, allowing faster implementation. // 3. Encryption and decryption use identical implementation. // // Very important note : choice of initial counter is critical to the security of CTR mode. // The requirement is that the same counter and AES key combination can never to used to encrypt more than more one 16 - byte block. // Notes // ----- // * CTR mode does not require padding to block boundaries. // // * The IV size of AES is 16 bytes. // // * CTR mode doesn't need separate encrypt and decrypt method. Encryption key can be set once. // // * AES is a block cipher : it takes as input a 16 byte plaintext block, // a secret key (16, 24 or 32 bytes) and outputs another 16 byte ciphertext block. // // References // ---------- // https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Counter_.28CTR.29 // https://www.cryptopp.com/wiki/CTR_Mode#Counter_Increment // https://modexp.wordpress.com/2016/03/10/windows-ctr-mode-with-crypto-api/ // https://msdn.microsoft.com/en-us/library/windows/desktop/jj650836(v=vs.85).aspx // http://www.cryptogrium.com/aes-ctr.html // http://www.bierkandt.org/encryption/symmetric_encryption.php #define IV_SIZE 16 #define AES_BLOCK_SIZE 16 typedef struct _key_hdr_t { PUBLICKEYSTRUC hdr; // Indicates the type of BLOB and the algorithm that the key uses. DWORD len; // The size, in bytes, of the key material. char key[32]; // The key material. } key_hdr; // NIST specifies two types of counters. // // First is a counter which is made up of a nonce and counter. // The nonce is random, and the remaining bytes are counter bytes (which are incremented). // For example, a 16 byte block cipher might use the high 8 bytes as a nonce, and the low 8 bytes as a counter. // // Second is a counter block, where all bytes are counter bytes and can be incremented as carries are generated. // For example, in a 16 byte block cipher, all 16 bytes are counter bytes. // // This uses the second method, which means the entire byte block is treated as counter bytes. void IncrementCounterByOne(char *inout) { int i; for (i = 16 - 1; i >= 0; i--) { inout[i]++; if (inout[i]) { break; } } } void XOR(char *plaintext, char *ciphertext, int plaintext_len) { int i; for (i = 0; i hdr.bType = PLAINTEXTKEYBLOB; key->hdr.bVersion = CUR_BLOB_VERSION; key->hdr.reserved = 0; key->hdr.aiKeyAlg = GetAlgorithmIdentifier(aeskeylenbits); key->len = GetKeyLengthBytes(aeskeylenbits); memmove(key->key, pKey, key->len); } // point = pointer to the start of the plaintext, extent is the size (44 bytes) void __stdcall AESCTR(char *point, int extent, char *pKey, char *pIV, unsigned int aeskeylenbits, char *bufOut) { HCRYPTPROV hProv; HCRYPTKEY hSession; key_hdr key; DWORD IV_len; div_t aesblocks; char nonceIV[64]; char tIV[64]; char *bufIn; bufIn = point; memmove(nonceIV, pIV, IV_SIZE); SetKeyData(&key, aeskeylenbits, pKey); CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT | CRYPT_SILENT); CryptImportKey(hProv, (PBYTE)&key, sizeof(key), 0, CRYPT_NO_SALT, &hSession); aesblocks = div(extent, AES_BLOCK_SIZE); while (aesblocks.quot != 0) { IV_len = IV_SIZE; memmove(tIV, nonceIV, IV_SIZE); CryptEncrypt(hSession, 0, FALSE, 0, (BYTE *)tIV, &IV_len, sizeof(tIV)); XOR(bufIn, tIV, AES_BLOCK_SIZE); IncrementCounterByOne(nonceIV); bufIn += AES_BLOCK_SIZE; aesblocks.quot--; } if (aesblocks.rem != 0) { memmove(tIV, nonceIV, IV_SIZE); CryptEncrypt(hSession, 0, TRUE, 0, (BYTE *)tIV, &IV_len, sizeof(tIV)); XOR(bufIn, tIV, aesblocks.rem); } memmove(bufOut, point, extent); CryptDestroyKey(hSession); CryptReleaseContext(hProv, 0); } 

Мне удалось получить эту работу по предложенному псевдокоду в разделе замечаний M $ CryptEncrypt () https://msdn.microsoft.com/en-us/library/windows/desktop/aa379924(v=vs.85).aspx :

 // Set the IV for the original key. Do not use the original key for // encryption or decryption after doing this because the key's // feedback register will get modified and you cannot change it. CryptSetKeyParam(hOriginalKey, KP_IV, newIV) while(block = NextBlock()) { // Create a duplicate of the original key. This causes the // original key's IV to be copied into the duplicate key's // feedback register. hDuplicateKey = CryptDuplicateKey(hOriginalKey) // Encrypt the block with the duplicate key. CryptEncrypt(hDuplicateKey, block) // Destroy the duplicate key. Its feedback register has been // modified by the CryptEncrypt function, so it cannot be used // again. It will be re-duplicated in the next iteration of the // loop. CryptDestroyKey(hDuplicateKey) } 

Вот обновленный код с добавленными двумя новыми строками:

 HCRYPTKEY hDuplicateKey; boolean final; while (aesblocks.quot != 0) { CryptDuplicateKey(hOriginalKey, NULL, 0, &hDuplicateKey); IV_len = IV_SIZE; memmove(tIV, nonceIV, IV_len); final = (aesblocks.quot == 1 && aesblocks.rem == 0) ? TRUE : FALSE; CryptEncrypt(hDuplicateKey, 0, final, 0, (BYTE *)tIV, &IV_len, sizeof(tIV)); XOR(bufIn, tIV, AES_BLOCK_SIZE); IncrementCounterByOne(nonceIV); bufIn += AES_BLOCK_SIZE; aesblocks.quot--; CryptDestroyKey(hDuplicateKey); } if (aesblocks.rem != 0) { CryptDuplicateKey(hOriginalKey, NULL, 0, &hDuplicateKey); final = TRUE; memmove(tIV, nonceIV, IV_SIZE); CryptEncrypt(hDuplicateKey, 0, final, 0, (BYTE *)tIV, &IV_len, sizeof(tIV)); XOR(bufIn, tIV, aesblocks.rem); CryptDestroyKey(hDuplicateKey); } 

Я не знаком с API-интерфейсами Microsoft, но я считаю, что CryptEncrypt () использует режим CBC по умолчанию – поэтому вывод из первого блока шифрования автоматически подается на вход для второго блока. Вы сами создаете режим CTR, который формирует скретч (что, кстати, обычно нецелесообразно делать – вы должны использовать возможности криптографических библиотек, а не «сворачивать свой собственный» крипто). Чтобы получить ожидаемый результат, вам, вероятно, понадобится заставить CryptEncrypt использовать AES в режиме ECB, который, как мне кажется, может быть выполнен с использованием CryptptSetKeyParam ( https://msdn.microsoft.com/en-us/library/aa380272.aspx ) и установки KP_MODE к CRYPT_MODE_ECB.

Убедитесь, что ваш входной файл не содержит никаких дополнительных символов, таких как новая строка и т. Д. Openssl будет включать эти дополнительные символы во время шифрования.