using System;
using System.Windows.Forms;
using ComponentPro.Net;

namespace SshKeyGen
{
    public partial class KeyGen : Form
    {
        private readonly int[] _rsaKeySizes = new int[] {512, 1024, 2048, 4096};
        private readonly int[] _dsaKeySizes = new int[] {512, 1024};
        private SecureShellPrivateKey _privateKey;

        public KeyGen()
        {
            InitializeComponent();
            cbxKeySize.DataSource = _rsaKeySizes;
        }

        private void btnLoad_Click(object sender, EventArgs e)
        {
            if (openDialog.ShowDialog() == DialogResult.OK)
            {
                try
                {
                    PasswordPrompt pp = new PasswordPrompt();
                    if (pp.ShowDialog() == DialogResult.OK)
                    {
                        _privateKey = new SecureShellPrivateKey(openDialog.FileName, pp.Password);
                        rbtSshRsa.Enabled = (_privateKey.KeyAlgorithm == SecureShellHostKeyAlgorithm.RSA);

                        txtFingerprint.Text = _privateKey.Fingerprint.ToString();

                        BuildSshPublicKey(_privateKey.KeyAlgorithm);

                        txtPassphrase.Text = "";
                        txtConfirmPassphrase.Text = "";

                        btnSavePrivate.Enabled = true;
                        btnSavePublic.Enabled = true;
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show(string.Format("Unable to load the key file.\n{0}", ex.Message), "Loading failed", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }

                MessageBox.Show("Key file has been loaded successfuly.", "SSH Key Gen", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }

        private void btnGenerate_Click(object sender, EventArgs e)
        {
            try
			{
				Cursor.Current = Cursors.WaitCursor;

                SecureShellHostKeyAlgorithm algorithm;
			
				if (rbtSshRsa.Checked)
                    algorithm = SecureShellHostKeyAlgorithm.RSA;
				else
                    algorithm = SecureShellHostKeyAlgorithm.DSS;

				int keySize = (int)cbxKeySize.SelectedValue;

				// generate private key 
                _privateKey = SecureShellPrivateKey.Create(algorithm, keySize);

				// fingerprint
				txtFingerprint.Text = _privateKey.Fingerprint.ToString();

				BuildSshPublicKey(algorithm);

				btnSavePrivate.Enabled = true;
				btnSavePublic.Enabled = true;
			}
			finally
			{
				Cursor.Current = Cursors.Default;
			}
        }

        private void btnSavePublic_Click(object sender, EventArgs e)
        {
            saveDialog.Filter = "Public Certificate (*.pub)|*.pub";
			saveDialog.DefaultExt = "pub";

			if (saveDialog.ShowDialog() == DialogResult.OK) 
			{
				// save the public key 
				_privateKey.SavePublicKey(saveDialog.FileName);
				MessageBox.Show("The public key has been saved successfuly.", "SSH Key Gen", MessageBoxButtons.OK, MessageBoxIcon.Information);
			}
        }

        private void btnSavePrivate_Click(object sender, EventArgs e)
        {
            if (txtPassphrase.Text != txtConfirmPassphrase.Text) 
			{
				MessageBox.Show("Passphrases do not match.", "SSH Key Gen", MessageBoxButtons.OK, MessageBoxIcon.Error);
				return;
			}

			if (txtPassphrase.Text == "") 
			{
				if (MessageBox.Show(
					"Are you sure you want to save this key without a passphrase?",
					"SSH Key Gen",
					MessageBoxButtons.YesNoCancel,
					MessageBoxIcon.Warning) != DialogResult.Yes) 
				{
					return;
				}
			}

			saveDialog.Filter = "Private Key (*.pri)|*.pri";
			saveDialog.DefaultExt = "pem";
			if (saveDialog.ShowDialog() == DialogResult.OK) 
			{
				// save the private key 
				_privateKey.Save(saveDialog.FileName, txtPassphrase.Text, null);
				MessageBox.Show("The private key has been saved successfuly.", " SSH Key Gen", MessageBoxButtons.OK, MessageBoxIcon.Information);
			}
        }

        private void btnClose_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void BuildSshPublicKey(SecureShellHostKeyAlgorithm algorithm) 
		{
			// Get the raw data of SSH public key.
			byte[] rawPublicKey = _privateKey.GetPublicKey();

			string publicKeyAlgorithm;
			switch (algorithm)
			{
                case SecureShellHostKeyAlgorithm.RSA:
					publicKeyAlgorithm = "ssh-rsa";
					break;
                case SecureShellHostKeyAlgorithm.DSS:
					publicKeyAlgorithm = "ssh-dss";
					break;
				default:
					throw new ApplicationException("Unsupported algorithm.");
			}

			// The SSH public key to be added to OpenSSH's ~/.ssh/authorized_keys file 
			string sshPublicKey = string.Format("{0} {1} username@hostname", publicKeyAlgorithm, Convert.ToBase64String(rawPublicKey));

			// Show it.
            txtSsh.Text = sshPublicKey;
		}

        private void rbtSshRsa_CheckedChanged(object sender, EventArgs e)
        {
            if (rbtSshRsa.Checked)
                cbxKeySize.DataSource = _rsaKeySizes;
            else
                cbxKeySize.DataSource = _dsaKeySizes;

            if (cbxKeySize.Items.Count > 0)
                cbxKeySize.SelectedIndex = 0;
        }

        private void rbtSshDsa_CheckedChanged(object sender, EventArgs e)
        {
            if (rbtSshRsa.Checked)
                cbxKeySize.DataSource = _rsaKeySizes;
            else
                cbxKeySize.DataSource = _dsaKeySizes;

            if (cbxKeySize.Items.Count > 0)
                cbxKeySize.SelectedIndex = 0;
        }
    }
}