⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 whirlpool.java

📁 磁盘格式解读
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
        Arrays.fill(bitLength, (byte)0);
        bufferBits = bufferPos = 0;
        buffer[0] = 0; // it's only necessary to cleanup buffer[bufferPos].
        Arrays.fill(hash, 0L); // initial value
    }

    /**
     * Delivers input data to the hashing algorithm.
     * 
     * @param    source        plaintext data to hash.
     * @param    sourceBits    how many bits of plaintext to process.
     * 
     * This method maintains the invariant: bufferBits < 512
     */
    public void NESSIEadd(byte[] source, long sourceBits) {
        /*
                           sourcePos
                           |
                           +-------+-------+-------
                              ||||||||||||||||||||| source
                           +-------+-------+-------
        +-------+-------+-------+-------+-------+-------
        ||||||||||||||||||||||                           buffer
        +-------+-------+-------+-------+-------+-------
                        |
                        bufferPos
        */
        int sourcePos = 0; // index of leftmost source byte containing data (1 to 8 bits).
        int sourceGap = (8 - ((int)sourceBits & 7)) & 7; // space on source[sourcePos].
        int bufferRem = bufferBits & 7; // occupied bits on buffer[bufferPos].
        int b;
        // tally the length of the added data:
        long value = sourceBits;
        for (int i = 31, carry = 0; i >= 0; i--) {
            carry += (bitLength[i] & 0xff) + ((int)value & 0xff);
            bitLength[i] = (byte)carry;
            carry >>>= 8;
            value >>>= 8;
        }
        // process data in chunks of 8 bits:
        while (sourceBits > 8) { // at least source[sourcePos] and source[sourcePos+1] contain data.
            // take a byte from the source:
            b = ((source[sourcePos] << sourceGap) & 0xff) |
                ((source[sourcePos + 1] & 0xff) >>> (8 - sourceGap));
            if (b < 0 || b >= 256) {
                throw new RuntimeException("LOGIC ERROR");
            }
            // process this byte:
            buffer[bufferPos++] |= b >>> bufferRem;
            bufferBits += 8 - bufferRem; // bufferBits = 8*bufferPos;
            if (bufferBits == 512) {
                // process data block:
                processBuffer();
                // reset buffer:
                bufferBits = bufferPos = 0;
            }
            buffer[bufferPos] = (byte)((b << (8 - bufferRem)) & 0xff);
            bufferBits += bufferRem;
            // proceed to remaining data:
            sourceBits -= 8;
            sourcePos++;
        }
        // now 0 <= sourceBits <= 8;
        // furthermore, all data (if any is left) is in source[sourcePos].
        if (sourceBits > 0) {
            b = (source[sourcePos] << sourceGap) & 0xff; // bits are left-justified on b.
            // process the remaining bits:
            buffer[bufferPos] |= b >>> bufferRem;
        } else {
            b = 0;
        }
        if (bufferRem + sourceBits < 8) {
            // all remaining data fits on buffer[bufferPos], and there still remains some space.
            bufferBits += sourceBits;
        } else {
            // buffer[bufferPos] is full:
            bufferPos++;
            bufferBits += 8 - bufferRem; // bufferBits = 8*bufferPos;
            sourceBits -= 8 - bufferRem;
            // now 0 <= sourceBits < 8; furthermore, all data is in source[sourcePos].
            if (bufferBits == 512) {
                // process data block:
                processBuffer();
                // reset buffer:
                bufferBits = bufferPos = 0;
            }
            buffer[bufferPos] = (byte)((b << (8 - bufferRem)) & 0xff);
            bufferBits += (int)sourceBits;
        }
    }

    /**
     * Get the hash value from the hashing state.
     * 
     * This method uses the invariant: bufferBits < 512
     */
    public void NESSIEfinalize(byte[] digest) {
        // append a '1'-bit:
        buffer[bufferPos] |= 0x80 >>> (bufferBits & 7);
        bufferPos++; // all remaining bits on the current byte are set to zero.
        // pad with zero bits to complete 512N + 256 bits:
        if (bufferPos > 32) {
            while (bufferPos < 64) {
                buffer[bufferPos++] = 0;
            }
            // process data block:
            processBuffer();
            // reset buffer:
            bufferPos = 0;
        }
        while (bufferPos < 32) {
            buffer[bufferPos++] = 0;
        }
        // append bit length of hashed data:
        System.arraycopy(bitLength, 0, buffer, 32, 32);
        // process data block:
        processBuffer();
        // return the completed message digest:
        for (int i = 0, j = 0; i < 8; i++, j += 8) {
            long h = hash[i];
            digest[j    ] = (byte)(h >>> 56);
            digest[j + 1] = (byte)(h >>> 48);
            digest[j + 2] = (byte)(h >>> 40);
            digest[j + 3] = (byte)(h >>> 32);
            digest[j + 4] = (byte)(h >>> 24);
            digest[j + 5] = (byte)(h >>> 16);
            digest[j + 6] = (byte)(h >>>  8);
            digest[j + 7] = (byte)(h       );
        }
    }

    /**
     * Delivers string input data to the hashing algorithm.
     * 
     * @param    source        plaintext data to hash (ASCII text string).
     * 
     * This method maintains the invariant: bufferBits < 512
     */
    public void NESSIEadd(String source) {
        if (source.length() > 0) {
            byte[] data = new byte[source.length()];
            for (int i = 0; i < source.length(); i++) {
                data[i] = (byte)source.charAt(i);
            }
            NESSIEadd(data, 8*data.length);
        }
    }

    private static String display(byte[] array) {
        char[] val = new char[2*array.length];
        String hex = "0123456789ABCDEF";
        for (int i = 0; i < array.length; i++) {
            int b = array[i] & 0xff;
            val[2*i] = hex.charAt(b >>> 4);
            val[2*i + 1] = hex.charAt(b & 15);
        }
        return String.valueOf(val);
    }

    private static final int LONG_ITERATION = 100000000;

    /**
     * Generate the NESSIE test vector set for Whirlpool.
     *
     * The test consists of:
     * 1. hashing all bit strings containing only zero bits
     *    for all lengths from 0 to 1023;
     * 2. hashing all 512-bit strings containing a single set bit;
     * 3. the iterated hashing of the 512-bit string of zero bits a large number of times.
     */
    public static void makeNESSIETestVectors() {
        Whirlpool w = new Whirlpool();
        byte[] digest = new byte[64];
        byte[] data = new byte[128];
        Arrays.fill(data, (byte)0);
        System.out.println("Message digests of strings of 0-bits and length L:");
        for (int i = 0; i < 1024; i++) {
            w.NESSIEinit();
            w.NESSIEadd(data, i);
            w.NESSIEfinalize(digest);
            String s = Integer.toString(i);
            s = "     ".substring(s.length()) + s;
            System.out.println("    L =" + s + ": " + display(digest));
        }
        System.out.println("Message digests of all 512-bit strings S containing a single 1-bit:");
        data = new byte[512/8];
        Arrays.fill(data, (byte)0);
        for (int i = 0; i < 512; i++) {
            // set bit i:
            data[i/8] |= 0x80 >>> (i % 8);
            w.NESSIEinit();
            w.NESSIEadd(data, 512);
            w.NESSIEfinalize(digest);
            System.out.println("    S = " + display(data) + ": " + display(digest));
            // reset bit i:
            data[i/8] = 0;
        }
        for (int i = 0; i < digest.length; i++) {
            digest[i] = 0;
        }
        for (int i = 0; i < LONG_ITERATION; i++) {
            w.NESSIEinit();
            w.NESSIEadd(digest, 512);
            w.NESSIEfinalize(digest);
        }
        System.out.println("Iterated message digest computation (" + LONG_ITERATION + " times): " + display(digest));
    }

    /**
     * Generate the ISO/IEC 10118-3 test vector set for Whirlpool.
     */
    public static void makeISOTestVectors() {
        Whirlpool w = new Whirlpool();
        byte[] digest = new byte[DIGESTBYTES];
        byte[] data = new byte[1000000];

        Arrays.fill(data, (byte)0);

        System.out.println("1. In this example the data-string is the empty string, i.e. the string of length zero.\n");
        w.NESSIEinit();
        w.NESSIEfinalize(digest);
        System.out.println("The hash-code is the following 512-bit string.\n\n" + display(digest) + "\n");

        System.out.println("2. In this example the data-string consists of a single byte, namely the ASCII-coded version of the letter 'a'.\n");
        w.NESSIEinit();
        w.NESSIEadd("a");
        w.NESSIEfinalize(digest);
        System.out.println("The hash-code is the following 512-bit string.\n\n" + display(digest) + "\n");

        System.out.println("3. In this example the data-string is the three-byte string consisting of the ASCII-coded version of 'abc'.\n");
        w.NESSIEinit();
        w.NESSIEadd("abc");
        w.NESSIEfinalize(digest);
        System.out.println("The hash-code is the following 512-bit string.\n\n" + display(digest) + "\n");

        System.out.println("4. In this example the data-string is the 14-byte string consisting of the ASCII-coded version of 'message digest'.\n");
        w.NESSIEinit();
        w.NESSIEadd("message digest");
        w.NESSIEfinalize(digest);
        System.out.println("The hash-code is the following 512-bit string.\n\n" + display(digest) + "\n");

        System.out.println("5. In this example the data-string is the 26-byte string consisting of the ASCII-coded version of 'abcdefghijklmnopqrstuvwxyz'.\n");
        w.NESSIEinit();
        w.NESSIEadd("abcdefghijklmnopqrstuvwxyz");
        w.NESSIEfinalize(digest);
        System.out.println("The hash-code is the following 512-bit string.\n\n" + display(digest) + "\n");

        System.out.println("6. In this example the data-string is the 62-byte string consisting of the ASCII-coded version of 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'.\n");
        w.NESSIEinit();
        w.NESSIEadd("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
        w.NESSIEfinalize(digest);
        System.out.println("The hash-code is the following 512-bit string.\n\n" + display(digest) + "\n");

        System.out.println("7. In this example the data-string is the 80-byte string consisting of the ASCII-coded version of eight repetitions of '1234567890'.\n");
        w.NESSIEinit();
        w.NESSIEadd("12345678901234567890123456789012345678901234567890123456789012345678901234567890");
        w.NESSIEfinalize(digest);
        System.out.println("The hash-code is the following 512-bit string.\n\n" + display(digest) + "\n");

        System.out.println("8. In this example the data-string is the 32-byte string consisting of the ASCII-coded version of 'abcdbcdecdefdefgefghfghighijhijk'.\n");
        w.NESSIEinit();
        w.NESSIEadd("abcdbcdecdefdefgefghfghighijhijk");
        w.NESSIEfinalize(digest);
        System.out.println("The hash-code is the following 512-bit string.\n\n" + display(digest) + "\n");

        Arrays.fill(data, (byte)'a');
        System.out.println("9. In this example the data-string is the 1000000-byte string consisting of the ASCII-coded version of 'a' repeated 10^6 times.\n");
        w.NESSIEinit();
        w.NESSIEadd(data, 8*1000000);
        w.NESSIEfinalize(digest);
        System.out.println("The hash-code is the following 512-bit string.\n\n" + display(digest) + "\n");
    }

    public static void main(String[] args) {
        //makeNESSIETestVectors();
        makeISOTestVectors();
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -