?? iso9796d2psssigner.java
字號(hào):
package org.bouncycastle.crypto.signers;import java.security.SecureRandom;import org.bouncycastle.crypto.AsymmetricBlockCipher;import org.bouncycastle.crypto.CipherParameters;import org.bouncycastle.crypto.CryptoException;import org.bouncycastle.crypto.Digest;import org.bouncycastle.crypto.SignerWithRecovery;import org.bouncycastle.crypto.digests.RIPEMD128Digest;import org.bouncycastle.crypto.digests.RIPEMD160Digest;import org.bouncycastle.crypto.digests.SHA1Digest;import org.bouncycastle.crypto.params.ParametersWithRandom;import org.bouncycastle.crypto.params.ParametersWithSalt;import org.bouncycastle.crypto.params.RSAKeyParameters;/** * ISO9796-2 - mechanism using a hash function with recovery (scheme 2 and 3). * <p> * Note: the usual length for the salt is the length of the hash * function used in bytes. */public class ISO9796d2PSSSigner implements SignerWithRecovery{ 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 SecureRandom random; private byte[] standardSalt; private int hLen; private int trailer; private int keyBits; private byte[] block; private byte[] mBuf; private int messageLength; private int saltLength; private boolean fullMessage; private byte[] recoveredMessage; /** * Generate a signer for the with either implicit or explicit trailers * for ISO9796-2, scheme 2 or 3. * * @param cipher base cipher to use for signature creation/verification * @param digest digest to use. * @param saltLength length of salt in bytes. * @param implicit whether or not the trailer is implicit or gives the hash. */ public ISO9796d2PSSSigner( AsymmetricBlockCipher cipher, Digest digest, int saltLength, boolean implicit) { this.cipher = cipher; this.digest = digest; this.hLen = digest.getDigestSize(); this.saltLength = saltLength; 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"); } } } /** * Constructor for a signer with an explicit digest trailer. * * @param cipher cipher to use. * @param digest digest to sign with. * @param saltLength length of salt in bytes. */ public ISO9796d2PSSSigner( AsymmetricBlockCipher cipher, Digest digest, int saltLength) { this(cipher, digest, saltLength, false); } /** * Initialise the signer. * * @param forSigning true if for signing, false if for verification. * @param param parameters for signature generation/verification. If the * parameters are for generation they should be a ParametersWithRandom, * a ParametersWithSalt, or just an RSAKeyParameters object. If RSAKeyParameters * are passed in a SecureRandom will be created. * @exception IllegalArgumentException if wrong parameter type or a fixed * salt is passed in which is the wrong length. */ public void init( boolean forSigning, CipherParameters param) { RSAKeyParameters kParam = null; int lengthOfSalt = saltLength; if (param instanceof ParametersWithRandom) { ParametersWithRandom p = (ParametersWithRandom)param; kParam = (RSAKeyParameters)p.getParameters(); random = p.getRandom(); } else if (param instanceof ParametersWithSalt) { ParametersWithSalt p = (ParametersWithSalt)param; kParam = (RSAKeyParameters)p.getParameters(); standardSalt = p.getSalt(); lengthOfSalt = standardSalt.length; } else { kParam = (RSAKeyParameters)param; if (forSigning) { random = new SecureRandom(); } } cipher.init(forSigning, kParam); keyBits = kParam.getModulus().bitLength(); block = new byte[(keyBits + 7) / 8]; if (trailer == TRAILER_IMPLICIT) { mBuf = new byte[block.length - digest.getDigestSize() - lengthOfSalt - 1 - 1]; } else { mBuf = new byte[block.length - digest.getDigestSize() - lengthOfSalt - 1 - 2]; } reset(); } /** * compare two byte arrays. */ private boolean isSameAs( byte[] a, byte[] b) { if (messageLength != b.length) { return false; } for (int i = 0; i != b.length; i++) { if (a[i] != b[i]) { return false; } } return true; } /** * clear possible sensitive data */ private void clearBlock( byte[] block) { for (int i = 0; i != block.length; i++) { block[i] = 0; } } /** * update the internal digest with the byte b */ public void update( byte b) { if (messageLength < mBuf.length) { mBuf[messageLength++] = b; } else { digest.update(b); } } /** * update the internal digest with the byte array in */ public void update( byte[] in, int off, int len) { while (len > 0 && messageLength < mBuf.length) { this.update(in[off]); off++; len--; } if (len > 0) { digest.update(in, off, len); } } /** * reset the internal state */ public void reset() { digest.reset(); messageLength = 0; if (recoveredMessage != null) { clearBlock(recoveredMessage); } recoveredMessage = null; fullMessage = false; } /** * generate a signature for the loaded message using the key we were * initialised with. */ public byte[] generateSignature() throws CryptoException { int digSize = digest.getDigestSize(); int t = 0; int delta = 0; byte[] m2Hash = new byte[digSize]; digest.doFinal(m2Hash, 0); byte[] C = new byte[8]; LtoOSP(messageLength * 8, C); digest.update(C, 0, C.length); digest.update(mBuf, 0, messageLength); digest.update(m2Hash, 0, m2Hash.length); byte[] salt; if (standardSalt != null) { salt = standardSalt; } else { salt = new byte[saltLength]; random.nextBytes(salt); } digest.update(salt, 0, salt.length); byte[] hash = new byte[digest.getDigestSize()]; digest.doFinal(hash, 0); int tLength = 2; if (trailer == TRAILER_IMPLICIT) { tLength = 1; } int off = block.length - messageLength - salt.length - hLen - tLength - 1;
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -