gpt4 book ai didi

CTR-AES256 加密与 OpenSSL -aes-256-ctr 不匹配

转载 作者:可可西里 更新时间:2023-11-01 11:46:47 26 4
gpt4 key购买 nike

我的问题是我无法从下面的 C 代码中获取 AES 256 CTR 输出以匹配下面 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 在下一次迭代中更新时,然后与明文进行异或运算,接下来的 16 个字节不同等等......?

我不明白为什么会这样?任何人都知道为什么十六进制代码在第一个 16 字节 block 之后不同?

免责声明:我不是 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 <Windows.h>

// 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 < plaintext_len; i++)
{
plaintext[i] ^= ciphertext[i];
}
}


unsigned int GetAlgorithmIdentifier(unsigned int aeskeylenbits)
{
switch (aeskeylenbits)
{
case 128:
return CALG_AES_128;
case 192:
return CALG_AES_192;
case 256:
return CALG_AES_256;
default:
return 0;
}
}


unsigned int GetKeyLengthBytes(unsigned int aeskeylenbits)
{
return aeskeylenbits / 8;
}


void SetKeyData(key_hdr *key, unsigned int aeskeylenbits, char *pKey)
{
key->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);
}

最佳答案

我不熟悉 Microsoft API,但我相信 CryptEncrypt() 默认使用 CBC 模式 - 因此第一个加密 block 的输出会自动输入到第二个 block 的输入中。您正在从头开始自己构建 CTR 模式(顺便说一下,这通常不是一件可取的事情 - 您应该使用加密库的功能而不是“推出自己的”加密)。为了获得预期的输出,您可能需要让 CryptEncrypt 在 ECB 模式下使用 AES - 我相信这可以使用 CryptptSetKeyParam ( https://msdn.microsoft.com/en-us/library/aa380272.aspx ) 并将 KP_MODE 设置为 CRYPT_MODE_ECB 来完成。

关于CTR-AES256 加密与 OpenSSL -aes-256-ctr 不匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42847568/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com