gpt4 book ai didi

java - 用 Java 重写 Gimli_hash

转载 作者:太空宇宙 更新时间:2023-11-04 03:13:29 24 4
gpt4 key购买 nike

我正在尝试将 Gimli_hash 从 C 语言重写为 Java。

我已经根据 C 代码和测试 vector 检查了我对 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 实现返回 b0634b2c0b082aedc5c0a2fe4ee3adcfc989ec05de6f00addb04b3aaac271f67,Java 代码返回 4b7f6da2d5a901dbdb580a08647e16ae11163288593da0ba29d8802592

如果您能帮助我们找出 Java 实现与 C 实现的不同之处,我们将不胜感激。

最佳答案

事实证明,散列不起作用的原因是字节顺序问题:原来的 stateToBytes 和 stateToInt 没有工作,因为它在 BE 而不是 LE:原文:

private static byte[] stateToBytes(int[] state) {
byte[][] temp = new byte[state.length][];

for (int i = 0; i < temp.length; i++) {
temp[i] = intToBytes(state[i]);
}

return merge(temp);
}

private static int[] stateToInt(byte[] state) {
int[] out = new int[state.length / 4];
for (int i = 0; i < (state.length / 4); i++) {
out[i] = byteArrayToInt(Arrays.copyOfRange(state, (i * 4), ((i + 1) * 4)));
}

return out;
}

更新:

private static byte[] stateToBytes(int[] state) {
byte[][] temp = new byte[state.length][];

for (int i = 0; i < temp.length; i++) {
temp[i] = reverse(intToBytes(state[i]));
}

return merge(temp);
}

private static int[] stateToInt(byte[] state) {
int[] out = new int[state.length / 4];
for (int i = 0; i < (state.length / 4); i++) {
out[i] = byteArrayToInt(reverse(Arrays.copyOfRange(state, (i * 4), ((i + 1) * 4))));
}

return out;
}

感谢@paddy 让我注意到这些函数的行为。

关于java - 用 Java 重写 Gimli_hash,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54140047/

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