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

📄 blowfish.java

📁 基于Jabber协议的即时消息服务器
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
/** * $RCSfile$ * $Revision: 3657 $ * $Date: 2002-09-09 08:31:31 -0700 (Mon, 09 Sep 2002) $ * * Adapted from Markus Hahn's Blowfish package so that all functionality is * in a single source file. Please visit the following URL for his excellent * package: http://www.hotpixel.net/software.html * * Copyright (c) 1997-2002 Markus Hahn <markus_hahn@gmx.net> * * Released under the Apache 2.0 license. */package org.jivesoftware.util;import java.util.*;import java.security.*;/** * A class that provides easy Blowfish encryption.<p> * * @author Markus Hahn <markus_hahn@gmx.net> */public class Blowfish {    private BlowfishCBC m_bfish;    private static Random m_rndGen = new Random();    /**     * Creates a new Blowfish object using the specified key (oversized     * password will be cut).     *     * @param password the password (treated as a real unicode array)     */    public Blowfish(String password) {        // hash down the password to a 160bit key        MessageDigest digest = null;        try {            digest = MessageDigest.getInstance("SHA1");            digest.update(password.getBytes());        }        catch (Exception e) {            Log.error(e);        }        // setup the encryptor (use a dummy IV)        m_bfish = new BlowfishCBC(digest.digest(), 0);        digest.reset();    }    /**     * Encrypts a string (treated in UNICODE) using the     * standard Java random generator, which isn't that     * great for creating IVs     *     * @param sPlainText string to encrypt     * @return encrypted string in binhex format     */    public String encryptString(String sPlainText) {        // get the IV        long lCBCIV;        synchronized (m_rndGen)        {            lCBCIV = m_rndGen.nextLong();        }        // map the call;        return encStr(sPlainText, lCBCIV);    }    // Internal routine for string encryption    private String encStr(String sPlainText,                          long lNewCBCIV)    {        // allocate the buffer (align to the next 8 byte border plus padding)        int nStrLen = sPlainText.length();        byte[] buf = new byte [((nStrLen << 1) & 0xfffffff8) + 8];        // copy all bytes of the string into the buffer (use network byte order)        int nI;        int nPos = 0;        for (nI = 0; nI < nStrLen; nI++)        {            char cActChar = sPlainText.charAt(nI);            buf[nPos++] = (byte) ((cActChar >> 8) & 0x0ff);            buf[nPos++] = (byte) (cActChar & 0x0ff) ;        }        // pad the rest with the PKCS5 scheme        byte bPadVal = (byte)(buf.length - (nStrLen << 1));        while (nPos < buf.length)        {            buf[nPos++] = bPadVal;        }        // create the encryptor        m_bfish.setCBCIV(lNewCBCIV);        // encrypt the buffer        m_bfish.encrypt(buf);        // return the binhex string        byte[] newCBCIV = new byte[BlowfishCBC.BLOCKSIZE];        longToByteArray(lNewCBCIV,                newCBCIV,                0);        return bytesToBinHex(newCBCIV, 0, BlowfishCBC.BLOCKSIZE) +                bytesToBinHex(buf, 0, buf.length);    }    /**     * decrypts a hexbin string (handling is case sensitive)     * @param sCipherText hexbin string to decrypt     * @return decrypted string (null equals an error)     */    public String decryptString(String sCipherText)    {        // get the number of estimated bytes in the string (cut off broken blocks)        int nLen = (sCipherText.length() >> 1) & ~7;        // does the given stuff make sense (at least the CBC IV)?        if (nLen < BlowfishECB.BLOCKSIZE)            return null;        // get the CBC IV        byte[] cbciv = new byte[BlowfishCBC.BLOCKSIZE];        int nNumOfBytes = binHexToBytes(sCipherText,                cbciv,                0,                0,                BlowfishCBC.BLOCKSIZE);        if (nNumOfBytes < BlowfishCBC.BLOCKSIZE)            return null;        // (got it)        m_bfish.setCBCIV(cbciv);        // something left to decrypt?        nLen -= BlowfishCBC.BLOCKSIZE;        if (nLen == 0)        {            return "";        }        // get all data bytes now        byte[] buf = new byte[nLen];        nNumOfBytes = binHexToBytes(sCipherText,                buf,                BlowfishCBC.BLOCKSIZE * 2,                0,                nLen);        // we cannot accept broken binhex sequences due to padding        // and decryption        if (nNumOfBytes < nLen)        {            return null;        }        // decrypt the buffer        m_bfish.decrypt(buf);        // get the last padding byte        int nPadByte = (int)buf[buf.length - 1] & 0x0ff;        // ( try to get all information if the padding doesn't seem to be correct)        if ((nPadByte > 8) || (nPadByte < 0))        {            nPadByte = 0;        }        // calculate the real size of this message        nNumOfBytes -= nPadByte;        if (nNumOfBytes < 0)        {            return "";        }        // success        return byteArrayToUNCString(buf, 0, nNumOfBytes);    }    /**     * destroys (clears) the encryption engine,     * after that the instance is not valid anymore     */    public void destroy()    {        m_bfish.cleanUp();    }    /**     * implementation of the Blowfish encryption algorithm in ECB mode     * @author Markus Hahn <markus_hahn@gmx.net>     * @version Feburary 14, 2001     */    private static class BlowfishECB    {        /** maximum possible key length */        public final static int MAXKEYLENGTH = 56;        /** block size of this cipher (in bytes) */        public final static int BLOCKSIZE = 8;        // size of the single boxes        final static int PBOX_ENTRIES = 18;        final static int SBOX_ENTRIES = 256;        // the boxes        int[] m_pbox;        int[] m_sbox1;        int[] m_sbox2;        int[] m_sbox3;        int[] m_sbox4;        /**         * default constructor         * @param bfkey key material, up to MAXKEYLENGTH bytes         */        public BlowfishECB(byte[] bfkey)        {            // create the boxes            int nI;            m_pbox = new int[PBOX_ENTRIES];            for (nI = 0; nI < PBOX_ENTRIES; nI++)            {                m_pbox[nI] = pbox_init[nI];            }            m_sbox1 = new int[SBOX_ENTRIES];            m_sbox2 = new int[SBOX_ENTRIES];            m_sbox3 = new int[SBOX_ENTRIES];            m_sbox4 = new int[SBOX_ENTRIES];            for (nI = 0; nI < SBOX_ENTRIES; nI++)            {                m_sbox1[nI] = sbox_init_1[nI];                m_sbox2[nI] = sbox_init_2[nI];                m_sbox3[nI] = sbox_init_3[nI];                m_sbox4[nI] = sbox_init_4[nI];            }            // xor the key over the p-boxes            int nLen = bfkey.length;            if (nLen == 0) return; // such a setup is also valid (zero key "encryption" is possible)            int nKeyPos = 0;            int nBuild = 0;            int nJ;            for (nI = 0; nI < PBOX_ENTRIES; nI++)            {                for (nJ = 0; nJ < 4; nJ++)                {                    nBuild = (nBuild << 8) | (((int) bfkey[nKeyPos]) & 0x0ff);                    if (++nKeyPos == nLen)                    {                        nKeyPos = 0;                    }                }                m_pbox[nI] ^= nBuild;            }            // encrypt all boxes with the all zero string            long lZero = 0;            // (same as above)            for (nI = 0; nI < PBOX_ENTRIES; nI += 2)            {                lZero = encryptBlock(lZero);                m_pbox[nI] = (int) (lZero >>> 32);                m_pbox[nI+1] = (int) (lZero & 0x0ffffffffL);            }            for (nI = 0; nI < SBOX_ENTRIES; nI += 2)            {                lZero = encryptBlock(lZero);                m_sbox1[nI] = (int) (lZero >>> 32);                m_sbox1[nI+1] = (int) (lZero & 0x0ffffffffL);            }            for (nI = 0; nI < SBOX_ENTRIES; nI += 2)            {                lZero = encryptBlock(lZero);                m_sbox2[nI] = (int) (lZero >>> 32);                m_sbox2[nI+1] = (int) (lZero & 0x0ffffffffL);            }            for (nI = 0; nI < SBOX_ENTRIES; nI += 2)            {                lZero = encryptBlock(lZero);                m_sbox3[nI] = (int) (lZero >>> 32);                m_sbox3[nI+1] = (int) (lZero & 0x0ffffffffL);            }            for (nI = 0; nI < SBOX_ENTRIES; nI += 2)            {                lZero = encryptBlock(lZero);                m_sbox4[nI] = (int) (lZero >>> 32);                m_sbox4[nI+1] = (int) (lZero & 0x0ffffffffL);            }        }        /**         * to clear data in the boxes before an instance is freed         */        public void cleanUp()        {            int nI;            for (nI = 0; nI < PBOX_ENTRIES; nI++)            {                m_pbox[nI] = 0;            }            for (nI = 0; nI < SBOX_ENTRIES; nI++)            {                m_sbox1[nI] = m_sbox2[nI] = m_sbox3[nI] = m_sbox4[nI] = 0;            }        }        /**         * selftest routine, to check e.g. for a valid class file transmission         * @return true: selftest passed / false: selftest failed         */        public static boolean selfTest()        {            // test vector #1 (checking for the "signed bug")            byte[] testKey1 = { (byte) 0x1c, (byte) 0x58, (byte) 0x7f, (byte) 0x1c,                                (byte) 0x13, (byte) 0x92, (byte) 0x4f, (byte) 0xef };            int[] tv_p1 = { 0x30553228, 0x6d6f295a };            int[] tv_c1 = { 0x55cb3774, 0xd13ef201 };            int[] tv_t1 = new int[2];            // test vector #2 (offical vector by Bruce Schneier)            String sTestKey2 = "Who is John Galt?";            byte[] testKey2 = sTestKey2.getBytes();            int[] tv_p2 = { 0xfedcba98, 0x76543210 };            int[] tv_c2 = { 0xcc91732b, 0x8022f684 };            int[] tv_t2 = new int[2];            // start the tests, check for a proper decryption, too            BlowfishECB testbf1 = new BlowfishECB(testKey1);            testbf1.encrypt(tv_p1, tv_t1);            if ((tv_t1[0] != tv_c1[0]) ||                    (tv_t1[1] != tv_c1[1]))            {                return false;            }            testbf1.decrypt(tv_t1);            if ((tv_t1[0] != tv_p1[0]) ||                    (tv_t1[1] != tv_p1[1]))

⌨️ 快捷键说明

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