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

📄 blowfish.java

📁 另一个使用java编写的加密通用算法包
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
            L ^= (((S[(R >>> 24) & 0xFF] + S[256 + ((R >>> 16) & 0xFF)]) ^ S[512 + ((R >>>  8) & 0xFF)]) + S[768 + (R & 0xFF)]) ^ K1;            R ^= K0;        }        out[outOff++] = (byte)(R >>> 24);        out[outOff++] = (byte)(R >>> 16);        out[outOff++] = (byte)(R >>>  8);        out[outOff++] = (byte) R;        out[outOff++] = (byte)(L >>> 24);        out[outOff++] = (byte)(L >>> 16);        out[outOff++] = (byte)(L >>>  8);        out[outOff  ] = (byte) L;    }    /**     * Expands a user-key to a working Blowfish P array (P) and S-box     * data (S).     * <p>     * The key bytes are first extracted from the user-key and then     * used, repetitively if need be, to build the contents of this     * key schedule and S-box values.     * <p>     * The Blowfish algorithm uses a single key schedule for both encryption     * and decryption. The process (key byte values and algorithm formulae)     * are used in one direction during encryption and simply reversed     * during decryption.     *     * @param  key  the user-key object to use.     * @exception InvalidKeyException if one of the following occurs: <ul>     *                <li> key.getEncoded() == null;     *                <li> key.getEncoded().length is invalid.     *              </ul>     * @exception CryptixException if any one of the two self-tests fail.     *              The two self-tests are as follows: <ol>     *                <li> encrypt 0 ten times using the initial S and P boxes     *                     values. Check the result against a known value. If equal     *                     decrypt the result 10 times and compare it to 0;     *                <li> complete the key expansion process and use the newly     *                     formed key to encrypt 10 times 0; decrypt the result 10     *                     times and compare.     *              </ol>     */    private void makeKey (Key key)    throws InvalidKeyException, CryptixException    {        byte[] userkey = key.getEncoded();        if (userkey == null)            throw new InvalidKeyException(getAlgorithm() + ": Null user key");        int len = userkey.length;        if (len < MIN_USER_KEY_LENGTH || len > MAX_USER_KEY_LENGTH)            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, rounds));                    return;                } catch (Error error) {                    native_finalize();                    native_lock = null;if (DEBUG && debuglevel > 0) debug(error + ". Will use 100% Java.");                }            }        }        System.arraycopy(S0, 0, S,   0, 256);        System.arraycopy(S1, 0, S, 256, 256);        System.arraycopy(S2, 0, S, 512, 256);        System.arraycopy(S3, 0, S, 768, 256);        System.arraycopy(P0, 0, P, 0, rounds + 2);        //        // Self test #1        // 1. Encrypt 0 ten times using initial S-Boxes and a zero-value key.        //    Check result against pre-computed value.        // 2. Decrypt it 10 times and check if == 0.        //        int[] block = {0, 0};        int st = 0;        for (st = 0; st < 10; st++)            BF_encrypt(block[0], block[1], block, 0);        if (block[0] != 0xAAFE4EBD || block[1] != 0x26D725FC)            throw new CryptixException(getAlgorithm() +                ": Self Test 1 failed: encrypt^10(0) = " + Hex.toString(block));if (DEBUG && debuglevel >= 3) debug("Self Test 1 Good");        while (--st >= 0)            BF_decrypt(block[0], block[1], block, 0);        if (block[0] != 0 || block[1] != 0)            throw new CryptixException(getAlgorithm() +                ": Self Test 1 failed: decrypt^10(encrypt^10(0)) = " +                Hex.toString(block));//        if (len > MAX_USER_KEY_LENGTH) len = MAX_USER_KEY_LENGTH;        int ri;        for (int i = 0, j = 0; i < rounds + 2; i++) {            ri = 0;            for (int k = 0; k < 4; k++) {                ri = (ri << 8) | (userkey[j++] & 0xFF);                j %= len;            }            P[i] ^= ri;        }        // use the former to effectively generate the P-array for this key        BF_encrypt(0, 0, P, 0);        for (int i = 2; i < rounds + 2; i += 2)            BF_encrypt(P[i - 2], P[i - 1], P, i);        // and the S-boxes        BF_encrypt(P[rounds], P[rounds + 1], S, 0);        for (int i = 2; i < 1024; i += 2)            BF_encrypt(S[i - 2], S[i - 1], S, i);        //        // Self test #2        // Encrypt 0 ten times.  Decrypt it ten times.  Should be the same.        //        for (st = 0; st < 10; st++)            BF_encrypt(block[0], block[1], block, 0);        while (--st >= 0)            BF_decrypt(block[0], block[1], block, 0);        if (block[0] != 0 || block[1] != 0)            throw new CryptixException(getAlgorithm() +                ": Self Test 2 failed: decrypt^10(encrypt^10(0)) = " +                Hex.toString(block));if (DEBUG && debuglevel >= 3) debug("Self Test 2 Good");        if (rounds == DEFAULT_NOF_ROUNDS) {            // unfold the P array into individual Ki's.            K0 =  P[0];  K1 =  P[1];  K2 =  P[2];  K3 =  P[3];  K4 =  P[4];            K5 =  P[5];  K6 =  P[6];  K7 =  P[7];  K8 =  P[8];  K9 =  P[9];            K10 = P[10]; K11 = P[11]; K12 = P[12]; K13 = P[13]; K14 = P[14];            K15 = P[15]; K16 = P[16]; K17 = P[17];        }    }    /**     * See description in <code>blockEncrypt</code> above.     * <p>     * This method is only called by the <code>makeKey</code> method to     * generate the key schedule from user data. It outputs the result to an     * int array.     *     * @param L         left half (32-bit) of the plain text block.     * @param R         right half (32-bit) of the plain text block.     * @param out       the int array where the result will be saved.     * @param outOff    where the data starts in the byte array.     * @see #blockEncrypt     */    private void BF_encrypt (int L, int R, int[] out, int outOff)    {        L ^= P[0];        for (int i = 0; i < rounds; ) {            R ^= (((S[(L >>> 24) & 0xFF] + S[256 + ((L >>> 16) & 0xFF)]) ^ S[512 + ((L >>>  8) & 0xFF)]) + S[768 + (L & 0xFF)]) ^ P[++i];            L ^= (((S[(R >>> 24) & 0xFF] + S[256 + ((R >>> 16) & 0xFF)]) ^ S[512 + ((R >>>  8) & 0xFF)]) + S[768 + (R & 0xFF)]) ^ P[++i];        }        out[outOff++] = R ^ P[rounds + 1];        out[outOff  ] = L;    }    /**     * See description in <code>blockDecrypt</code> above.     * <p>     * This method is only called by the <code>makeKey</code> method during     * self-test operation.     *     * @param L         left half (32-bit) of the ciphertext block,     * @param R         right half (32-bit) of the ciphertext block.     * @param out       the int array where the result will be saved.     * @param outOff    where the data starts in the byte array.     * @see #blockDecrypt     */    private void BF_decrypt (int L, int R, int[] out, int outOff)    {        L ^= P[rounds + 1];        for (int i = rounds; i > 0; ) {            R ^= (((S[(L >>> 24) & 0xFF] + S[256 + ((L >>> 16) & 0xFF)]) ^ S[512 + ((L >>>  8) & 0xFF)]) + S[768 + (L & 0xFF)]) ^ P[i--];            L ^= (((S[(R >>> 24) & 0xFF] + S[256 + ((R >>> 16) & 0xFF)]) ^ S[512 + ((R >>>  8) & 0xFF)]) + S[768 + (R & 0xFF)]) ^ P[i--];        }        out[outOff++] = R ^ P[0];        out[outOff  ] = L;    }// Test methods//...........................................................................//// Don't expand this code please without thinking about it,// much better to write a separate program.//    /** Entry point for very basic <code>self_test</code>. */    public static void main(String[] args) {        try { self_test(); }        catch (Exception e) { e.printStackTrace(); }    }    /**     * This is (apparently) the official certification data.     * Use decimal as Java grumbles about hex values > 0x7F.     */    private static final byte[][][] tests = {      { // cert 1        { // key         97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110,         111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122        },        { 66, 76, 79, 87, 70, 73, 83, 72},  // plain        { 50, 78, -48, -2, -12, 19, -94, 3} // cipher      },      { // cert 2        {          87, 104, 111, 32, 105, 115, 32, 74, 111, 104, 110, 32, 71, 97, 108,          116, 63        },        { -2, -36, -70, -104, 118, 84, 50, 16},        { -52, -111, 115, 43, -128, 34, -10, -124}      },      { // cert 3 - Ayn Rand with 4th () and 8th (d) chars hi bit set.        { 65, 121, 110, -96, 82, 97, 110, -28}, // key        { -2, -36, -70, -104, 118, 84, 50, 16}, // plain        { -31, 19, -12, 16, 44, -4, -50, 67}    // cipher      }    };    /**     * Do some basic tests.     * Three of the certification data are included only, no output,     * success or exception.     * If you want more, write a test program!     *     * @see cryptix.examples.TestBlowfish     */    private static void self_test()    throws Exception {        Cipher cryptor = Cipher.getInstance("Blowfish", "Cryptix");        RawSecretKey userKey;        byte[] tmp;        for (int i = 0; i < tests.length; i++) {            userKey = new RawSecretKey("Blowfish", tests[i][0]);            cryptor.initEncrypt(userKey);            tmp = cryptor.crypt(tests[i][1]);            if (!ArrayUtil.areEqual(tests[i][2], tmp))                throw new CryptixException("encrypt #"+ i +" failed");            cryptor.initDecrypt(userKey);            tmp = cryptor.crypt(tests[i][2]);            if (!ArrayUtil.areEqual(tests[i][1], 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 + -