public void updateWithRecoveredMessage(byte[] signature)
        throws InvalidCipherTextException
    {
        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);
            Integer trailerObj = (Integer)trailerMap.get(digest.getAlgorithmName());

            if (trailerObj != null)
            {
                if (sigTrail != trailerObj.intValue())
                {
                    throw new IllegalStateException("signer initialised with wrong digest for trailer " + sigTrail);
                }
            }
            else
            {
                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++;

        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];
            System.arraycopy(block, mStart, recoveredMessage, 0, recoveredMessage.length);
        }
        else
        {
            fullMessage = false;

            recoveredMessage = new byte[off - mStart];
            System.arraycopy(block, mStart, recoveredMessage, 0, recoveredMessage.length);
        }

        preSig = signature;
        preBlock = block;

        digest.update(recoveredMessage, 0, recoveredMessage.length);
        messageLength = recoveredMessage.length;
    }