我正试图从C到Java重写GimLIIHHASH。
我已经对照C代码和测试向量检查了我对gimli排列的重写,这是正确的,所以问题就在我对实际哈希的重写中,尽管我不知道在哪里。
void Gimli_hash(const uint8_t *input,
uint64_t inputByteLen,
uint8_t *output,
uint64_t outputByteLen)
{
uint32_t state[12];
uint8_t* state_8 = (uint8_t*)state;
uint64_t blockSize = 0;
uint64_t i;
// === Initialize the state ===
memset(state, 0, sizeof(state));
// === Absorb all the input blocks ===
while(inputByteLen > 0) {
blockSize = MIN(inputByteLen, rateInBytes);
for(i=0; i<blockSize; i++)
state_8[i] ^= input[i];
input += blockSize;
inputByteLen -= blockSize;
if (blockSize == rateInBytes) {
gimli(state);
blockSize = 0;
}
}
// === Do the padding and switch to the squeezing phase ===
state_8[blockSize] ^= 0x1F;
// Add the second bit of padding
state_8[rateInBytes-1] ^= 0x80;
// Switch to the squeezing phase
gimli(state);
// === Squeeze out all the output blocks ===
while(outputByteLen > 0) {
blockSize = MIN(outputByteLen, rateInBytes);
memcpy(output, state, blockSize);
output += blockSize;
outputByteLen -= blockSize;
if (outputByteLen > 0)
gimli(state);
}
}
这直接取自Gimli的C实现,
下面是我已经编写的Java代码:
public static byte[] hash(byte[] input, int outputLen) {
int inputlen = input.length;
int[] state = new int[12];
byte[] state_8 = stateToBytes(state);
int blocksize = 0;
int i;
int pointer = 0;
/* Absorbing input */
while (inputlen > 0) {
blocksize = Math.min(inputlen, rateInBytes);
for (i = 0; Integer.compareUnsigned(i, blocksize) < 0; i++) {
state_8[i] ^= input[i + pointer];
}
state = stateToInt(state_8);
pointer += blocksize;
inputlen -= blocksize;
if (blocksize == rateInBytes) {
gimli(state);
state_8 = stateToBytes(state);
blocksize = 0;
}
}
state_8[blocksize] ^= 0x1f;
state_8[rateInBytes - 1] ^= 0x80;
state = stateToInt(state_8);
gimli(state);
state_8 = stateToBytes(state);
byte[] output = new byte[outputLen];
int outputPointer = 0;
while (outputLen > 0) {
blocksize = Math.min(outputLen, rateInBytes);
System.arraycopy(state_8, 0, output, outputPointer, blocksize);
outputPointer += blocksize;
outputLen -= blocksize;
if (outputLen > 0) {
gimli(state);
state_8 = stateToBytes(state);
}
}
return output;
}
StateToInt和StateToBytes只是在状态的字节格式和int格式之间进行转换(因为排列操作的是int格式,而哈希操作的是字节格式)。当对空字符串(0字节)进行散列时,C实现返回B0634 B2C0B082AEDC5A0FE4EE3ADCFC989EC05DE6F0ADB04B3AAAC27 1F67,Java代码返回4B7F6DA2D5A901DBB580A0864 7E716EA1116328 85 993DA0BA29 D88 CE8926AF025。
对Java实现与C语言的不同之处的任何帮助都将是非常值得赞赏的。