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

📄 serpent_algorithm.java

📁 密码serpent算法源代码, 该算法是AES候选算法之一
💻 JAVA
字号:
// $Id: $//// $Log: $// Revision 1.1.1  1998/04/10  raif// + added code to generate Intermediate Values KAT.// + cosmetics.//// Revision 1.1  1998/04/07  Serpent authors// + revised slightly (endianness, and key schedule for variable lengths)//// Revision 1.0  1998/04/06  raif// + original version.//// $Endlog$/* * Copyright (c) 1997, 1998 Systemics Ltd on behalf of * the Cryptix Development Team. All rights reserved. */package Serpent;import java.io.PrintWriter;import java.security.InvalidKeyException;//.........................................................................../** * Serpent is a 128-bit 32-round block cipher with variable key lengths, * including 128-, 192- and 256-bit * keys conjectured to be at least as secure as three-key triple-DES.<p> * * Serpent was designed by Ross Anderson, Eli Biham and Lars Knudsen as a * candidate algorithm for the NIST AES Quest.<p> * * References:<ol> *  <li>Serpent: A New Block Cipher Proposal. This paper was published in the *  proceedings of the "Fast Software Encryption Workshop No. 5" held in *  Paris in March 1998. LNCS, Springer Verlag.<p> *  <li>Reference implementation of the standard Serpent cipher written in C *  by <a href="http://www.cl.cam.ac.uk/~fms/">Frank Stajano</a>.</ol><p> * * <b>Copyright</b> &copy; 1997, 1998 * <a href="http://www.systemics.com/">Systemics Ltd</a> on behalf of the * <a href="http://www.systemics.com/docs/cryptix/">Cryptix Development Team</a>. * <br>All rights reserved.<p> * * <b>$Revision: $</b> * @author  Raif S. Naffah * @author  Serpent authors (Ross Anderson, Eli Biham and Lars Knudsen) */public final class Serpent_Algorithm // implicit no-argument constructor{// Debugging methods and variables//...........................................................................    static final String NAME = "Serpent_Algorithm";    static final boolean IN = true, OUT = false;    static final boolean DEBUG = Serpent_Properties.GLOBAL_DEBUG;    static final int debuglevel = DEBUG ? Serpent_Properties.getLevel(NAME) : 0;    static final PrintWriter err = DEBUG ? Serpent_Properties.getOutput() : null;    static final boolean TRACE = Serpent_Properties.isTraceable(NAME);    static void debug (String s) { err.println(">>> "+NAME+": "+s); }    static void trace (boolean in, String s) {        if (TRACE) err.println((in?"==> ":"<== ")+NAME+"."+s);    }    static void trace (String s) { if (TRACE) err.println("<=> "+NAME+"."+s); }// Constants and variables//...........................................................................    /**     * This variable acts as a selector to allow the user to choose between     * a bit-slice implementation (Serpent_BitSlice) and a standard one     * (Serpent_Standard). When set to true the bit-slice implementation     * code is used, otherwise it's the standard implementation code.<p>     *     * IMPORTANT: When you change the value of this variable, make sure     * you re-compile all the classes in the Serpent package.     */    static final boolean USE_BIT_SLICE_IMPLEMENTATION = true;    static final int BLOCK_SIZE = 16; // bytes in a Serpent data-block    private static final char[] HEX_DIGITS = {        '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'    };// Basic API methods//...........................................................................    /**     * Expand a user-supplied key material into a session key.     *     * @param key  The user-key bytes (multiples of 4) to use.     * @exception  InvalidKeyException  If the key is invalid.     */    public static synchronized Object makeKey (byte[] key)    throws InvalidKeyException {        if (key == null)            throw new InvalidKeyException("Empty key");/*        if (!(key.length == 16 || key.length == 24 || key.length == 32))             throw new InvalidKeyException("Incorrect key length");	// Although it checks for size of 16, 24 or 32, it really	// supports all multiples of 4 up to 32 in the code of makeKey.*/        if ((key.length % 4) != 0 || (key.length / 4) > 8)             throw new InvalidKeyException("Incorrect key length");        return USE_BIT_SLICE_IMPLEMENTATION ?            Serpent_BitSlice.makeKey(key) :            Serpent_Standard.makeKey(key);    }    /**     * Encrypt exactly one block of plaintext.     *     * @param  in         The plaintext.     * @param  inOffset   Index of in from which to start considering data.     * @param  sessionKey The session key to use for encryption.     * @return The ciphertext generated from a plaintext using the session key.     */    public static byte[]    blockEncrypt (byte[] in, int inOffset, Object sessionKey) {        return USE_BIT_SLICE_IMPLEMENTATION ?            Serpent_BitSlice.blockEncrypt(in, inOffset, sessionKey) :            Serpent_Standard.blockEncrypt(in, inOffset, sessionKey);    }    /**     * Decrypt exactly one block of ciphertext.     *     * @param  in         The ciphertext.     * @param  inOffset   Index of in from which to start considering data.     * @param  sessionKey The session key to use for decryption.     * @return The plaintext generated from a ciphertext using the session key.     */    public static byte[]    blockDecrypt (byte[] in, int inOffset, Object sessionKey) {        return USE_BIT_SLICE_IMPLEMENTATION ?            Serpent_BitSlice.blockDecrypt(in, inOffset, sessionKey) :            Serpent_Standard.blockDecrypt(in, inOffset, sessionKey);    }    /** A basic symmetric encryption/decryption test. */     public static boolean self_test() {if (DEBUG) trace(IN, "self_test()");        boolean ok = false;        try {            byte[] kb = new byte[BLOCK_SIZE*2]; // all zeroes// kb=fromString("0000000000000000000000000000000000000000000000000000000000000000");            byte[] pt = fromEvenLengthString("00000003000000020000000100000000");            int i;            Object key = makeKey(kb);            byte[] ct =  blockEncrypt(pt, 0, key);            byte[] cpt = blockDecrypt(ct, 0, key);            ok = areEqual(pt, cpt);            if (!ok) {if (DEBUG && debuglevel > 7) {    debug("  plain: "+toReversedString(pt));    debug(" cipher: "+toReversedString(ct));    debug(" plain2: "+toReversedString(cpt));}                throw new RuntimeException("Symmetric operation failed");            }            ok = self_test(BLOCK_SIZE);        } catch (Exception x) {if (DEBUG && debuglevel > 0) {    debug("Exception encountered during self-test: " + x.getMessage());    x.printStackTrace();}        }if (DEBUG && debuglevel > 0) debug("Self-test OK? " + ok);if (DEBUG) trace(OUT, "self_test()");        return ok;    }// Serpent own methods//...........................................................................        /** @return The length in bytes of the Algorithm input block. */    public static int blockSize() { return BLOCK_SIZE; }    /** A basic symmetric encryption/decryption test for a given key size. */    private static boolean self_test (int keysize) {if (DEBUG) trace(IN, "self_test("+keysize+")");        boolean ok = false;        try {            byte[] kb = new byte[keysize];            byte[] pt = new byte[BLOCK_SIZE];            int i;            for (i = 0; i < keysize; i++)                kb[i] = (byte) i;            for (i = 0; i < BLOCK_SIZE; i++)                pt[i] = (byte) i;if (DEBUG && debuglevel > 6) {System.out.println("==========");System.out.println();System.out.println("KEYSIZE="+(8*keysize));System.out.println("KEY="+toString(kb));System.out.println();}            Object key = makeKey(kb);if (DEBUG && debuglevel > 6) {System.out.println("Intermediate Ciphertext Values (Encryption)");System.out.println();System.out.println("PT="+toString(pt));}            byte[] ct =  blockEncrypt(pt, 0, key);if (DEBUG && debuglevel > 6) {System.out.println("Intermediate Plaintext Values (Decryption)");System.out.println();System.out.println("CT="+toString(ct));}            byte[] cpt = blockDecrypt(ct, 0, key);            ok = areEqual(pt, cpt);            if (!ok)                throw new RuntimeException("Symmetric operation failed");        } catch (Exception x) {if (DEBUG && debuglevel > 0) {    debug("Exception encountered during self-test: " + x.getMessage());    x.printStackTrace();}        }if (DEBUG && debuglevel > 0) debug("Self-test OK? " + ok);if (DEBUG) trace(OUT, "self_test()");        return ok;    }// utility static methods (from cryptix.util.core ArrayUtil and Hex classes)//...........................................................................        /**     * Compares two byte arrays for equality.     *     * @return true if the arrays have identical contents     */    private static boolean areEqual (byte[] a, byte[] b) {        int aLength = a.length;        if (aLength != b.length)            return false;        for (int i = 0; i < aLength; i++)            if (a[i] != b[i])                return false;        return true;    }    /**     * Returns a number from 0 to 15 corresponding to the hex     * digit <i>ch</i>.     */    public static int fromDigit (char ch) {        if (ch >= '0' && ch <= '9')            return ch - '0';        if (ch >= 'A' && ch <= 'F')            return ch - 'A' + 10;        if (ch >= 'a' && ch <= 'f')            return ch - 'a' + 10;        throw new IllegalArgumentException("Invalid hex digit '"+ch+"'");    }    /**     * Returns a string of hexadecimal digits from a byte array. Each     * byte is converted to 2 hex symbols.     */    private static String toString (byte[] ba) {        int length = ba.length;        char[] buf = new char[length * 2];        for (int i = 0, j = 0, k; i < length; ) {            k = ba[i++];            buf[j++] = HEX_DIGITS[(k >>> 4) & 0x0F];            buf[j++] = HEX_DIGITS[ k        & 0x0F];        }        return new String(buf);    }// other utility static methods//...........................................................................    /**     * Returns an hexadecimal number (respresented as a string of hexadecimal      * digits from a byte array). Each byte is converted to 2 hex symbols.     * The order is however, as of printing a number from a little-endian     * internal representation (i.e., reverse order).     */    public static String toReversedString (byte[] ba) {        int length = ba.length;        char[] buf = new char[length * 2];        for (int i = length-1, j = 0, k; i >=0; ) {            k = ba[i--];            buf[j++] = HEX_DIGITS[(k >>> 4) & 0x0F];            buf[j++] = HEX_DIGITS[ k        & 0x0F];        }        return new String(buf);    }           /**     * Returns a byte array from an hexadecimal number.     */    public static byte[] fromEvenLengthString (String hex) {        int len = hex.length();        byte[] buf = new byte[((len + 1) / 2)];        int j = 0;        if ((len % 2) == 1) throw new IllegalArgumentException(            "string must have an even number of digits");        while (len > 0) {            buf[j++] = (byte) (fromDigit(hex.charAt(--len)) |                              (fromDigit(hex.charAt(--len)) << 4));        }        return buf;    }// main(): use to generate the Intermediate Values KAT//...........................................................................    public static void main (String[] args) {if (DEBUG && debuglevel > 6) {System.out.println("Algorithm Name: "+Serpent_Properties.FULL_NAME);System.out.println("Electronic Codebook (ECB) Mode");System.out.println();}        self_test(16);        self_test(24);        self_test(32);    }}

⌨️ 快捷键说明

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