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 + -
显示快捷键?