def setup_cipher
      raise RLPxSessionError, 'missing responder nonce' unless @responder_nonce
      raise RLPxSessionError, 'missing initiator_nonce' unless @initiator_nonce
      raise RLPxSessionError, 'missing auth_init' unless @auth_init
      raise RLPxSessionError, 'missing auth_ack' unless @auth_ack
      raise RLPxSessionError, 'missing remote ephemeral pubkey' unless @remote_ephemeral_pubkey
      raise InvalidKeyError, 'invalid remote ephemeral pubkey' unless Crypto::ECCx.valid_key?(@remote_ephemeral_pubkey)

      # derive base secrets from ephemeral key agreement
      # ecdhe-shared-secret = ecdh.agree(ephemeral-privkey, remote-ephemeral-pubk)
      @ecdhe_shared_secret = @ephemeral_ecc.get_ecdh_key(@remote_ephemeral_pubkey)
      @shared_secret = Crypto.keccak256("#{@ecdhe_shared_secret}#{Crypto.keccak256(@responder_nonce + @initiator_nonce)}")
      @token = Crypto.keccak256 @shared_secret
      @aes_secret = Crypto.keccak256 "#{@ecdhe_shared_secret}#{@shared_secret}"
      @mac_secret = Crypto.keccak256 "#{@ecdhe_shared_secret}#{@aes_secret}"

      mac1 = keccak256 "#{Utils.sxor(@mac_secret, @responder_nonce)}#{@auth_init}"
      mac2 = keccak256 "#{Utils.sxor(@mac_secret, @initiator_nonce)}#{@auth_ack}"

      if initiator?
        @egress_mac, @ingress_mac = mac1, mac2
      else
        @egress_mac, @ingress_mac = mac2, mac1
      end

      iv = "\x00" * 16
      @aes_enc = OpenSSL::Cipher.new(ENC_CIPHER).tap do |c|
        c.encrypt
        c.iv = iv
        c.key = @aes_secret
      end
      @aes_dec = OpenSSL::Cipher.new(ENC_CIPHER).tap do |c|
        c.decrypt
        c.iv = iv
        c.key = @aes_secret
      end
      @mac_enc = OpenSSL::Cipher.new(MAC_CIPHER).tap do |c|
        c.encrypt
        c.key = @mac_secret
      end

      @ready = true
    end
def setup_cipher
      raise RLPxSessionError, 'missing responder nonce' unless @responder_nonce
      raise RLPxSessionError, 'missing initiator_nonce' unless @initiator_nonce
      raise RLPxSessionError, 'missing auth_init' unless @auth_init
      raise RLPxSessionError, 'missing auth_ack' unless @auth_ack
      raise RLPxSessionError, 'missing remote ephemeral pubkey' unless @remote_ephemeral_pubkey
      raise InvalidKeyError, 'invalid remote ephemeral pubkey' unless Crypto::ECCx.valid_key?(@remote_ephemeral_pubkey)

      # derive base secrets from ephemeral key agreement
      # ecdhe-shared-secret = ecdh.agree(ephemeral-privkey, remote-ephemeral-pubk)
      @ecdhe_shared_secret = @ephemeral_ecc.get_ecdh_key(@remote_ephemeral_pubkey)
      @shared_secret = Crypto.keccak256("#{@ecdhe_shared_secret}#{Crypto.keccak256(@responder_nonce + @initiator_nonce)}")
      @token = Crypto.keccak256 @shared_secret
      @aes_secret = Crypto.keccak256 "#{@ecdhe_shared_secret}#{@shared_secret}"
      @mac_secret = Crypto.keccak256 "#{@ecdhe_shared_secret}#{@aes_secret}"

      mac1 = keccak256 "#{Utils.sxor(@mac_secret, @responder_nonce)}#{@auth_init}"
      mac2 = keccak256 "#{Utils.sxor(@mac_secret, @initiator_nonce)}#{@auth_ack}"

      if initiator?
        @egress_mac, @ingress_mac = mac1, mac2
      else
        @egress_mac, @ingress_mac = mac2, mac1
      end

      iv = "\x00" * 16
      @aes_enc = OpenSSL::Cipher.new(ENC_CIPHER).tap do |c|
        c.encrypt
        c.iv = iv
        c.key = @aes_secret
      end
      @aes_dec = OpenSSL::Cipher.new(ENC_CIPHER).tap do |c|
        c.decrypt
        c.iv = iv
        c.key = @aes_secret
      end
      @mac_enc = OpenSSL::Cipher.new(MAC_CIPHER).tap do |c|
        c.encrypt
        c.key = @mac_secret
      end

      @ready = true
    end
Handshake Key Derivation