psssigner.java

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

JAVA
285
字号
package org.bouncycastle.crypto.signers;import java.math.BigInteger;import java.security.SecureRandom;import org.bouncycastle.crypto.Digest;import org.bouncycastle.crypto.CryptoException;import org.bouncycastle.crypto.DataLengthException;import org.bouncycastle.crypto.CipherParameters;import org.bouncycastle.crypto.AsymmetricBlockCipher;import org.bouncycastle.crypto.params.RSAKeyParameters;import org.bouncycastle.crypto.params.ParametersWithRandom;import org.bouncycastle.crypto.digests.SHA1Digest;import org.bouncycastle.crypto.digests.RIPEMD128Digest;import org.bouncycastle.crypto.digests.RIPEMD160Digest;/** * RSA-PSS as described in PKCS# 1 v 2.1 */public class PSSSigner{    static final public byte   TRAILER_IMPLICIT    = (byte)0xBC;    private Digest                      digest;    private AsymmetricBlockCipher       cipher;    private SecureRandom                random;    private int                         hLen;    private int                         sLen;    private int                         emBits;    private byte[]                      salt;    private byte[]                      mDash;    private byte[]                      block;    /**     * basic constructor     *     * @param cipher the assymetric cipher to use.     * @param digest the digest to use.     * @param sLen the length of the salt to use (in bytes).     */    public PSSSigner(        AsymmetricBlockCipher   cipher,        Digest                  digest,        int                     sLen)    {        this.cipher = cipher;        this.digest = digest;        this.hLen = digest.getDigestSize();        this.sLen = sLen;        this.salt = new byte[sLen];        this.mDash = new byte[8 + sLen + hLen];    }	public void init(        boolean                 forSigning,        CipherParameters        param)	{        RSAKeyParameters  kParam = null;        if (param instanceof ParametersWithRandom)        {            ParametersWithRandom    p = (ParametersWithRandom)param;            kParam = (RSAKeyParameters)p.getParameters();            random = p.getRandom();        }        else        {            kParam = (RSAKeyParameters)param;            if (forSigning)            {                random = new SecureRandom();            }        }        cipher.init(forSigning, kParam);        emBits = kParam.getModulus().bitLength() - 1;        block = new byte[(emBits + 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, DataLengthException	{        if (emBits < (8 * hLen + 8 * sLen + 9))        {            throw new DataLengthException("encoding error");        }        digest.update(message, 0, message.length);        if (sLen != 0)        {            random.nextBytes(salt);            System.arraycopy(salt, 0, mDash, mDash.length - sLen, sLen);        }        digest.doFinal(mDash, mDash.length - hLen - sLen);        byte[]  h = new byte[hLen];        digest.update(mDash, 0, mDash.length);        digest.doFinal(h, 0);        block[block.length - sLen - 1 - hLen - 1] = 0x01;        System.arraycopy(salt, 0, block, block.length - sLen - hLen - 1, sLen);        byte[] dbMask = maskGeneratorFunction1(h, 0, h.length, block.length - hLen - 1);        for (int i = 0; i != dbMask.length; i++)        {            block[i] ^= dbMask[i];        }        block[0] &= (0xff >> ((block.length * 8) - emBits));        System.arraycopy(h, 0, block, block.length - hLen - 1, hLen);        block[block.length - 1] = TRAILER_IMPLICIT;        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)	{        if (emBits < (8 * hLen + 8 * sLen + 9))        {            return false;        }        byte[]      block = null;        try        {            block = cipher.processBlock(signature, 0, signature.length);        }        catch (Exception e)        {            return false;        }        if (block[block.length - 1] != TRAILER_IMPLICIT)        {            clearBlock(block);            return false;        }        byte[] dbMask = maskGeneratorFunction1(block, block.length - hLen - 1, hLen, block.length - hLen - 1);        for (int i = 0; i != dbMask.length; i++)        {            block[i] ^= dbMask[i];        }        block[0] &= (0xff >> ((block.length * 8) - emBits));        for (int i = 0; i != block.length - hLen - sLen - 2; i++)        {            if (block[i] != 0)            {                clearBlock(block);                return false;            }        }        if (block[block.length - hLen - sLen - 2] != 0x01)        {            clearBlock(block);            return false;        }        digest.update(message, 0, message.length);        System.arraycopy(block, block.length - sLen - hLen - 1, mDash, mDash.length - sLen, sLen);        digest.doFinal(mDash, mDash.length - hLen - sLen);        digest.update(mDash, 0, mDash.length);        digest.doFinal(mDash, mDash.length - hLen);        for (int i = block.length - hLen - 1, j = mDash.length - hLen;                                                 j != mDash.length; i++, j++)        {            if ((block[i] ^ mDash[j]) != 0)            {                clearBlock(mDash);                clearBlock(block);                return false;            }        }        clearBlock(mDash);        clearBlock(block);        return true;    }    /**     * int to octet string.     */    private void ItoOSP(        int     i,        byte[]  sp)    {        sp[0] = (byte)(i >>> 24);        sp[1] = (byte)(i >>> 16);        sp[2] = (byte)(i >>> 8);        sp[3] = (byte)(i >>> 0);    }    /**     * mask generator function, as described in PKCS1v2.     */    private byte[] maskGeneratorFunction1(        byte[]  Z,        int     zOff,        int     zLen,        int     length)    {        byte[]  mask = new byte[length];        byte[]  hashBuf = new byte[hLen];        byte[]  C = new byte[4];        int     counter = 0;        digest.reset();        do        {            ItoOSP(counter, C);            digest.update(Z, zOff, zLen);            digest.update(C, 0, C.length);            digest.doFinal(hashBuf, 0);            System.arraycopy(hashBuf, 0, mask, counter * hLen, hLen);        }        while (++counter < (length / hLen));        if ((counter * hLen) < length)        {            ItoOSP(counter, C);            digest.update(Z, zOff, zLen);            digest.update(C, 0, C.length);            digest.doFinal(hashBuf, 0);            System.arraycopy(hashBuf, 0, mask, counter * hLen, mask.length - (counter * hLen));        }        return mask;    }}

⌨️ 快捷键说明

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