text: 'use strict';
  
  const assert = require('assert');
  
  const {
    fixtureKey,
    mustCall,
    setup,
  } = require('./common.js');
  
  const debug = false;
  
  [
    { desc: 'RSA user key (old OpenSSH)',
      hostKey: fixtureKey('id_rsa') },
    { desc: 'RSA user key (new OpenSSH)',
      hostKey: fixtureKey('openssh_new_rsa') },
    { desc: 'DSA host key',
      hostKey: fixtureKey('ssh_host_dsa_key') },
    { desc: 'ECDSA host key',
      hostKey: fixtureKey('ssh_host_ecdsa_key') },
    { desc: 'PPK',
      hostKey: fixtureKey('id_rsa.ppk') },
  ].forEach((test) => {
    const { desc, hostKey } = test;
    const clientKey = fixtureKey('openssh_new_rsa');
    const username = 'KeyUser';
    const { server } = setup(
      desc,
      {
        client: {
          username,
          privateKey: clientKey.raw,
          algorithms: {
            serverHostKey: [ hostKey.key.type ],
          }
        },
        server: { hostKeys: [ hostKey.raw ] },
        debug,
      }
    );
  
    server.on('connection', mustCall((conn) => {
      let authAttempt = 0;
      conn.on('authentication', mustCall((ctx) => {
        assert(ctx.username === username,
               `Wrong username: ${ctx.username}`);
        switch (++authAttempt) {
          case 1:
            assert(ctx.method === 'none'),
                   `Wrong auth method: ${ctx.method}`;
            return ctx.reject();
          case 3:
            assert(ctx.signature, 'Missing publickey signature');
          // FALLTHROUGH
          case 2:
            assert(ctx.method === 'publickey',
                   `Wrong auth method: ${ctx.method}`);
            assert(ctx.key.algo === clientKey.key.type,
                   `Wrong key algo: ${ctx.key.algo}`);
            assert.deepStrictEqual(clientKey.key.getPublicSSH(),
                                   ctx.key.data,
                                   'Public key mismatch');
            break;
        }
        if (ctx.signature) {
          assert(clientKey.key.verify(ctx.blob, ctx.signature) === true,
                 'Could not verify publickey signature');
        }
        ctx.accept();
      }, 3)).on('ready', mustCall(() => {
        conn.end();
      }));
    }));
  });
  
  
  {
    const RSA_KEY = fixtureKey('ssh_host_rsa_key');
    const ECDSA_KEY = fixtureKey('ssh_host_ecdsa_key');
    [ RSA_KEY, ECDSA_KEY ].forEach((key) => {
      const selKeyType = key.key.type;
      const clientKey = fixtureKey('openssh_new_rsa');
      const username = 'KeyUser';
      const { client, server } = setup(
        `Multiple host key types (${key.type} selected)`,
        {
          client: {
            username,
            privateKey: clientKey.raw,
            algorithms: {
              serverHostKey: [ selKeyType ],
            }
          },
          server: { hostKeys: [ RSA_KEY.raw, ECDSA_KEY.raw ] },
          debug,
        }
      );
  
      server.on('connection', mustCall((conn) => {
        let authAttempt = 0;
        conn.on('authentication', mustCall((ctx) => {
          assert(ctx.username === username,
                 `Wrong username: ${ctx.username}`);
          switch (++authAttempt) {
            case 1:
              assert(ctx.method === 'none'),
                     `Wrong auth method: ${ctx.method}`;
              return ctx.reject();
            case 3:
              assert(ctx.signature, 'Missing publickey signature');
            // FALLTHROUGH
            case 2:
              assert(ctx.method === 'publickey',
                     `Wrong auth method: ${ctx.method}`);
              assert(ctx.key.algo === clientKey.key.type,
                     `Wrong key algo: ${ctx.key.algo}`);
              assert.deepStrictEqual(clientKey.key.getPublicSSH(),
                                     ctx.key.data,
                                     'Public key mismatch');
              break;
          }
          if (ctx.signature) {
            assert(clientKey.key.verify(ctx.blob, ctx.signature) === true,
                   'Could not verify publickey signature');
          }
          ctx.accept();
        }, 3)).on('ready', mustCall(() => {
          conn.end();
        }));
      }));
      client.on('handshake', mustCall((info) => {
        assert(info.serverHostKey === selKeyType, 'Wrong host key selected');
      }));
    });
  }
  