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

📄 blowfish.java

📁 另一个使用java编写的加密通用算法包
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
     * <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, rounds))                        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++) {                blockEncrypt(in, inOffset, out, outOffset);                inOffset += BLOCK_SIZE;                outOffset += BLOCK_SIZE;            }        } else {                // state == DECRYPT            for (int i = 0; i < blockCount; i++) {                blockDecrypt(in, inOffset, out, outOffset);                inOffset += BLOCK_SIZE;                outOffset += BLOCK_SIZE;            }        }        return inLen;    }    /**     * <b>SPI</b>: Sets the specified algorithm parameter to the specified     * value.     * <p>     * Blowfish has a single parameter, "rounds", which specifies the     * number of rounds for this instance as a decimal String.     *     * @param  param    the string name of the parameter.      * @param  value    the parameter value.     * @exception InvalidParameterException if param is an invalid     *                  parameter for this cipher implementation, the     *                  parameter is already set and cannot be set again, a     *                  security exception occurs, and so on.     * @exception InvalidParameterTypeException if value is of the wrong     *                  type.     */    protected void engineSetParameter(String param, Object value)    throws InvalidParameterException, InvalidParameterTypeException {        if (!(value instanceof String))            throw new InvalidParameterTypeException(getAlgorithm() +                ": value is not a String");        try {            if (param.equals("rounds"))                setRounds(Integer.parseInt((String) value));        }        catch (Exception e) {            throw new InvalidParameterException(e.toString());        }        throw new InvalidParameterException(getAlgorithm() + ": " + param);    }    /**     * <b>SPI</b>: Gets the value of the specified algorithm parameter.     * <p>     * Blowfish has a single parameter, "rounds", which specifies the     * number of rounds for this instance as a decimal String.     *     * @param  param    the string name of the parameter.      * @return the object that represents the parameter value, or null if there     *                  is none.     */    protected Object engineGetParameter(String param) {        if (param.equals("rounds")) return Integer.toString(rounds);        return null;    }// Own methods//...........................................................................    /**     * Sets the number of rounds for this cipher. Allowed only when this     * cipher is in the UNINITIALIZED state; otherwise an exception is     * thrown.     * <p>     * If the specified number is invalid, an IllegalArgumentException is     * thrown.     * <p>     * Note that there is not enough defined initial data for any number     * of rounds other than 16 for the time being.     *     * @param  r    the desired number of rounds for this cipher.     * @throw IllegalStateException if this cipher is not uninitialised.     * @exception IllegalArgumentException if the given number of rounds is     *              not supported.     */    public void setRounds(int r) {        if (getState() != UNINITIALIZED)            throw new IllegalStateException(getAlgorithm() +                ": Cipher not in UNINITIALIZED state");        if (r < MIN_NOF_ROUNDS || r > MAX_NOF_ROUNDS)            throw new IllegalArgumentException(getAlgorithm() +                ": Invalid number of rounds");        rounds = r;    }    /**     * Returns the currently set number of rounds for this instance.     *     * @return the number of rounds.     */    public int getRounds() { return rounds; }    /**     * The normal entry to the encryption process. It is guaranteed     * to be called with enough bytes in the input to carry on an     * encryption of one full block.     * <p>     * The code of the Blowfish encryption engine, found here, is also     * replicated in the BF_encrypt method found later. The reason for     * this duplication is performance. This method outputs the result     * in a byte array form, suitable for the user data encryption     * operations, while BF_encrypt outputs its result as an int array     * suitable for, and used during, the expansion of the user-key into     * a Blowfish key schedule.     *     * @param  in       contains the input plaintext.     * @param  off      index of in from which to start considering data.     * @param  out      will contain the ciphertext block.     * @param  outOff   index of out where the ciphertext will start.     */    private void blockEncrypt (byte[] in, int off, byte[] out, int outOff)    {        int L = (in[off++] & 0xFF) << 24 |                (in[off++] & 0xFF) << 16 |                (in[off++] & 0xFF) <<  8 |                (in[off++] & 0xFF);        int R = (in[off++] & 0xFF) << 24 |                (in[off++] & 0xFF) << 16 |                (in[off++] & 0xFF) <<  8 |                (in[off  ] & 0xFF);        if (rounds != DEFAULT_NOF_ROUNDS) {            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];            }            R ^= P[rounds + 1];        } else {            L ^= K0;            R ^= (((S[(L >>> 24) & 0xFF] + S[256 + ((L >>> 16) & 0xFF)]) ^ S[512 + ((L >>>  8) & 0xFF)]) + S[768 + (L & 0xFF)]) ^ K1;            L ^= (((S[(R >>> 24) & 0xFF] + S[256 + ((R >>> 16) & 0xFF)]) ^ S[512 + ((R >>>  8) & 0xFF)]) + S[768 + (R & 0xFF)]) ^ K2;            R ^= (((S[(L >>> 24) & 0xFF] + S[256 + ((L >>> 16) & 0xFF)]) ^ S[512 + ((L >>>  8) & 0xFF)]) + S[768 + (L & 0xFF)]) ^ K3;            L ^= (((S[(R >>> 24) & 0xFF] + S[256 + ((R >>> 16) & 0xFF)]) ^ S[512 + ((R >>>  8) & 0xFF)]) + S[768 + (R & 0xFF)]) ^ K4;            R ^= (((S[(L >>> 24) & 0xFF] + S[256 + ((L >>> 16) & 0xFF)]) ^ S[512 + ((L >>>  8) & 0xFF)]) + S[768 + (L & 0xFF)]) ^ K5;            L ^= (((S[(R >>> 24) & 0xFF] + S[256 + ((R >>> 16) & 0xFF)]) ^ S[512 + ((R >>>  8) & 0xFF)]) + S[768 + (R & 0xFF)]) ^ K6;            R ^= (((S[(L >>> 24) & 0xFF] + S[256 + ((L >>> 16) & 0xFF)]) ^ S[512 + ((L >>>  8) & 0xFF)]) + S[768 + (L & 0xFF)]) ^ K7;            L ^= (((S[(R >>> 24) & 0xFF] + S[256 + ((R >>> 16) & 0xFF)]) ^ S[512 + ((R >>>  8) & 0xFF)]) + S[768 + (R & 0xFF)]) ^ K8;            R ^= (((S[(L >>> 24) & 0xFF] + S[256 + ((L >>> 16) & 0xFF)]) ^ S[512 + ((L >>>  8) & 0xFF)]) + S[768 + (L & 0xFF)]) ^ K9;            L ^= (((S[(R >>> 24) & 0xFF] + S[256 + ((R >>> 16) & 0xFF)]) ^ S[512 + ((R >>>  8) & 0xFF)]) + S[768 + (R & 0xFF)]) ^ K10;            R ^= (((S[(L >>> 24) & 0xFF] + S[256 + ((L >>> 16) & 0xFF)]) ^ S[512 + ((L >>>  8) & 0xFF)]) + S[768 + (L & 0xFF)]) ^ K11;            L ^= (((S[(R >>> 24) & 0xFF] + S[256 + ((R >>> 16) & 0xFF)]) ^ S[512 + ((R >>>  8) & 0xFF)]) + S[768 + (R & 0xFF)]) ^ K12;            R ^= (((S[(L >>> 24) & 0xFF] + S[256 + ((L >>> 16) & 0xFF)]) ^ S[512 + ((L >>>  8) & 0xFF)]) + S[768 + (L & 0xFF)]) ^ K13;            L ^= (((S[(R >>> 24) & 0xFF] + S[256 + ((R >>> 16) & 0xFF)]) ^ S[512 + ((R >>>  8) & 0xFF)]) + S[768 + (R & 0xFF)]) ^ K14;            R ^= (((S[(L >>> 24) & 0xFF] + S[256 + ((L >>> 16) & 0xFF)]) ^ S[512 + ((L >>>  8) & 0xFF)]) + S[768 + (L & 0xFF)]) ^ K15;            L ^= (((S[(R >>> 24) & 0xFF] + S[256 + ((R >>> 16) & 0xFF)]) ^ S[512 + ((R >>>  8) & 0xFF)]) + S[768 + (R & 0xFF)]) ^ K16;            R ^= K17;        }        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;    }    /**     * The normal entry to the decryption process. It is guaranteed     * to be called with enough bytes in the input to carry on a     * decryption of one full block.     * <p>     * Because the Blowfish cipher engine is designed to handle two     * 32-bit blocks, this method's purpose is to transform on entry     * and exit the data to/from 32-bit blocks; i.e. Java ints.     * <p>     * The input becomes two 32-bit blocks as Left and Right halves     * onto which the Blowfish cipher function is applied ROUNDS times     * in reverse order to that of the encryption.     *     * @param  in       contains the input plaintext.     * @param  off      index of in from which to start considering data.     * @param  out      will contain the ciphertext block.     * @param  outOff   index of out where the ciphertext will start.     */    private void blockDecrypt (byte[] in, int off, byte[] out, int outOff)    {        int L = (in[off++] & 0xFF) << 24 |                (in[off++] & 0xFF) << 16 |                (in[off++] & 0xFF) <<  8 |                (in[off++] & 0xFF);        int R = (in[off++] & 0xFF) << 24 |                (in[off++] & 0xFF) << 16 |                (in[off++] & 0xFF) <<  8 |                (in[off  ] & 0xFF);        if (rounds != DEFAULT_NOF_ROUNDS) {            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--];            }            R ^= P[0];        } else {            L ^= K17;            R ^= (((S[(L >>> 24) & 0xFF] + S[256 + ((L >>> 16) & 0xFF)]) ^ S[512 + ((L >>>  8) & 0xFF)]) + S[768 + (L & 0xFF)]) ^ K16;            L ^= (((S[(R >>> 24) & 0xFF] + S[256 + ((R >>> 16) & 0xFF)]) ^ S[512 + ((R >>>  8) & 0xFF)]) + S[768 + (R & 0xFF)]) ^ K15;            R ^= (((S[(L >>> 24) & 0xFF] + S[256 + ((L >>> 16) & 0xFF)]) ^ S[512 + ((L >>>  8) & 0xFF)]) + S[768 + (L & 0xFF)]) ^ K14;            L ^= (((S[(R >>> 24) & 0xFF] + S[256 + ((R >>> 16) & 0xFF)]) ^ S[512 + ((R >>>  8) & 0xFF)]) + S[768 + (R & 0xFF)]) ^ K13;            R ^= (((S[(L >>> 24) & 0xFF] + S[256 + ((L >>> 16) & 0xFF)]) ^ S[512 + ((L >>>  8) & 0xFF)]) + S[768 + (L & 0xFF)]) ^ K12;            L ^= (((S[(R >>> 24) & 0xFF] + S[256 + ((R >>> 16) & 0xFF)]) ^ S[512 + ((R >>>  8) & 0xFF)]) + S[768 + (R & 0xFF)]) ^ K11;            R ^= (((S[(L >>> 24) & 0xFF] + S[256 + ((L >>> 16) & 0xFF)]) ^ S[512 + ((L >>>  8) & 0xFF)]) + S[768 + (L & 0xFF)]) ^ K10;            L ^= (((S[(R >>> 24) & 0xFF] + S[256 + ((R >>> 16) & 0xFF)]) ^ S[512 + ((R >>>  8) & 0xFF)]) + S[768 + (R & 0xFF)]) ^ K9;            R ^= (((S[(L >>> 24) & 0xFF] + S[256 + ((L >>> 16) & 0xFF)]) ^ S[512 + ((L >>>  8) & 0xFF)]) + S[768 + (L & 0xFF)]) ^ K8;            L ^= (((S[(R >>> 24) & 0xFF] + S[256 + ((R >>> 16) & 0xFF)]) ^ S[512 + ((R >>>  8) & 0xFF)]) + S[768 + (R & 0xFF)]) ^ K7;            R ^= (((S[(L >>> 24) & 0xFF] + S[256 + ((L >>> 16) & 0xFF)]) ^ S[512 + ((L >>>  8) & 0xFF)]) + S[768 + (L & 0xFF)]) ^ K6;            L ^= (((S[(R >>> 24) & 0xFF] + S[256 + ((R >>> 16) & 0xFF)]) ^ S[512 + ((R >>>  8) & 0xFF)]) + S[768 + (R & 0xFF)]) ^ K5;            R ^= (((S[(L >>> 24) & 0xFF] + S[256 + ((L >>> 16) & 0xFF)]) ^ S[512 + ((L >>>  8) & 0xFF)]) + S[768 + (L & 0xFF)]) ^ K4;            L ^= (((S[(R >>> 24) & 0xFF] + S[256 + ((R >>> 16) & 0xFF)]) ^ S[512 + ((R >>>  8) & 0xFF)]) + S[768 + (R & 0xFF)]) ^ K3;            R ^= (((S[(L >>> 24) & 0xFF] + S[256 + ((L >>> 16) & 0xFF)]) ^ S[512 + ((L >>>  8) & 0xFF)]) + S[768 + (L & 0xFF)]) ^ K2;

⌨️ 快捷键说明

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