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

📄 hmac.java

📁 另一个使用java编写的加密通用算法包
💻 JAVA
字号:
// $Id: HMAC.java,v 1.3 1998/01/28 05:58:10 hopwood Exp $//// $Log: HMAC.java,v $// Revision 1.3  1998/01/28 05:58:10  hopwood// + Documentation changes.//// Revision 1.2  1998/01/12 04:17:51  hopwood// + HMAC rewrite.//// Revision 1.1.1.1.1  1998/01/12  hopwood// + Rewritten as a MessageDigest.//// Revision 1.1.1.1  1998/01/04 03:27:05  hopwood// + Imported to CVS (tagged as 'start').//// Revision 0.1.0  1998/01/03  hopwood// + Original version.//// $Endlog$/* * Copyright (c) 1997 Systemics Ltd * on behalf of the Cryptix Development Team.  All rights reserved. */package cryptix.provider.mac;import cryptix.CryptixException;import cryptix.util.core.Debug;import cryptix.util.core.Hex;import cryptix.util.core.ArrayUtil;import java.io.PrintWriter;import java.security.MessageDigest;import java.security.Security;import java.security.Parameterized;import java.security.InvalidParameterException;/** * A class to implement the HMAC message authentication code, as described in * RFC 2104. * <p> * The definition of HMAC-X for a given message digest algorithm X depends * on that algorithm's internal block size, which is passed into the constructor * when this class is used directly. Normally, this class will be obtained * indirectly via the JCA API, e.g. <code>MessageDigest.getInstance("HMAC-SHA-1")</code> * if SHA-1 is to be used as the digest algorithm. * <p> * The key can be set as a byte array using the "key" parameter. It is <em>not</em> * reset after the MAC has been returned (this enables successive MACs using the * same key to be calculated efficiently). For example: * <pre> *    import java.security.Parameterized; * <br> *    MessageDigest hmac = MessageDigest.getInstance("HMAC-SHA-1"); *    byte[] key = ..., input1 = ..., input2 = ...; *    ((Parameterized) mac).setParameter("key", key); *    byte[] mac1 = hmac.digest(input1); *    byte[] mac2 = hmac.digest(input2); * </pre> * <p> * Parameters other than "key" are passed through to the MessageDigest object, * but this can only be done when the key is not set. An explicit call to * <code>reset()</code> will 'unset' the key. * <p> * This implementation does not support truncation of the output MAC. If * truncation is desired, the caller should use only the relevant initial bits * of the output array. * <p> * Note that although this class implements <samp>Cloneable</samp>, its * <code>clone()</code> method will throw a <samp>CloneNotSupportedException</samp> * if the underlying MessageDigest cannot be cloned. This should not be the * case for any of the Cryptix-supported digest algorithms. * <p> * HMAC is similar, but <em>not</em> identical to the MAC used by Secure Sockets * Layer version 3. The JCA standard algorithm name of the variant used in SSL v3 * is "SSL3MAC-X", for a message digest name X. * <p> * <b>References:</b> * <ol> *   <li> RFC 2104, <cite>HMAC: Keyed-Hashing for Message Authentication</cite> *   <li> RFC 2202, <cite>Test Cases for HMAC-MD5 and HMAC-SHA-1</cite> * </ol> * <p> * <b>Copyright</b> &copy; 1997 * <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: 1.3 $</b> * @author  David Hopwood * @since   Cryptix 3.0.3 */public class HMACextends MessageDigestimplements Parameterized, Cloneable{// Debugging methods and vars.//...........................................................................    private static final boolean DEBUG = Debug.GLOBAL_DEBUG;    private static final int debuglevel = DEBUG ? Debug.getLevel("HMAC") : 0;    private static final PrintWriter err = DEBUG ? Debug.getOutput() : null;    private static void debug(String s) { err.println("HMAC: " + s); }// Constants and variables//...........................................................................    private MessageDigest md;    // precomputation not implemented yet.    // private MessageDigest precompInner;    // private MessageDigest precompOuter;    private int blockSize;    private int length;    private byte[] key; // defaults to null// Constructors//...........................................................................    /**     * Constructs an HMAC object for the given MD algorithm name and block     * size.     * <p>     * Do not rely on being able to use this constructor to obtain a subclass     * of MessageDigest; when Cryptix is changed to use the Java 1.2 provider     * architecture, it will be a subclass of MessageDigestSpi instead.     *     * @param  mdAlgorithm  the standard JCA algorithm name of the message     *                      digest to be used.     * @param  mdBlockSize  the internal block size of the digest algorithm.     */    public HMAC(String mdAlgorithm, int mdBlockSize) {        super("HMAC-" + mdAlgorithm);        try { md = MessageDigest.getInstance(mdAlgorithm, "Cryptix"); }        catch (Exception e) {            try { md = MessageDigest.getInstance(mdAlgorithm); }            catch (Exception e2) {                throw new CryptixException(getAlgorithm() +                ": Unable to instantiate the " + mdAlgorithm +                " MessageDigest\n" + e2);            }        }        blockSize = mdBlockSize;        length = md.digest().length;        // in Java 1.2, use "length = md.getDigestLength();"        key = new byte[mdBlockSize];    }    /** This constructor is here to implement cloneability of this class. */    private HMAC(HMAC mac) throws CloneNotSupportedException {        super(mac.getAlgorithm());        md = (MessageDigest) (mac.md.clone());        blockSize = mac.blockSize;        length = mac.length;        byte[] _key = mac.key;        key = (_key == null) ? null : (byte[]) (_key.clone());    }// Cloneable method implementation//...........................................................................    /**     * Returns a copy of this HMAC object.     *     * @throws CloneNotSupportedException if the underlying MessageDigest is not     *                                    cloneable.     */    public Object clone() throws CloneNotSupportedException {        return new HMAC(this);    }// SPI methods//...........................................................................    /**     * Resets this object disregarding any temporary data present at the     * time of the invocation of this call.     */    protected void engineReset() {        md.reset();        key = null;    }    /** Continues an HMAC digest using the input byte. */    protected void engineUpdate(byte input) {        if (key == null)            throw new IllegalStateException(getAlgorithm() + ": Key has not been set");        md.update(input);    }    /**     * Hashes a byte array from a given offset for a specified length.     *     * @param  input    byte array from which data is to be hashed.     * @param  offset   start index of bytes to hash in input.     * @param  len      number of bytes to hash.     */    protected void engineUpdate(byte[] input, int offset, int len) {        if (key == null)            throw new IllegalStateException(getAlgorithm() + ": Key has not been set");        md.update(input, offset, len);    }    /**     * Calculates the final MAC.     * <p>     * RFC 2104 describes HMAC as follows:     * <p>     * The definition of HMAC requires a cryptographic hash function, which     * we denote by H, and a secret key K. We assume H to be a cryptographic     * hash function where data is hashed by iterating a basic compression     * function on blocks of data.   We denote by B the byte-length of such     * blocks (B=64 for all the above mentioned examples of hash functions),     * and by L the byte-length of hash outputs (L=16 for MD5, L=20 for     * SHA-1).  The authentication key K can be of any length up to B, the     * block length of the hash function.  Applications that use keys longer     * than B bytes will first hash the key using H and then use the     * resultant L byte string as the actual key to HMAC. In any case the     * minimal recommended length for K is L bytes (as the hash output     * length). See section 3 for more information on keys.     * <p>     * We define two fixed and different strings <i>ipad</i> and <i>opad</i>     * as follows (the 'i' and 'o' are mnemonics for inner and outer):     * <blockquote>     *    <i>ipad</i> = the byte 0x36 repeated B times <br>     *    <i>opad</i> = the byte 0x5C repeated B times.     * </blockquote>     * <p>     * To compute HMAC over the data 'text' we perform     * <blockquote>     *    H(K XOR <i>opad</i>, H(K XOR <i>ipad</i>, text))     * </blockquote>     * <p>     * Namely,     * <ol>     *   <li> append zeros to the end of K to create a B byte string     *        (e.g., if K is of length 20 bytes and B=64, then K will be     *        appended with 44 zero bytes 0x00)     *   <li> XOR (bitwise exclusive-OR) the B byte string computed in step     *        (1) with <i>ipad</i>     *   <li> append the stream of data 'text' to the B byte string resulting     *        from step (2)     *   <li> apply H to the stream generated in step (3)     *   <li> XOR (bitwise exclusive-OR) the B byte string computed in     *        step (1) with <i>opad</i>     *   <li> append the H result from step (4) to the B byte string     *        resulting from step (5)     *   <li> apply H to the stream generated in step (6) and output     *        the result     * </ol>     */    protected byte[] engineDigest() {if (DEBUG && debuglevel >= 7) debug("engineDigest()");        if (key == null)            throw new IllegalStateException(getAlgorithm() + ": Key has not been set");        byte[] innerhash = md.digest();        byte[] xorblock = new byte[blockSize];        for (int i = 0; i < key.length; i++)            xorblock[i] = (byte) (0x5C ^ key[i]);        for (int i = key.length; i < blockSize; i++)            xorblock[i] = (byte) 0x5C;        md.update(xorblock);        byte[] result = md.digest(innerhash);if (DEBUG && debuglevel >= 7) debug("... = <" + Hex.toString(result) + ">");        return result;    }    /** <b>SPI</b>: Returns the digest length in bytes. */    protected int engineGetDigestLength() { return length; }    public void setParameter(String param, Object value)    throws InvalidParameterException {        engineSetParameter(param, value);    }    public Object getParameter(String param)    throws InvalidParameterException {        return engineGetParameter(param);    }    protected void engineSetParameter(String param, Object value)    throws InvalidParameterException {        try {            if (param.equalsIgnoreCase("key")) {                setKey((byte[]) value);                return;            }            // don't allow setting hash parameters after the key has been initialised            // (allowing this would inhibit planned optimisations).            if (key != null)                throw new InvalidParameterException(getAlgorithm() +                    ": Can't set parameter after key has been initialised");            ((Parameterized) md).setParameter(param, value);        } catch (Exception e) { throw new InvalidParameterException(e.getMessage()); }    }    protected Object engineGetParameter(String param)    throws InvalidParameterException {        try {            return ((Parameterized) md).getParameter(param);        } catch (Exception e) { throw new InvalidParameterException(e.getMessage()); }    }// Own methods//...........................................................................    /**     * Sets the key value. If the MessageDigest is cloneable, it is possible to     * do precomputations for the inner and outer digests (but this is not     * implemented yet).     *     * @param  userkey  the bytes of the key.     */    private void setKey(byte[] userkey) {if (DEBUG && debuglevel >= 7) debug("setKey(<" + Hex.toString(userkey) + ">)");        if (key != null)            md.reset(); // junk incomplete input        if (userkey.length > blockSize)            key = md.digest(userkey);        else            key = (byte[]) (userkey.clone());        byte[] xorblock = new byte[blockSize];        for (int i = 0; i < key.length; i++)            xorblock[i] = (byte) (0x36 ^ key[i]);        for (int i = key.length; i < blockSize; i++)            xorblock[i] = (byte) 0x36;        md.update(xorblock);    }}

⌨️ 快捷键说明

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