private byte[] getHash(byte[] data, boolean nullData) {
        int byteLen = data.length;
        int intLen = ((byteLen + 9 + 63) / 64) * 16;
        byte[] bytes = new byte[intLen * 4];
        System.arraycopy(data, 0, bytes, 0, byteLen);
        if (nullData) {
            Arrays.fill(data, (byte) 0);
        }
        bytes[byteLen] = (byte) 0x80;
        int[] buff = new int[intLen];
        for (int i = 0, j = 0; j < intLen; i += 4, j++) {
            buff[j] = readInt(bytes, i);
        }
        buff[intLen - 2] = byteLen >>> 29;
        buff[intLen - 1] = byteLen << 3;
        int[] w = new int[64];
        int[] hh = {0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
            0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19};
        for (int block = 0; block < intLen; block += 16) {
            for (int i = 0; i < 16; i++) {
                w[i] = buff[block + i];
            }
            for (int i = 16; i < 64; i++) {
                int x = w[i - 2];
                int theta1 = rot(x, 17) ^ rot(x, 19) ^ (x >>> 10);
                x = w[i - 15];
                int theta0 = rot(x, 7) ^ rot(x, 18) ^ (x >>> 3);
                w[i] = theta1 + w[i - 7] + theta0 + w[i - 16];
            }

            int a = hh[0], b = hh[1], c = hh[2], d = hh[3];
            int e = hh[4], f = hh[5], g = hh[6], h = hh[7];

            for (int i = 0; i < 64; i++) {
                int t1 = h + (rot(e, 6) ^ rot(e, 11) ^ rot(e, 25))
                        + ((e & f) ^ ((~e) & g)) + K[i] + w[i];
                int t2 = (rot(a, 2) ^ rot(a, 13) ^ rot(a, 22))
                        + ((a & b) ^ (a & c) ^ (b & c));
                h = g;
                g = f;
                f = e;
                e = d + t1;
                d = c;
                c = b;
                b = a;
                a = t1 + t2;
            }
            hh[0] += a;
            hh[1] += b;
            hh[2] += c;
            hh[3] += d;
            hh[4] += e;
            hh[5] += f;
            hh[6] += g;
            hh[7] += h;
        }
        byte[] result = new byte[32];
        for (int i = 0; i < 8; i++) {
            writeInt(result, i * 4, hh[i]);
        }
        Arrays.fill(w, 0);
        Arrays.fill(buff, 0);
        Arrays.fill(hh, 0);
        Arrays.fill(bytes, (byte) 0);
        return result;
    }