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

📄 square.java

📁 另一个使用java编写的加密通用算法包
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
    public final Object clone() throws CloneNotSupportedException {        throw new CloneNotSupportedException();    }// Implementation of JCE methods//............................................................................        /**     * <b>SPI</b>: Returns the length of an input block, in bytes.     *     * @return the length in bytes of an input block for this cipher.     */    public int engineBlockSize() { return BLOCK_SIZE; }    /**     * <b>SPI</b>: Initializes this cipher for encryption, using the     * specified key.     *     * @param  key  the key to use for encryption.     * @exception InvalidKeyException when one of the following occurs: <ul>     *                <li> key.getEncoded() == null;     *                <li> The encoded byte array form of the key is zero-length;     *                <li> The length of the user key data array is out of the     *                permissible limits.     *              </ul>     */    protected void engineInitEncrypt(Key key)    throws InvalidKeyException {        makeKey(key, true);    }    /**     * <b>SPI</b>: Initializes this cipher for decryption, using the     * specified key.     *     * @param  key  the key to use for decryption.     * @exception InvalidKeyException when one of the following occurs: <ul>     *                <li> key.getEncoded() == null;     *                <li> The encoded byte array form of the key is zero-length;     *                <li> The length of the user key data array is out of the     *                permissible limits.     *              </ul>     */    protected void engineInitDecrypt(Key key)    throws InvalidKeyException {        makeKey(key, false);    }    /**     * <b>SPI</b>: This is the main engine method for updating data.     * <p>     * <i>in</i> and <i>out</i> may be the same array, and the input and output     * regions may overlap.     *     * @param  in           the input data.     * @param  inOffset     the offset into in specifying where the data starts.     * @param  inLen        the length of the subarray.     * @param  out          the output array.     * @param  outOffset    the offset indicating where to start writing into     *                      the out array.     * @return the number of bytes written.     * @exception CryptixException if the native library is being used, and it     *                      reports an error.     */    protected int    engineUpdate(byte[] in, int inOffset, int inLen, byte[] out, int outOffset) {        if (inLen < 0) throw new IllegalArgumentException("inLen < 0");        int blockCount = inLen / BLOCK_SIZE;        inLen = blockCount * BLOCK_SIZE;        boolean doEncrypt = (getState() == ENCRYPT);        // Avoid overlapping input and output regions.        if (in == out && (outOffset >= inOffset && outOffset < (long)inOffset+inLen ||                          inOffset >= outOffset && inOffset < (long)outOffset+inLen)) {            byte[] newin = new byte[inLen];            System.arraycopy(in, inOffset, newin, 0, inLen);            in = newin;            inOffset = 0;        }        if (native_lock != null) {            synchronized(native_lock) {                // If in == null || out == 0, evaluating their lengths will throw a                // NullPointerException.                if (inOffset < 0 || (long)inOffset + inLen > in.length ||                    outOffset < 0 || (long)outOffset + inLen > out.length)                    throw new ArrayIndexOutOfBoundsException(getAlgorithm() +                        ": Arguments to native_crypt would cause a buffer overflow");                // In future, we may pass more than one block to native_crypt to reduce                // native method overhead.                for (int i = 0; i < blockCount; i++) {                    if (0 == native_crypt(native_cookie, in, inOffset, out, outOffset,                                          doEncrypt))                        throw new CryptixException(getAlgorithm() + ": Error in native code");                    inOffset += BLOCK_SIZE;                    outOffset += BLOCK_SIZE;                }            }        } else if (doEncrypt) { // state == ENCRYPT            for (int i = 0; i < blockCount; i++) {                square(in, inOffset, out, outOffset, TE, SE);                inOffset += BLOCK_SIZE;                outOffset += BLOCK_SIZE;            }        } else {                // state == DECRYPT            for (int i = 0; i < blockCount; i++) {                square(in, inOffset, out, outOffset, TD, SD);                inOffset += BLOCK_SIZE;                outOffset += BLOCK_SIZE;            }        }        return inLen;    }// Own methods//............................................................................    /**     * Expands a user-key to a working key schedule.     *     * @param  key          the user-key object to use.     * @param  doEncrypt    true for encryption, false for decryption.     * @exception InvalidKeyException if one of the following occurs: <ul>     *                <li> key.getEncoded() == null;     *                <li> The length of the user key array is not KEY_LENGTH.     *              </ul>     */    private void makeKey(Key key, boolean doEncrypt)    throws InvalidKeyException {        byte[] userkey = key.getEncoded();        if (userkey == null)            throw new InvalidKeyException(getAlgorithm() + ": Null user key");        if (userkey.length != BLOCK_SIZE)            throw new InvalidKeyException(getAlgorithm() + ": Invalid user key length");        // If native library available then use it. If not or if        // native method returned error then revert to 100% Java.        if (native_lock != null) {            synchronized(native_lock) {                try {//                    linkStatus.check(native_ks(native_cookie, userkey, doEncrypt));                    linkStatus.check(native_ks(native_cookie, userkey));                    return;                } catch (Error error) {                    native_finalize();                    native_lock = null;if (DEBUG && debuglevel > 0) debug(error + ". Will use 100% Java.");                }            }        }        int i, j = 0;        if (doEncrypt) {            for (i = 0; i < 4; i++)                sKey[0][i] = (userkey[j++] & 0xFF) << 24 | (userkey[j++] & 0xFF) << 16 |                             (userkey[j++] & 0xFF) <<  8 | (userkey[j++] & 0xFF);            for (i = 1; i < R + 1; i++) {                j = i - 1;                sKey[i][0] = sKey[j][0] ^ rot32L(sKey[j][3], 8) ^ OFFSET[j];                sKey[i][1] = sKey[j][1] ^ sKey[i][0];                sKey[i][2] = sKey[j][2] ^ sKey[i][1];                sKey[i][3] = sKey[j][3] ^ sKey[i][2];                         transform(sKey[j], sKey[j]);            }        } else {            int[][] tKey = new int[R + 1][4];            // apply the key evolution function            for (i = 0; i < 4; i++)                tKey[0][i] = (userkey[j++] & 0xFF) << 24 | (userkey[j++] & 0xFF) << 16 |                             (userkey[j++] & 0xFF) <<  8 | (userkey[j++] & 0xFF);            for (i = 1; i < R + 1; i++) {                j = i - 1;                tKey[i][0] = tKey[j][0] ^ rot32L(tKey[j][3], 8) ^ OFFSET[j];                tKey[i][1] = tKey[j][1] ^ tKey[i][0];                tKey[i][2] = tKey[j][2] ^ tKey[i][1];                tKey[i][3] = tKey[j][3] ^ tKey[i][2];            }            for (i = 0; i < R; i++)                System.arraycopy(tKey[R - i], 0, sKey[i], 0, 4);            transform(tKey[0], sKey[R]);        }    }    /**     * Applies the Theta function to an input <i>in</i> in order to     * produce in <i>out</i> an internal session sub-key.     * <p>     * Both <i>in</i> and <i>out</i> are arrays of four ints.     * <p>     * Pseudo-code is:     * <pre>     *    for (i = 0; i < 4; i++) {     *        out[i] = 0;     *        for (j = 0, n = 24; j < 4; j++, n -= 8) {     *            k = mul(in[i] >>> 24, G[0][j]) ^     *                mul(in[i] >>> 16, G[1][j]) ^     *                mul(in[i] >>>  8, G[2][j]) ^     *                mul(in[i]       , G[3][j]);     *            out[i] ^= k << n;     *        }     *    }     * </pre>     */    private static void transform (int[] in, int[] out) {        int l3, l2, l1, l0, m;        for (int i = 0; i < 4; i++) {            l3 = in[i];            l2 = l3 >>>  8;            l1 = l3 >>> 16;            l0 = l3 >>> 24;            m  = ((mul(l0, 2) ^ mul(l1, 3) ^ l2 ^ l3) & 0xFF) << 24;            m ^= ((l0 ^ mul(l1, 2) ^ mul(l2, 3) ^ l3) & 0xFF) << 16;            m ^= ((l0 ^ l1 ^ mul(l2, 2) ^ mul(l3, 3)) & 0xFF) <<  8;            m ^= (mul(l0, 3) ^l1 ^ l2 ^ mul(l3, 2)  ) & 0xFF;            out[i] = m;        }    }    /**     * Left rotate a 32-bit chunk.     *     * @param  x    the 32-bit data to rotate     * @param  s    number of places to left-rotate by     * @return the newly permutated value.     */    private static int rot32L (int x, int s) { return x << s | x >>> (32 - s); }    /**     * Right rotate a 32-bit chunk.     *     * @param  x    the 32-bit data to rotate     * @param  s    number of places to right-rotate by     * @return the newly permutated value.     */    private static int rot32R (int x, int s) { return x >>> s | x << (32 - s); }    /**     * Returns the product of two binary numbers a and b, using     * the generator ROOT as the modulus: p = (a * b) mod ROOT.     * ROOT Generates a suitable Galois Field in GF(2 ** 8).     * <p>     * For best performance call it with abs(b) < abs(a).     *     * @param  a    operand for multiply.     * @param  b    operand for multiply.     * @return the result of (a * b) % ROOT.     */    private static final int mul (int a, int b) {        if (a == 0)            return 0;        a &= 0xFF;        b &= 0xFF;        int p = 0;        while (b != 0) {            if ((b & 0x01) != 0)                p ^= a;            a <<= 1;            if (a > 0xFF)                a ^= ROOT;            b >>>= 1;        }        return p & 0xFF;    }    /**     * Applies the Square algorithm (for both encryption and decryption since     * it is the same) on a 128-bit plain/cipher text into a same length cipher/     * plain text using the Square formulae, relevant sub-keys, transposition     * and S-Box values.     *     * @param  in       contains the plain-text 128-bit block.     * @param  off      start index within input where data is considered.     * @param  out      will contain the cipher-text block.     * @param  outOff   index in out where cipher-text starts.     * @param  T        reference to either the encryption (TE) or decryption     *                  (TD) transposition vector.     * @param  S        reference to either the encryption (SE) or decryption     *                  (SD) S-Box values.     */    private void    square (byte[] in, int off, byte[] out, int outOff, int[] T, byte[] S) {        int a = (in[off++] & 0xFF) << 24 | (in[off++] & 0xFF) << 16 |                (in[off++] & 0xFF) <<  8 | (in[off++] & 0xFF);        int b = (in[off++] & 0xFF) << 24 | (in[off++] & 0xFF) << 16 |                (in[off++] & 0xFF) <<  8 | (in[off++] & 0xFF);        int c = (in[off++] & 0xFF) << 24 | (in[off++] & 0xFF) << 16 |                (in[off++] & 0xFF) <<  8 | (in[off++] & 0xFF);        int d = (in[off++] & 0xFF) << 24 | (in[off++] & 0xFF) << 16 |                (in[off++] & 0xFF) <<  8 | (in[off++] & 0xFF);        int aa, bb, cc, dd;        int i, j, k;        a ^= sKey[0][0];        b ^= sKey[0][1];        c ^= sKey[0][2];        d ^= sKey[0][3];        // R - 1 full rounds        for (i = 1; i < R; i++) {            aa =       T[(a >>> 24) & 0xFF]      ^                rot32R(T[(b >>> 24) & 0xFF],  8) ^                rot32R(T[(c >>> 24) & 0xFF], 16) ^                rot32R(T[(d >>> 24) & 0xFF], 24) ^ sKey[i][0];            bb =       T[(a >>> 16) & 0xFF]      ^                rot32R(T[(b >>> 16) & 0xFF],  8) ^                rot32R(T[(c >>> 16) & 0xFF], 16) ^                rot32R(T[(d >>> 16) & 0xFF], 24) ^ sKey[i][1];            cc =       T[(a >>>  8) & 0xFF]      ^                rot32R(T[(b >>>  8) & 0xFF],  8) ^                rot32R(T[(c >>>  8) & 0xFF], 16) ^                rot32R(T[(d >>>  8) & 0xFF], 24) ^ sKey[i][2];            dd =       T[ a         & 0xFF]      ^                rot32R(T[ b         & 0xFF],  8) ^                rot32R(T[ c         & 0xFF], 16) ^                rot32R(T[ d         & 0xFF], 24) ^ sKey[i][3];            a = aa;            b = bb;            c = cc;            d = dd;        }        // last round (diffusion becomes only transposition)        for (i = 0, j = 24; i < 4; i++, j -= 8) {            k = (S[(a >>> j) & 0xFF] & 0xFF) << 24 |                (S[(b >>> j) & 0xFF] & 0xFF) << 16 |                (S[(c >>> j) & 0xFF] & 0xFF) <<  8 |                (S[(d >>> j) & 0xFF] & 0xFF);            k ^= sKey[R][i];            out[outOff++] = (byte)((k >>> 24) & 0xFF);            out[outOff++] = (byte)((k >>> 16) & 0xFF);            out[outOff++] = (byte)((k >>>  8) & 0xFF);            out[outOff++] = (byte) (k         & 0xFF);        }    }// Test methods//...........................................................................    static final private String[][] tests = {        { "000102030405060708090a0b0c0d0e0f",   // KEY          "000102030405060708090a0b0c0d0e0f",   // PLAINTEXT          "7C3491D94994E70F0EC2E7A5CCB5A14F"},  // CIPHERTEXT                 { "000102030405060708090a0b0c0d0e0f",          "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f",          "7C3491D94994E70F0EC2E7A5CCB5A14F7C3491D94994E70F0EC2E7A5CCB5A14F"}    };    public static final void main (String[] args) {        try { self_test(); }        catch (Exception e) { e.printStackTrace(); }    }        private static void self_test()    throws Exception {        Cipher cryptor = Cipher.getInstance("Square", "Cryptix");        RawSecretKey userKey;        byte[] tmp, pt, ct;        for (int i = 0; i < tests.length; i++) {            userKey = new RawSecretKey("Square", Hex.fromString(tests[i][0]));            pt = Hex.fromString(tests[i][1]);            ct = Hex.fromString(tests[i][2]);            cryptor.initEncrypt(userKey);            tmp = cryptor.crypt(pt);            if (!ArrayUtil.areEqual(ct, tmp)) {                System.out.println("     input: " + Hex.toString(pt));                System.out.println("  computed: " + Hex.toString(tmp));                System.out.println(" certified: " + Hex.toString(ct));                throw new CryptixException("encrypt #"+ i +" failed");            }            cryptor.initDecrypt(userKey);            tmp = cryptor.crypt(ct);            if (!ArrayUtil.areEqual(pt, tmp))                throw new CryptixException("decrypt #"+ i +" failed");        }if (DEBUG && debuglevel > 0) debug("Self-test OK");    }}

⌨️ 快捷键说明

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