Я использую довольно старый компилятор, и я считаю, что компилятор сделал небольшую ошибку в диагностике предупреждений.
typedef unsigned char uint8_t; // 8-bit byte
typedef unsigned int uint32_t; // 32-bit word (change to "long" for 16-bit machines)
typedef struct _sha256_ctx_t
{
uint8_t data[64];
uint32_t data_len;
unsigned __int64 bit_len; // unsigned long long
uint32_t state[8];
} sha256_ctx_t;
void crypto_sha256_final(sha256_ctx_t *ctx, uint8_t *digest)
{
uint32_t i;
i = ctx->data_len;
// Append to the padding the total message's length in bits and transform.
ctx->bit_len += ctx->data_len * 8;
ctx->data[63] = ctx->bit_len; // LINE 156 IS HERE!
ctx->data[62] = ctx->bit_len >> 8;
ctx->data[61] = ctx->bit_len >> 16;
ctx->data[60] = ctx->bit_len >> 24;
ctx->data[59] = ctx->bit_len >> 32;
ctx->data[58] = ctx->bit_len >> 40;
ctx->data[57] = ctx->bit_len >> 48;
ctx->data[56] = ctx->bit_len >> 56; // LINE 163 IS HERE!
local_sha256_transform(ctx, ctx->data);
// Since this implementation uses little endian byte ordering and SHA uses big endian,
// reverse all the bytes when copying the final state to the output digest.
for (i = 0; i < 4; ++i) {
digest[i] = (ctx->state[0] >> (24 - i * 8)) & 0x000000ff;
digest[i + 4] = (ctx->state[1] >> (24 - i * 8)) & 0x000000ff;
digest[i + 8] = (ctx->state[2] >> (24 - i * 8)) & 0x000000ff;
digest[i + 12] = (ctx->state[3] >> (24 - i * 8)) & 0x000000ff;
digest[i + 16] = (ctx->state[4] >> (24 - i * 8)) & 0x000000ff;
digest[i + 20] = (ctx->state[5] >> (24 - i * 8)) & 0x000000ff;
digest[i + 24] = (ctx->state[6] >> (24 - i * 8)) & 0x000000ff;
digest[i + 28] = (ctx->state[7] >> (24 - i * 8)) & 0x000000ff;
}
}
Этот код приводит к этой ошибке (от строк 156 до 163):
SHA256.cpp(156) : warning C4244: '=' : conversion from 'unsigned __int64' to 'unsigned char', possible loss of data
Я предполагаю, что этот старый компилятор не понимает, что добавление его с 0xFF сужает результат до байта. У кого-нибудь есть предложения о том, как обойти ложное предупреждение?
Исходный источник кода: https://programmer.group/61737ba233df9.html
Конечно, я добавил это для вас.
64-битное число не поместится в 8-битное без потери данных. Это не ложное предупреждение.
Ну да, похоже компилятор этого не понимает, вот и все.
Любые предложения о том, как это исправить? У меня есть свои причины, по которым мне нужно использовать именно этот компилятор.
— Честно говоря, исправление заключается в использовании минимально работающего компилятора. Если у вас действительно есть веские причины использовать безнадежно сломанный, все, что мы можем сделать, это пожелать вам удачи. Но если бы вы рассказали нам больше о своих причинах, мы потенциально могли бы предложить альтернативы.
простое решение - разыграть ctx->data[60] = uint8_t(ctx->bit_len >> 24);. Но настоящее решение — использовать современный компилятор и, хорошую криптографическую библиотеку. Современные библиотеки используют SIMD и будут в десятки или сотни раз быстрее, чем эта.
Спасибо за предложение по актерскому составу. Это решило это.
Не размещайте решения в теле вопроса. Сделайте отдельный ответ, пожалуйста. Это правила сайта.
@matead, возможно, вы захотите проверить OpenWatcom, это компилятор с открытым исходным кодом, который поддерживает почти все системы VC++6 и, по крайней мере, все еще «поддерживается»





В этом случае с компилятором все в порядке.
ctx->data[63] = ctx->bit_len; // LINE 156 IS HERE!
ctx->data[62] = ctx->bit_len >> 8;
ctx->data[61] = ctx->bit_len >> 16;
ctx->data[60] = ctx->bit_len >> 24;
ctx->data[59] = ctx->bit_len >> 32;
ctx->data[58] = ctx->bit_len >> 40;
ctx->data[57] = ctx->bit_len >> 48;
ctx->data[56] = ctx->bit_len >> 56; // LINE 163 IS HERE!
ctx->bit_len — это 64-битный тип, поэтому очевидно, что сохранение его в uint8_t не работает. В этих строках нет маскировки с помощью 0xFF, как в digest[i] = (ctx->state[0] >> (24 - i * 8)) & 0x000000ff;. Единственный случай, когда отсутствует анализ, это ctx->data[56] = ctx->bit_len >> 56, потому что результат соответствует uint8_t. Чтобы получить LSB, вам нужно сделать явное приведение, чтобы компилятор знал, что вы делаете.
ctx->data[62] = uint8_t(ctx->bit_len >> 8);
При этом нет необходимости копировать вручную, просто используйте memcpy и ntohll. Код не очень хорош, а использование древнего компилятора еще хуже. В настоящее время существует множество хороших криптографических библиотек, которые используют правильный SIMD и многопоточность, такие как OpenSSL.
Компилятор может быть достаточно умен, чтобы проверить возможный диапазон арифметического выражения (в очевидных случаях), и этот компилятор был совершенно прав, выдав предупреждение, если он не проверил. Это действительно по-разному обрабатывается более поздними версиями компилятора.
Попробуйте это лекарство: приведите назначенное выражение к char.
Можете ли вы уточнить, какая именно строка в показанном коде «добавляет его с 0xFF»?