Пример #1
0
        /**
         * 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);
            }
        }
Пример #2
0
        /// <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);
            }
        }
Пример #3
0
        /// <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);
        }
Пример #4
0
        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;
        }
Пример #5
0
        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);
        }