/** * Generate a signer with either implicit or explicit trailers for X9.31. * * @param cipher base cipher to use for signature creation/verification * @param digest digest to use. * @param implicit whether or not the trailer is implicit or gives the hash. */ public X931Signer(IAsymmetricBlockCipher cipher, IDigest digest, bool isImplicit) { this.cipher = cipher; this.digest = digest; if (isImplicit) { trailer = IsoTrailers.TRAILER_IMPLICIT; } else if (IsoTrailers.NoTrailerAvailable(digest)) { throw new ArgumentException("no valid trailer", "digest"); } else { trailer = IsoTrailers.GetTrailer(digest); } }
/// <summary> /// Generate a signer with either implicit or explicit trailers for ISO9796-2, scheme 2 or 3. /// </summary> /// <param name="cipher">base cipher to use for signature creation/verification</param> /// <param name="digest">digest to use.</param> /// <param name="saltLength">length of salt in bytes.</param> /// <param name="isImplicit">whether or not the trailer is implicit or gives the hash.</param> public Iso9796d2PssSigner( IAsymmetricBlockCipher cipher, IDigest digest, int saltLength, bool isImplicit) { this.cipher = cipher; this.digest = digest; this.hLen = digest.GetDigestSize(); this.saltLength = saltLength; if (isImplicit) { trailer = IsoTrailers.TRAILER_IMPLICIT; } else if (IsoTrailers.NoTrailerAvailable(digest)) { throw new ArgumentException("no valid trailer", "digest"); } else { trailer = IsoTrailers.GetTrailer(digest); } }
/// <summary> return true if the signature represents a ISO9796-2 signature /// for the passed in message. /// </summary> public virtual bool VerifySignature(byte[] signature) { byte[] block; if (preSig == null) { try { block = cipher.ProcessBlock(signature, 0, signature.Length); } catch (Exception) { return(false); } } else { if (!Arrays.AreEqual(preSig, signature)) { throw new InvalidOperationException("updateWithRecoveredMessage called on different signature"); } block = preBlock; preSig = null; preBlock = null; } if (((block[0] & 0xC0) ^ 0x40) != 0) { return(ReturnFalse(block)); } if (((block[block.Length - 1] & 0xF) ^ 0xC) != 0) { return(ReturnFalse(block)); } int delta = 0; if (((block[block.Length - 1] & 0xFF) ^ 0xBC) == 0) { delta = 1; } else { int sigTrail = ((block[block.Length - 2] & 0xFF) << 8) | (block[block.Length - 1] & 0xFF); if (IsoTrailers.NoTrailerAvailable(digest)) { throw new ArgumentException("unrecognised hash in signature"); } if (sigTrail != IsoTrailers.GetTrailer(digest)) { throw new InvalidOperationException("signer initialised with wrong digest for trailer " + sigTrail); } delta = 2; } // // find out how much padding we've got // int mStart = 0; for (; mStart != block.Length; mStart++) { if (((block[mStart] & 0x0f) ^ 0x0a) == 0) { break; } } mStart++; // // check the hashes // byte[] hash = new byte[digest.GetDigestSize()]; int off = block.Length - delta - hash.Length; // // there must be at least one byte of message string // if ((off - mStart) <= 0) { return(ReturnFalse(block)); } // // if we contain the whole message as well, check the hash of that. // if ((block[0] & 0x20) == 0) { fullMessage = true; // check right number of bytes passed in. if (messageLength > off - mStart) { return(ReturnFalse(block)); } digest.Reset(); digest.BlockUpdate(block, mStart, off - mStart); digest.DoFinal(hash, 0); bool isOkay = true; for (int i = 0; i != hash.Length; i++) { block[off + i] ^= hash[i]; if (block[off + i] != 0) { isOkay = false; } } if (!isOkay) { return(ReturnFalse(block)); } recoveredMessage = new byte[off - mStart]; Array.Copy(block, mStart, recoveredMessage, 0, recoveredMessage.Length); } else { fullMessage = false; digest.DoFinal(hash, 0); bool isOkay = true; for (int i = 0; i != hash.Length; i++) { block[off + i] ^= hash[i]; if (block[off + i] != 0) { isOkay = false; } } if (!isOkay) { return(ReturnFalse(block)); } recoveredMessage = new byte[off - mStart]; Array.Copy(block, mStart, recoveredMessage, 0, recoveredMessage.Length); } // // if they've input a message check what we've recovered against // what was input. // if (messageLength != 0) { if (!IsSameAs(mBuf, recoveredMessage)) { return(ReturnFalse(block)); } } ClearBlock(mBuf); ClearBlock(block); messageLength = 0; return(true); }
public virtual void UpdateWithRecoveredMessage( byte[] signature) { byte[] block = cipher.ProcessBlock(signature, 0, signature.Length); // // adjust block size for leading zeroes if necessary // if (block.Length < (keyBits + 7) / 8) { byte[] tmp = new byte[(keyBits + 7) / 8]; Array.Copy(block, 0, tmp, tmp.Length - block.Length, block.Length); ClearBlock(block); block = tmp; } int tLength; if (((block[block.Length - 1] & 0xFF) ^ 0xBC) == 0) { tLength = 1; } else { int sigTrail = ((block[block.Length - 2] & 0xFF) << 8) | (block[block.Length - 1] & 0xFF); if (IsoTrailers.NoTrailerAvailable(digest)) { throw new ArgumentException("unrecognised hash in signature"); } if (sigTrail != IsoTrailers.GetTrailer(digest)) { throw new InvalidOperationException("signer initialised with wrong digest for trailer " + sigTrail); } tLength = 2; } // // calculate H(m2) // byte[] m2Hash = new byte[hLen]; digest.DoFinal(m2Hash, 0); // // remove the mask // byte[] dbMask = MaskGeneratorFunction1(block, block.Length - hLen - tLength, hLen, block.Length - hLen - tLength); for (int i = 0; i != dbMask.Length; i++) { block[i] ^= dbMask[i]; } block[0] &= 0x7f; // // find out how much padding we've got // int mStart = 0; while (mStart < block.Length) { if (block[mStart++] == 0x01) { break; } } if (mStart >= block.Length) { ClearBlock(block); } fullMessage = (mStart > 1); recoveredMessage = new byte[dbMask.Length - mStart - saltLength]; Array.Copy(block, mStart, recoveredMessage, 0, recoveredMessage.Length); recoveredMessage.CopyTo(mBuf, 0); preSig = signature; preBlock = block; preMStart = mStart; preTLength = tLength; }
public virtual void UpdateWithRecoveredMessage( byte[] signature) { byte[] block = cipher.ProcessBlock(signature, 0, signature.Length); if (((block[0] & 0xC0) ^ 0x40) != 0) { throw new InvalidCipherTextException("malformed signature"); } if (((block[block.Length - 1] & 0xF) ^ 0xC) != 0) { throw new InvalidCipherTextException("malformed signature"); } int delta = 0; if (((block[block.Length - 1] & 0xFF) ^ 0xBC) == 0) { delta = 1; } else { int sigTrail = ((block[block.Length - 2] & 0xFF) << 8) | (block[block.Length - 1] & 0xFF); if (IsoTrailers.NoTrailerAvailable(digest)) { throw new ArgumentException("unrecognised hash in signature"); } if (sigTrail != IsoTrailers.GetTrailer(digest)) { throw new InvalidOperationException("signer initialised with wrong digest for trailer " + sigTrail); } 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++; int off = block.Length - delta - digest.GetDigestSize(); // // there must be at least one byte of message string // if ((off - mStart) <= 0) { throw new InvalidCipherTextException("malformed block"); } // // if we contain the whole message as well, check the hash of that. // if ((block[0] & 0x20) == 0) { fullMessage = true; recoveredMessage = new byte[off - mStart]; Array.Copy(block, mStart, recoveredMessage, 0, recoveredMessage.Length); } else { fullMessage = false; recoveredMessage = new byte[off - mStart]; Array.Copy(block, mStart, recoveredMessage, 0, recoveredMessage.Length); } preSig = signature; preBlock = block; digest.BlockUpdate(recoveredMessage, 0, recoveredMessage.Length); messageLength = recoveredMessage.Length; recoveredMessage.CopyTo(mBuf, 0); }