# File lib/Dnsruby/resource/TSIG.rb, line 248
      def verify_envelope(response, response_bytes)
        #RFC2845 Section 4.4
        #-----
        #A DNS TCP session can include multiple DNS envelopes.  This is, for
        #example, commonly used by zone transfer.  Using TSIG on such a
        #connection can protect the connection from hijacking and provide data
        #integrity.  The TSIG MUST be included on the first and last DNS
        #envelopes.  It can be optionally placed on any intermediary
        #envelopes.  It is expensive to include it on every envelopes, but it
        #MUST be placed on at least every 100'th envelope.  The first envelope
        #is processed as a standard answer, and subsequent messages have the
        #following digest components:
        #
        #*   Prior Digest (running)
        #*   DNS Messages (any unsigned messages since the last TSIG)
        #*   TSIG Timers (current message)
        #
        #This allows the client to rapidly detect when the session has been
        #altered; at which point it can close the connection and retry.  If a
        #client TSIG verification fails, the client MUST close the connection.
        #If the client does not receive TSIG records frequently enough (as
        #specified above) it SHOULD assume the connection has been hijacked
        #and it SHOULD close the connection.  The client SHOULD treat this the
        #same way as they would any other interrupted transfer (although the
        #exact behavior is not specified).
        #-----
        #
        # Each time a new envelope comes in, this method is called on the QUERY TSIG RR.
        # It will set the response tsigstate to :Verified :Intermediate or :Failed
        # as appropriate.
        
        # Keep digest going of messages as they come in (and mark them intermediate)
        # When TSIG comes in, work out what key should be and check. If OK, mark 
        # verified. Can reset digest then.
        if (!@buf)
          @num_envelopes = 0
          @last_signed = 0
        end
        @num_envelopes += 1
        if (!response.tsig)
          if ((@num_envelopes > 1) && (@num_envelopes - @last_signed < 100))
            TheLog.debug("Receiving intermediate envelope in TSIG TCP session")
            response.tsigstate = :Intermediate
            response.tsigerror = RCode.NOERROR
            @buf = @buf + response_bytes
            return
          else
            response.tsigstate = :Failed
            TheLog.error("Expecting signed packet")
            return false
          end
        end
        @last_signed = @num_envelopes
        
        # We have a TSIG - process it!
        tsig = response.tsig
        if (@num_envelopes == 1)
          TheLog.debug("First response in TSIG TCP session - verifying normally")
          # Process it as a standard answer
          ok = verify(@query, response, response_bytes)
          if (ok)
            mac_bytes = MessageEncoder.new {|m|
              m.put_pack('n', tsig.mac_size)
              m.put_bytes(tsig.mac)
            }.to_s
            @buf = mac_bytes
          else
          end
          return ok
        end
        TheLog.debug("Processing TSIG on TSIG TCP session")

        if (!verify_common(response))
          return false
        end
        
        # Now add the current message data - remember to frig the arcount
        response_bytes = Header.decrement_arcount_encoded(response_bytes)
        @buf += response_bytes[0, response.tsigstart]
        
        # Let's add the timers
        timers_data = MessageEncoder.new { |msg|
          time_high = (tsig.time_signed >> 32)
          time_low = (tsig.time_signed & 0xFFFFFFFF)
          msg.put_pack('nN', time_high, time_low)
          msg.put_pack('n', tsig.fudge)
        }.to_s
        @buf += timers_data
        
        mac = nil
        key = @key.gsub(" ", "")
        key = Base64::decode64(key)
        if (tsig.algorithm == HMAC_MD5)
          mac = OpenSSL::HMAC.digest(OpenSSL::Digest::MD5.new, key, @buf)
        elsif (tsig.algorithm == HMAC_SHA1)
          mac = OpenSSL::HMAC.digest(OpenSSL::Digest::SHA1.new, key, @buf)
        elsif (tsig.algorithm == HMAC_SHA256)
          mac = OpenSSL::HMAC.digest(OpenSSL::Digest::SHA256.new, key, @buf)
        else
          # Should we allow client to pass in their own signing function?
          raise RuntimeError.new("Algorithm #{tsig.algorithm} unsupported by TSIG")
        end

        if (mac != tsig.mac)
          TheLog.error("TSIG Verify error on TSIG TCP session")
          response.tsigstate = :Failed
          return false
        end
        mac_bytes = MessageEncoder.new {|m|
          m.put_pack('n', mac.length)
          m.put_bytes(mac)
        }.to_s
        @buf=mac_bytes

        response.tsigstate = :Verified
        response.tsigerror = RCode.NOERROR
        return true
      end