iso9796d2signer.java

来自「《移动Agent技术》一书的所有章节源代码。」· Java 代码 · 共 308 行

JAVA
308
字号
package org.bouncycastle.crypto.signers;import java.math.BigInteger;import org.bouncycastle.crypto.Digest;import org.bouncycastle.crypto.CryptoException;import org.bouncycastle.crypto.CipherParameters;import org.bouncycastle.crypto.AsymmetricBlockCipher;import org.bouncycastle.crypto.params.RSAKeyParameters;import org.bouncycastle.crypto.digests.SHA1Digest;import org.bouncycastle.crypto.digests.RIPEMD128Digest;import org.bouncycastle.crypto.digests.RIPEMD160Digest;/** * ISO9796-2 - mechanism using a hash function. */public class ISO9796d2Signer{    static final public int   TRAILER_IMPLICIT    = 0xBC;    static final public int   TRAILER_RIPEMD160   = 0x31CC;    static final public int   TRAILER_RIPEMD128   = 0x32CC;    static final public int   TRAILER_SHA1        = 0x33CC;    private Digest                      digest;    private AsymmetricBlockCipher       cipher;    private int         trailer;    private int         keyBits;    private byte[]      block;    public ISO9796d2Signer(        AsymmetricBlockCipher   cipher,        Digest                  digest,        boolean                 implicit)    {        this.cipher = cipher;        this.digest = digest;        if (implicit)        {            trailer = TRAILER_IMPLICIT;        }        else        {            if (digest instanceof SHA1Digest)            {                trailer = TRAILER_SHA1;            }            else if (digest instanceof RIPEMD160Digest)            {                trailer = TRAILER_RIPEMD160;            }            else if (digest instanceof RIPEMD128Digest)            {                trailer = TRAILER_RIPEMD128;            }            else            {                throw new IllegalArgumentException("no valid trailer for digest");            }        }    }    public ISO9796d2Signer(        AsymmetricBlockCipher   cipher,        Digest                  digest)    {        this(cipher, digest, false);    }	public void init(        boolean                 forSigning,        CipherParameters        param)	{        RSAKeyParameters  kParam = (RSAKeyParameters)param;        cipher.init(forSigning, kParam);        keyBits = kParam.getModulus().bitLength();        block = new byte[(keyBits + 7) / 8];	}    /**     * clear possible sensitive data     */    private void clearBlock(        byte[]  block)    {        for (int i = 0; i != block.length; i++)        {            block[i] = 0;        }    }    /**     * generate a signature for the given message using the key we were     * initialised with.     *     * @param message the message that will be verified later.     */	public byte[] generateSignature(        byte[] message)        throws CryptoException	{        int     digSize = digest.getDigestSize();        int t = 0;        int delta = 0;        digest.update(message, 0, message.length);        if (trailer == TRAILER_IMPLICIT)        {            t = 8;            delta = block.length - digSize - 1;            digest.doFinal(block, delta);            block[block.length - 1] = (byte)TRAILER_IMPLICIT;        }        else        {            t = 16;            delta = block.length - digSize - 2;            digest.doFinal(block, delta);            block[block.length - 2] = (byte)(trailer >>> 8);            block[block.length - 1] = (byte)trailer;        }        byte    header = 0;        int     x = (digSize + message.length) * 8 + t + 4 - keyBits;        if (x > 0)        {            int mR = message.length - ((x + 7) / 8);            header = 0x60;            delta -= mR;                        System.arraycopy(message, 0, block, delta, mR);        }        else        {            header = 0x40;            delta -= message.length;                        System.arraycopy(message, 0, block, delta, message.length);        }                if ((delta - 1) > 0)        {            for (int i = delta - 1; i != 0; i--)            {                block[i] = (byte)0xbb;            }            block[delta - 1] ^= (byte)0x01;            block[0] = (byte)0x0b;            block[0] |= header;        }        else        {            block[0] = (byte)0x0a;            block[0] |= header;        }        byte[]  b = cipher.processBlock(block, 0, block.length);        clearBlock(block);        return b;	}    /**     * return true if the signature represents a ISO9796-2 signature     * for the passed in message.     */	public boolean verifySignature(        byte[]      message,        byte[]      signature)	{        byte[]      block = null;        try        {            block = cipher.processBlock(signature, 0, signature.length);        }        catch (Exception e)        {            return false;        }        if (((block[0] & 0xC0) ^ 0x40) != 0)        {            clearBlock(block);            return false;        }        if (((block[block.length - 1] & 0xF) ^ 0xC) != 0)        {            clearBlock(block);            return false;        }        Digest  d = null;        int     delta = 0;        if (((block[block.length - 1] & 0xFF) ^ 0xBC) == 0)        {            if (digest == null)            {                throw new IllegalArgumentException("can't interpret signature");            }            else            {                d = digest;            }            delta = 1;        }        else        {            int sigTrail = ((block[block.length - 2] & 0xFF) << 8) | (block[block.length - 1] & 0xFF);            switch (sigTrail)            {            case TRAILER_RIPEMD160:                    d = new RIPEMD160Digest();                    break;            case TRAILER_SHA1:                    d = new SHA1Digest();                    break;            case TRAILER_RIPEMD128:                    d = new RIPEMD128Digest();                    break;            default:                throw new IllegalArgumentException("unrecognised hash in signature");            }            delta = 2;        }        //        // find out how much padding we've got        //        int mStart = 0;        for (mStart = 0; mStart != block.length; mStart++)        {            if (((block[mStart] & 0x0f) ^ 0x0a) == 0)            {                break;            }        }        mStart++;        //        // check the hashes        //        byte[]  hash = new byte[d.getDigestSize()];        d.update(message, 0, message.length);        d.doFinal(hash, 0);        int off = block.length - delta - hash.length;        //        // there must be at least one byte of message string        //        if ((off - mStart) <= 0)        {            clearBlock(block);            return false;        }        for (int i = 0; i != hash.length; i++)        {            block[off + i] ^= hash[i];            if (block[off + i] != 0)            {                clearBlock(block);                return false;            }        }        //        // if we contain the whole message as well, check the hash of that also        //        if ((block[0] & 0x20) == 0)        {            d.update(block, mStart, off - mStart);            d.doFinal(block, off);            for (int i = 0; i != hash.length; i++)            {                block[off + i] ^= hash[i];                if (block[off + i] != 0)                {                    clearBlock(block);                    return false;                }            }        }        clearBlock(block);        return true;	}}

⌨️ 快捷键说明

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