Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/313.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Keccak-256实现对零字节消息的不正确哈希_Java_Cryptography_Keccak - Fatal编程技术网

Java Keccak-256实现对零字节消息的不正确哈希

Java Keccak-256实现对零字节消息的不正确哈希,java,cryptography,keccak,Java,Cryptography,Keccak,我一直在尝试用Java编写自己的Keccak-256加密哈希函数实现。我一直在使用和他们的参考。我想使用零长度输入测试我的实现。根据在线工具。零长度输入的哈希值应为:C5D2460186F7233C927E7DB2DCC703C0E500B653CA82273B7BFAD8045D85A470,但我的哈希值是其他值 我的密码在这里。 我的想法是,在将byte[]转换为long和back的过程中,或者在吸收/压缩阶段,我一定是在消息的填充(这就是所有被散列的内容)或字节顺序上做错了什么。在我的实现

我一直在尝试用Java编写自己的Keccak-256加密哈希函数实现。我一直在使用和他们的参考。我想使用零长度输入测试我的实现。根据在线工具。零长度输入的哈希值应为:
C5D2460186F7233C927E7DB2DCC703C0E500B653CA82273B7BFAD8045D85A470
,但我的哈希值是其他值

我的密码在这里。 我的想法是,在将byte[]转换为long和back的过程中,或者在吸收/压缩阶段,我一定是在消息的填充(这就是所有被散列的内容)或字节顺序上做错了什么。在我的实现中,我只需要
keccak-f[1600]
,这意味着每个通道中只有64位,每个块是1088位或136字节。我选择使用五乘五的二维长数组来表示代码中的状态

使用零字节消息意味着应该只有一个136字节的块,这些块应该都只是填充。根据,由于keccak使用的是little endian,因此我的填充应按字节顺序排列:

byte[] p = new byte[136];
p[7] = (byte) 0x01;
p[135] = (byte) 0x80;
我看了别人的,但似乎找不出我的错误在哪里

这是海绵功能:

public byte[] keccak(byte[] Mbytes, int r, int c) { // r should be 1088 and c should be 512 for Keccack-256
    // Padding
    byte[] paddedMessage = concatBytes(Mbytes, pad(r, Mbytes.length));
    System.out.println("Padded Message size: " + paddedMessage.length);

    // Initialize State
    A = new long[5][5];

    // Break up message into blocks r bits or 136 bytes
    byte[] block = new byte[136];
    int n = paddedMessage.length / block.length; // number of blocks
    System.out.println("Blocks: " + n);

    for (int i = 0; i < n; i++) { // For each block
        //set block values
        for (int j = 0; j < block.length; j++) {
            block[j] = paddedMessage[i * block.length + j];
        }
        printBlock(block);

        // Fill state
        for (int x = 0; x < 5; x++) {
            for (int y = 0; y < 5; y++) {
                int index = x + 5 * y;
                if (index < r/w) {
                    long value = decodeLELong(block, index * 8);
                    System.out.println(value + " index: " + index);
                    A[x][y] = A[x][y] ^ value;
                    A = keccakF1600(A);
                }
            }
        }
    }
    byte[] output = new byte[0]; // Size should be 256 bits/Z
    int bytesFilled = 0;
    for (int x = 0; x < 5; x++) {
        for (int y = 0; y < 5; y++) {
            int index = x+5*y;
            if (index < r/w) {
                if (bytesFilled < 136) {
                    // Take out a long from state and concat it to output.
                    output = concatBytes(output, encodeLELong(A[x][y]));
                    bytesFilled += 8;
                    A = keccakF1600(A);
                }
            }
            if (bytesFilled == 32) {
                //System.out.println("Finished Hash");
                return output;
            }
        }
    }

    return output;
}
 private byte[] pad(int x, int m) { // x/size should be 1088 or 136 bytes
    byte[] p = null;
    int q = 136 - (m % 136); // number of padding bytes
    //System.out.println("Pad q: " + q + "  m: " + m);
    if(q == 136) { // Whole block is padding
        p = new byte[136];
        p[7] = (byte) 0x01;
        p[135] = (byte) 0x80;
    }
    else { // Ignore for now
        p = new byte[q];
        p[0] = 1;
    }
    return p;
}
这是我的keccak排列代码:

public long[][] keccakF1600(long[][] A) { // KECCAK-f where b = 1600
    for (int i = 0; i < 24; i++) { // 24 Rounds
        A = Round1600(A, RC[i]);
    }
    return A;
}

private long[][] Round1600(long[][] A, long rc) {
    // θ Step
    long[] C = new long[5];
    for (int x = 0; x < 5; x++) {
        C[x] = A[x][0] ^ A[x][1]^ A[x][2] ^ A[x][3] ^ A[x][4];
    }

    long[] D = new long[5];
    for (int x = 0; x < 5; x++) {
        D[x] = C[(x + 4) % 5] ^ Long.rotateLeft(C[(x + 1) % 5], 1);
    }
    for (int x = 0; x < 5; x++) {
        for (int y = 0; y < 5; y++) {
            A[x][y] = A[x][y] ^ D[x];
        }
    }

    // ρ and π steps
    long[][] B = new long[5][5];
    for (int x = 0; x < 5; x++) {
        for (int y = 0; y < 5; y++) {
            B[y][(2 * x + 3 * y) % 5] = Long.rotateLeft(A[x][y], rot_offset(x,y));
        }
    }

    // χ step
    for (int x = 0; x < 5; x++) {
        for (int y = 0; y < 5; y++) {
            A[x][y] = B[x][y] ^ ((~B[(x+1) % 5][y]) & B[(x+2) % 5][y]);
        }
    }

    // ι step
    A[0][0] = A[0][0] ^ rc;

    return A;
}


private int rot_offset(int x, int y) {
    switch (x){
        case 0:
            switch (y) {
                case 0:
                    return 0;
                case 1:
                    return 36;
                case 2:
                    return 3;
                case 3:
                    return 41;
                case 4:
                    return 18;
            }
        case 1:
            switch (y) {
                case 0:
                    return 1;
                case 1:
                    return 44;
                case 2:
                    return 10;
                case 3:
                    return 45;
                case 4:
                    return 2;
            }
        case 2:
            switch (y) {
                case 0:
                    return 62;
                case 1:
                    return 6;
                case 2:
                    return 43;
                case 3:
                    return 15;
                case 4:
                    return 61;
            }
        case 3:
            switch (y) {
                case 0:
                    return 28;
                case 1:
                    return 55;
                case 2:
                    return 25;
                case 3:
                    return 21;
                case 4:
                    return 56;
            }
        case 4:
            switch (y) {
                case 0:
                    return 27;
                case 1:
                    return 20;
                case 2:
                    return 39;
                case 3:
                    return 8;
                case 4:
                    return 14;
            }
    }
    System.out.println("Should not Happen!");
    return -1; // Should not happen!
}
public long[]keccakF1600(long[]A){//KECCAK-f其中b=1600
对于(int i=0;i<24;i++){//24轮
A=整数1600(A,RC[i]);
}
返回A;
}
专用长[][]Round1600(长[][]A,长rc){
//θ阶跃
long[]C=新长[5];
对于(int x=0;x<5;x++){
C[x]=A[x][0]^A[x][1]^A[x][2]^A[x][3]^A[x][4];
}
长[]D=新长[5];
对于(int x=0;x<5;x++){
D[x]=C[(x+4)%5]^Long.rotateLeft(C[(x+1)%5],1);
}
对于(int x=0;x<5;x++){
对于(int y=0;y<5;y++){
A[x][y]=A[x][y]^D[x];
}
}
//ρ和π步
long[]B=新的long[5][5];
对于(int x=0;x<5;x++){
对于(int y=0;y<5;y++){
B[y][(2*x+3*y)%5]=长旋转英尺(A[x][y],旋转偏移(x,y));
}
}
//χ步
对于(int x=0;x<5;x++){
对于(int y=0;y<5;y++){
A[x][y]=B[x][y]^(~B[(x+1)%5][y])&B[(x+2)%5][y]);
}
}
//ι步
[0][0]=A[0][0]^rc;
返回A;
}
专用整数旋转偏移量(整数x,整数y){
开关(x){
案例0:
开关(y){
案例0:
返回0;
案例1:
返回36;
案例2:
返回3;
案例3:
返回41;
案例4:
返回18;
}
案例1:
开关(y){
案例0:
返回1;
案例1:
返回44;
案例2:
返回10;
案例3:
返回45;
案例4:
返回2;
}
案例2:
开关(y){
案例0:
返回62;
案例1:
返回6;
案例2:
返回43;
案例3:
返回15;
案例4:
返回61;
}
案例3:
开关(y){
案例0:
返回28;
案例1:
返回55;
案例2:
返回25;
案例3:
返回21;
案例4:
返回56;
}
案例4:
开关(y){
案例0:
返回27;
案例1:
返回20;
案例2:
返回39;
案例3:
返回8;
案例4:
返回14;
}
}
System.out.println(“不应该发生!”);
return-1;//不应该发生!
}
最后,帮助器方法将字节[]转换为long和back:

public static long decodeLELong(byte[] buf, int off)
{
    return (buf[off + 0] & 0xFFL)
            | ((buf[off + 1] & 0xFFL) << 8)
            | ((buf[off + 2] & 0xFFL) << 16)
            | ((buf[off + 3] & 0xFFL) << 24)
            | ((buf[off + 4] & 0xFFL) << 32)
            | ((buf[off + 5] & 0xFFL) << 40)
            | ((buf[off + 6] & 0xFFL) << 48)
            | ((buf[off + 7] & 0xFFL) << 56);
}
public static byte[] encodeLELong(long val)
{
    byte[] buf = new byte[8];
    buf[0] = (byte)val;
    buf[1] = (byte)(val >>> 8);
    buf[2] = (byte)(val >>> 16);
    buf[3] = (byte)(val >>> 24);
    buf[4] = (byte)(val >>> 32);
    buf[5] = (byte)(val >>> 40);
    buf[6] = (byte)(val >>> 48);
    buf[7] = (byte)(val >>> 56);
    return buf;
}
公共静态长解码长(字节[]buf,int off)
{
返回(buf[off+0]&0xFFL)
|((buf[off+1]&0xFFL)>>24);
buf[4]=(字节)(val>>>32);
buf[5]=(字节)(val>>>40);
buf[6]=(字节)(val>>>48);
buf[7]=(字节)(val>>>56);
返回buf;
}
concatBytes的最后一个帮助程序方法:

public static byte[] concatBytes(byte[] in1, byte[] in2) {
    byte[] output = new byte[in1.length + in2.length];
    for (int i = 0; i < in1.length; i++) {
        output[i] = in1[i];
    }
    for (int i = 0; i < in2.length; i++) {
        output[i + in1.length] = in2[i];
    }
    return output;
}
公共静态字节[]concatBytes(字节[]in1,字节[]in2){
字节[]输出=新字节[in1.length+in2.length];
for(inti=0;i
一般来说,您需要在问题中包含代码的相关部分。代码链接的问题在于,链接最终会失效,而当这种情况发生时,这个问题就会成为Stackoverflow归档中的另一个污染物。我明白,要知道发布什么和遗漏什么是很有挑战性的,只要尽你最大的努力。您可以保留到Github的链接,只是问题不应该完全依赖于该链接;这是
p[135]
而不是
p[128]
。我没有看其余的。@PresidentJamesK.Polk很高兴知道。我将编辑帖子以添加代码的其他重要部分。好的,我现在知道我的keccak排列的Round1600函数是正确的,因为我已经将Bouncing Castle的排列代码复制到我的代码中,并得到了相同的哈希值。这意味着误差在填充、吸收或挤压阶段的某个地方