Вы должны быть в состоянии быстро адаптировать источник метода 1 к методу 2. Изменяемая функция - Sha1ProcessMessageBlock()
в методе 1. Инициализируйте w[0:15]
из сообщения, затем выполните цикл от 0 до 79, где вы только делаете w[]
манипуляция после итерации 16, и вычисление температуры зависит от значения t
s (0-19 используют одно, 20-39 используют другое и т. Д.). Важно помнить, что всякий раз, когда вы обращаетесь к массиву w[]
, используйте index%16
или index & 0x0f
.
Быстрая модификация будет выглядеть примерно так (дважды проверьте все обращения к w
, чтобы убедиться, что я не пропустил t & 0x0f
):
void SHA1ProcessMessageBlock(SHA1Context *context)
{
const uint32_t K[] = { /* Constants defined in SHA-1 */
0x5A827999,
0x6ED9EBA1,
0x8F1BBCDC,
0xCA62C1D6
};
int t; /* Loop counter */
uint32_t temp; /* Temporary word value */
uint32_t W[16]; /* Word sequence */
uint32_t A, B, C, D, E; /* Word buffers */
/*
* Initialize the first 16 words in the array W. You can move this to your
* context.
*/
for(t = 0; t < 16; t++)
{
W[t] = context->Message_Block[t * 4] << 24;
W[t] |= context->Message_Block[t * 4 + 1] << 16;
W[t] |= context->Message_Block[t * 4 + 2] << 8;
W[t] |= context->Message_Block[t * 4 + 3];
}
A = context->Intermediate_Hash[0];
B = context->Intermediate_Hash[1];
C = context->Intermediate_Hash[2];
D = context->Intermediate_Hash[3];
E = context->Intermediate_Hash[4];
for(t = 0; t < 80; t++) {
if (t >= 16) {
W[t&0xf] = SHA1CircularShift(1,W[(t-3)&0xf] ^ W[(t-8)&0xf] ^ W[(t-14)&0xf] ^ W[t&0xf]);
}
if (t<20) {
temp = SHA1CircularShift(5,A) +
((B & C) | ((~B) & D)) + E + W[t&0xf] + K[0];
}
else if (t<40) {
temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t&0xf] + K[1];
}
else if (t < 60) {
temp = SHA1CircularShift(5,A) +
((B & C) | (B & D) | (C & D)) + E + W[t&0xf] + K[2];
}
else {
temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t&0xf] + K[3];
}
E = D;
D = C;
C = SHA1CircularShift(30,B);
B = A;
A = temp;
}
context->Intermediate_Hash[0] += A;
context->Intermediate_Hash[1] += B;
context->Intermediate_Hash[2] += C;
context->Intermediate_Hash[3] += D;
context->Intermediate_Hash[4] += E;
context->Message_Block_Index = 0;
}
Еще предстоит сэкономить: избавьтесь от массива W[]
в стеке и поместите его в контекст, предварительно инициализированный полученными данными.
Кроме того, вам необходимо провести большую предварительную обработку перед вызовом этой функции. Например, если все ваши сообщения меньше 55 байт, вы можете поместить их в массив W, добавить заполнение и сразу же обработать. Если нет, вам придется вызывать process дважды: сначала с частично заполненным вводом, а затем с остальной частью пэда и т. Д. Подобные вещи будут зависеть от конкретного приложения, и я сомневаюсь, что вы сможете найти код, чтобы сделать это для вас.
Кстати, приведенный выше код является прямой адаптацией из источника типа 1 по вашей ссылке. Вероятно, вы можете выжать из него немного больше, если попытаетесь оптимизировать его дальше.
Я не мог придумать, как сэкономить промежуточный хеш, поэтому для этого вам понадобится всего 108 байт (109, если счетчик также находится в ОЗУ), и 24 из которых являются локальными для этой функции. и может быть повторно использован в других местах - при условии, что они также являются временными. Поэтому очень сложно делать то, что ты хочешь делать.
РЕДАКТИРОВАТЬ: Если все ваши сообщения меньше 55 байт, вы можете сохранить еще 20 байт в своем контексте, избавившись от хранилища intermediate_hash[]
. Просто инициализируйте A-E из констант и добавьте константы в конце. Наконец, вместо того, чтобы хранить их в отдельной переменной, перезапишите ввод, когда эта функция завершится.