package be.iminds.ilabt.jfed.ssh_terminal_tool.putty;

import be.iminds.ilabt.jfed.lowlevel.ssh_key_info.putty.PuTTYPrivateKeyFile;
import be.iminds.ilabt.jfed.util.FileEncrypter;
import be.iminds.ilabt.jfed.util.KeyUtil;
import org.testng.Assert;
import org.testng.annotations.Test;

import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.security.*;
import java.security.interfaces.RSAPrivateCrtKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;

/**
 * PuttyTest
 */
public class PuttyTest {
    /*
    * "rsa2@22:bastion.test.iminds.be"="0x10001,0xd6c63bfb035045eba9c591607e7c2cc218756c3c4cb1544a1ee1aad3fb0723652484b44658632faf78e6fe1f6f3e03e6aeaf544102578b7d34daf70e6a88f983fc82de2ade4b1ec03c731af676d83169d1a037122ac96289c3edcbe7da948fb60d2c31e694f101c6ba0159640ca9258a7a219dd095ef5054d18fb45a3de9da183dd7cd25b567e7ee6062b6cea28a3c0c1d4e9eb0a0fca7f7c6cf820c15d1373053a721d5c7893b04bbe25ddc75c120957050ea1369f5eea430c62d7dac55a45ad0b67afe94e2e57597646c236dc794d1e97d4c18bb105088cb89284ce26284d3a7addef3bd92a8db72f8c4d0523720813ca6cdc066acc90231ec72c450d787c1"
    * */

    @Test
    public void puttyHostKeyTest() {
        String in =
                "bastion.test.iminds.be ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDWxjv7A1BF66nFkWB+fCzCGHVsPEyxVEoe4a" +
                        "rT+wcjZSSEtEZYYy+veOb+H28+A+aur1RBAleLfTTa9w5qiPmD/ILeKt5LHsA8cxr2dtgxadGgNxIqyWKJw+3L59qUj7YNLDHmlPEB" +
                        "xroBWWQMqSWKeiGd0JXvUFTRj7RaPenaGD3XzSW1Z+fuYGK2zqKKPAwdTp6woPyn98bPggwV0TcwU6ch1ceJOwS74l3cdcEglXBQ6h" +
                        "Np9e6kMMYtfaxVpFrQtnr+lOLldZdkbCNtx5TR6X1MGLsQUIjLiShM4mKE06et3vO9kqjbcvjE0FI3IIE8ps3AZqzJAjHscsRQ14fB";
        String expected =
                "0x10001,0xd6c63bfb035045eba9c591607e7c2cc218756c3c4cb1544a1ee1aad3fb0723652484b44658632faf78e6fe1f6f3e03e6aeaf544102578b7d34daf70e6a88f983fc82de2ade4b1ec03c731af676d83169d1a037122ac96289c3edcbe7da948fb60d2c31e694f101c6ba0159640ca9258a7a219dd095ef5054d18fb45a3de9da183dd7cd25b567e7ee6062b6cea28a3c0c1d4e9eb0a0fca7f7c6cf820c15d1373053a721d5c7893b04bbe25ddc75c120957050ea1369f5eea430c62d7dac55a45ad0b67afe94e2e57597646c236dc794d1e97d4c18bb105088cb89284ce26284d3a7addef3bd92a8db72f8c4d0523720813ca6cdc066acc90231ec72c450d787c1";
        String actual = PuttyHelper.convertSshHostKeyToPuttyFormat(in);
        Assert.assertEquals(actual, expected);
    }


    @Test
    public void sshHostKeyToRegistryKeyTest() {
        String in =
                "bastion.test.iminds.be ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDWxjv7A1BF66nFkWB+fCzCGHVsPEyxVEoe4a" +
                        "rT+wcjZSSEtEZYYy+veOb+H28+A+aur1RBAleLfTTa9w5qiPmD/ILeKt5LHsA8cxr2dtgxadGgNxIqyWKJw+3L59qUj7YNLDHmlPEB" +
                        "xroBWWQMqSWKeiGd0JXvUFTRj7RaPenaGD3XzSW1Z+fuYGK2zqKKPAwdTp6woPyn98bPggwV0TcwU6ch1ceJOwS74l3cdcEglXBQ6h" +
                        "Np9e6kMMYtfaxVpFrQtnr+lOLldZdkbCNtx5TR6X1MGLsQUIjLiShM4mKE06et3vO9kqjbcvjE0FI3IIE8ps3AZqzJAjHscsRQ14fB";
        String expected = "rsa2@22:bastion.test.iminds.be";
        String actual = PuttyHelper.sshHostKeyToRegistryKey(in, 22);
        Assert.assertEquals(actual, expected);

    }

    @Test
    public void testEncryptDecrypt() throws NoSuchAlgorithmException, UnsupportedEncodingException {
        String tstString = "This is the data to be encrypted";
        byte[] origData = tstString.getBytes(Charset.forName("UTF-8"));

        KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
        keyGen.initialize(2048);
        KeyPair keyPair = keyGen.genKeyPair();
        PublicKey publicKey = keyPair.getPublic();
        PrivateKey privateKey = keyPair.getPrivate();

        byte[] encData = FileEncrypter.encryptData(origData, publicKey);
        byte[] decrData = FileEncrypter.decryptData(encData, privateKey);

        System.out.println("Original data: " + new String(origData, "utf-8"));
        System.out.println("Encoded data: " + new String(encData, "utf-8"));
        System.out.println("Decrypted data: " + new String(decrData, "utf-8"));

        Assert.assertEquals(decrData, origData);
    }


    //PuTTYPrivateKeyFile tests

    @Test
    public void testToPPKFormat() throws KeyUtil.PEMDecodingException {
        String pem = encrypted_pem;
        String pass = encryptionPass;
        String expected_ppk = unencrypted_putty_ppk;

        PrivateKey privKey = KeyUtil.pemToAnyPrivateKey(pem, pass.toCharArray());
        PublicKey pubKey = KeyUtil.rsaPrivateKeyToRsaPublicKey((RSAPrivateKey) privKey);

        String actual_ppk = PuTTYPrivateKeyFile.createContent("rsa-key-20140128",
                (RSAPublicKey) pubKey, (RSAPrivateCrtKey) privKey, null);

        System.out.println("Expected: " + expected_ppk);
        System.out.println("Actual: " + actual_ppk);

        Assert.assertEquals(actual_ppk, expected_ppk);
    }

    @Test
    public void testToPPKFormatEncrypted() throws KeyUtil.PEMDecodingException {
        String pem = encrypted_pem;
        String pass = encryptionPass;
        String expected_ppk = encrypted_putty_ppk;

        PrivateKey privKey = KeyUtil.pemToAnyPrivateKey(pem, pass.toCharArray());
        PublicKey pubKey = KeyUtil.rsaPrivateKeyToRsaPublicKey((RSAPrivateKey) privKey);

        String actual_ppk = PuTTYPrivateKeyFile.createContent("rsa-key-20140128",
                (RSAPublicKey) pubKey, (RSAPrivateCrtKey) privKey, encryptionPass);

        System.out.println("Expected: " + expected_ppk);
        System.out.println("Actual: " + actual_ppk);

        Assert.assertEquals(actual_ppk, expected_ppk);
    }

    @Test
    public void testFromPPKFormatUnencrypted() throws KeyUtil.PEMDecodingException {
        String pem = encrypted_pem;
        String pass = encryptionPass;
        PuTTYPrivateKeyFile ppk = PuTTYPrivateKeyFile.parse(unencrypted_putty_ppk);

        PrivateKey expected_privKey = KeyUtil.pemToAnyPrivateKey(pem, pass.toCharArray());

        PrivateKey actual_privKey = ppk.getPrivateKey();

        Assert.assertEquals(actual_privKey, expected_privKey);
    }

    @Test
    public void testFromPPKFormatEncrypted() throws KeyUtil.PEMDecodingException {
        String pem = encrypted_pem;
        String pass = encryptionPass;
        PuTTYPrivateKeyFile ppk = PuTTYPrivateKeyFile.parse(encrypted_putty_ppk);
        ppk.unlock(encryptionPass);

        PrivateKey expected_privKey = KeyUtil.pemToAnyPrivateKey(pem, pass.toCharArray());

        PrivateKey actual_privKey = ppk.getPrivateKey();

        Assert.assertEquals(actual_privKey, expected_privKey);
    }

    @Test
    public void testIsPPk() {
        Assert.assertFalse(PuTTYPrivateKeyFile.isPuttyPrivateKey(unencrypted_public_key_openssh));
        Assert.assertFalse(PuTTYPrivateKeyFile.isPuttyPrivateKey(encrypted_pem));
        Assert.assertTrue(PuTTYPrivateKeyFile.isPuttyPrivateKey(unencrypted_putty_ppk));
        Assert.assertTrue(PuTTYPrivateKeyFile.isPuttyPrivateKey(encrypted_putty_ppk));
    }

    @Test
    public void testPPKToPublicKey() throws KeyUtil.PEMDecodingException {
        String pubkeyText = unencrypted_public_key_openssh;
        PuTTYPrivateKeyFile ppk = PuTTYPrivateKeyFile.parse(unencrypted_putty_ppk);

        PublicKey expected_pubKey = KeyUtil.openSshAuthorizedKeysFormatRsaPublicKey(pubkeyText);
        PublicKey actual_pubKey = ppk.getPublicKey();

        Assert.assertEquals(actual_pubKey, expected_pubKey);
    }

    @Test
    public void testIsPPkEncrypted() throws KeyUtil.PEMDecodingException {
        Assert.assertFalse(PuTTYPrivateKeyFile.parse(unencrypted_putty_ppk).isEncrypted());
        Assert.assertTrue(PuTTYPrivateKeyFile.parse(encrypted_putty_ppk).isEncrypted());
    }


    //the following keys are all of the same public and private key, in vairous formats
    private static final String unencrypted_public_key_openssh =
            "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAQEAySnserUhDwxU3P+MCPxqmMPSL4WpSKKUMYrV" +
                    "6y2UGD4tAIahUUj2/xbJGmjnLDYP4saUp7dko3e7oefN7Zk0oJDQuSJPzhiIS4gA" +
                    "hVKRMls+xtCkmDJ1OHvcmsFMuJYErygmqxlFHgdHkIrE6BNZtCYe+60AZU8V8P5K" +
                    "woaneXIiARO3GfRdhfsn1jF5WP+/fTDOerLdUR6AQ+5PPyK5+uMySPIg7WZNfrCC" +
                    "YOI1GQLWihsF4o1SeU++NHHspUwVFDQbrS0tJlqlgkDoQxVRibWCkIbsm50+Vl8c" +
                    "PfNTKcdV+aMQm6wRWG91rYORmZcqqcaN1Igvn+bsVUitAB+atw=="/*+"  comment"*/;
    private static final String encryptionPass = "test";
    private static final String encrypted_pem = "-----BEGIN RSA PRIVATE KEY-----\n" +
            "Proc-Type: 4,ENCRYPTED\n" +
            "DEK-Info: DES-EDE3-CBC,B7D0B61AFADDB308\n" +
            "\n" +
            "Hso2tRv1fbdhKdLBsgUcXr/UQ35A2HfidFEC8xiG+h4W0pSj8kz2LcJqDROSaP4z\n" +
            "1W8X6la5KaMLqYf1EVLuMAZz9IvyB/kaZpp9N/qFQuxnJL+425kslcn61Me6l5dC\n" +
            "CB6c0vfbvgR9een7WtaJT6Z8SRp5PmM8DCSioPh8X1ktlvUNJ3I0ckLEHi3aiMBM\n" +
            "0gWMitXuOS/Hb5zohOaQ1yq8dxeifzokEunUfLKZ9yuF0L+JTJ3LZddTy1MYkIoP\n" +
            "FWPrthfY5yK4/zbpN+ucEBjG5EEyFPySDz5NVpDAlR8h4fEkeNuUZ/MWr4Ce2zO3\n" +
            "TXraE8wLeSC5JIFXMfn0KUjrz8UmEtjvJbMpERUQWbzF6kICnAB6+nyiU19OLhJo\n" +
            "MSTZMOh2NjnQ6y501B4dH9gbQJuoYURGQ59n/2UekyrXlOR7dNSD6vJEUNy8cCap\n" +
            "6XRJKc5++Igyhh3oZLB7yib69oDv9rsyzelcA2PnTCpv8dOEr/j+6HkvTUHHnZDN\n" +
            "lAEjn5EKYksNq0ZAWHh8uCNhsj3f7kMw+mP5kAWI/SODy6CXql+54/Jy//OcXl1N\n" +
            "mB+1HsDrlIXr23iwVYyEPKg1hd6Or/rmHJxiX+/HlSzFqsieZdf5lK+Dx8lKl0pg\n" +
            "VZNiW8RvWRqV6vJYRcpcE9TcysZ7Udv0IPqrLawOCifk6Zl3T1IP21OumvKkinIi\n" +
            "TZ/fVmDBLxkR1itovI4wTk/T8sMKApani+ByIcRrO/Kia9PjdRka+wVDEetSIufd\n" +
            "i+Y+x4+y4+uSSn75Mfdt9dDn8YW6DAYqtv46MRLmFVzybT9+U7ECs0xXlxZtk9+L\n" +
            "f3nX1bP2pXs5gyHIauKbqY2earzUfMitsOJ05OiVrWESdfHVX/cbRd4u6zTwudGW\n" +
            "rMJP6AWzPYx9LxjyKCWnu1I/V2qehM92WhLKRJheenoLF6BYuP9WZjOome6r5wNc\n" +
            "9RrLutoRUt6RRDY0zGLptffQ0PnTgg7onOY5AeybdaMzSWKZ06kzysZ17meGsmGZ\n" +
            "Dnry+JcaIOItlOY6xvlJe7s+6rZ5dYYInKt+C5MgwYSRC+1pKzyWApfkSSeV4loq\n" +
            "NaRefz+yVCEkw4qQwR1VTMvKwrAuhReHLyXJN7OO1WVhs45wEoFNmKET2kH9ilJb\n" +
            "zdXcOq9iajO4HpOLZiOF/ckWrXfF7Oyv5UfrH616l2O8YSD6TXk7gG2XAONPAzW+\n" +
            "ofIzMVv5WbRU6IoHwESi6/n6+QUbr+sh59qmB7CIbQ/j8rID+8oXcwecqzeqNetd\n" +
            "xrM2yAQQLnNKtu5FgwqGEbBDztZG2+IEibkeH291T/iZagT70E8CLmWwcHYUMeYa\n" +
            "rQ8sUbPNCl7fjyIF+nvNdV1uMHPAOLxcF2ZYOtHi7DfqnihflWVofbtxm9Ao65dd\n" +
            "BmQGaadkvnsGOVMf2zF5FviyTN6XKK+WggedJm+D77ogqSgfA5KOSQyMxEiqtSUb\n" +
            "TjtVdNcpUbJOMckCO7yHtdQeEnbZeH9UvQcek7cEcn+M5qGcaj8VysaklDZtwWFX\n" +
            "VjBxcjH63mk2/T9Oh5BBM0UZdUEC20DwqLQwyYo9YmeTS7nzt9OHzw==\n" +
            "-----END RSA PRIVATE KEY-----";
    private static final String unencrypted_putty_ppk = "PuTTY-User-Key-File-2: ssh-rsa\n" +
            "Encryption: none\n" +
            "Comment: rsa-key-20140128\n" +
            "Public-Lines: 6\n" +
            "AAAAB3NzaC1yc2EAAAABJQAAAQEAySnserUhDwxU3P+MCPxqmMPSL4WpSKKUMYrV\n" +
            "6y2UGD4tAIahUUj2/xbJGmjnLDYP4saUp7dko3e7oefN7Zk0oJDQuSJPzhiIS4gA\n" +
            "hVKRMls+xtCkmDJ1OHvcmsFMuJYErygmqxlFHgdHkIrE6BNZtCYe+60AZU8V8P5K\n" +
            "woaneXIiARO3GfRdhfsn1jF5WP+/fTDOerLdUR6AQ+5PPyK5+uMySPIg7WZNfrCC\n" +
            "YOI1GQLWihsF4o1SeU++NHHspUwVFDQbrS0tJlqlgkDoQxVRibWCkIbsm50+Vl8c\n" +
            "PfNTKcdV+aMQm6wRWG91rYORmZcqqcaN1Igvn+bsVUitAB+atw==\n" +
            "Private-Lines: 14\n" +
            "AAABACCfA8DfGh4drOWROU2Qt1cK/31T8fAaXTh3YPW0XTRdHA3sUYLNj9ZWuNPZ\n" +
            "qPJpobYSXUuhMuoTaoj1KFALAZ1/RHEMe6ThYjXDBwDc9PNovhJnBe8qxuaQoFBy\n" +
            "X3fg+dc28YOHjqrsbHhN2r3Zn9gGLomtWgKXM/2RBTRNL+ot5PBOxglBxTloX9Eg\n" +
            "nE1KYL5Zg2OZDcvUzq9hVtGYhj4jKH+1FPr4OW/9XOfQYHxUnud7MXK3xmINaEcd\n" +
            "hGldocRbsiReUeKITAwXr9RA/X6qC/LuYMcPbBkcH6kLoiaDUE7bDZLC/x+2B6F3\n" +
            "MTqg3ILZnPPo4nJZjPEDF444sG0AAACBAP6o4oxQ0lUG3X0JWw82cc2+3x1ZJpXY\n" +
            "g/rgLakfLzF8173qMfqPd3WceOBqaizZoQEOCs3vcQexYsnJ4WtM6buhVhsggwT9\n" +
            "87XzKmGkYQ+QxFB6LD47T60kqpRZtA1lR+G3vslf1DPTtY1XJ/eUYTvObX+bfvRV\n" +
            "dzRpvanzOwSnAAAAgQDKOPYQOrcdnRoGmI1Q8JidKH8G5gcdD6TgKj25aMb3VDKl\n" +
            "SzjPp57LBPKPtkhf61gBk0Mxr68Da0TxXq/QzqDz4qiLVw8vM3PFRIR1Ac4mwS3o\n" +
            "ZvIEP252ltxvUczd1wBaW51ziCVi69dj8qc/xlX0XxsbrkJxiUd9cqKcdTGrcQAA\n" +
            "AIEAlMBHqGYJFadThKRrGwewk/t47CZCOo2XogZDYelqqDVP4Iy8xHAOORvNLxm/\n" +
            "xnSJ5ByQKp7cCcTNCD8imeXovbbmXewfhyuTNtrEmJ7x3rx6IOPqjHjN8vtxh388\n" +
            "fYYyOkzUQbRQTmHCfPYWSVBVz0T6qzX/R4khxjQHwm0NMPM=\n" +
            "Private-MAC: 6d28debfdba9fcd4a5e61d3d6a5152d89e900233\n";
    private static final String encrypted_putty_ppk = "PuTTY-User-Key-File-2: ssh-rsa\n" +
            "Encryption: aes256-cbc\n" +
            "Comment: rsa-key-20140128\n" +
            "Public-Lines: 6\n" +
            "AAAAB3NzaC1yc2EAAAABJQAAAQEAySnserUhDwxU3P+MCPxqmMPSL4WpSKKUMYrV\n" +
            "6y2UGD4tAIahUUj2/xbJGmjnLDYP4saUp7dko3e7oefN7Zk0oJDQuSJPzhiIS4gA\n" +
            "hVKRMls+xtCkmDJ1OHvcmsFMuJYErygmqxlFHgdHkIrE6BNZtCYe+60AZU8V8P5K\n" +
            "woaneXIiARO3GfRdhfsn1jF5WP+/fTDOerLdUR6AQ+5PPyK5+uMySPIg7WZNfrCC\n" +
            "YOI1GQLWihsF4o1SeU++NHHspUwVFDQbrS0tJlqlgkDoQxVRibWCkIbsm50+Vl8c\n" +
            "PfNTKcdV+aMQm6wRWG91rYORmZcqqcaN1Igvn+bsVUitAB+atw==\n" +
            "Private-Lines: 14\n" +
            "H2jPnvfGAMvCHuvhDHmhsdMKFboPBf3kkwRF7uduWRmM8iIfQjaD6o76Nr6ET0CC\n" +
            "lfm3sTTL1W3PRBO9QGSoS0QrgbfKRMMhWTj64U1ROR1rG8/UWCGVd2dSFi4q5GCH\n" +
            "BglI1zzZCDCMA+zzkf/tDyYkBKPCiRthaUn2VZx/o6hoj3jsZ396V7aTaAl4lQPl\n" +
            "uNpto+E/HqVLzQVZvEvKB8yGWGeikKtfcttIyyeh9LqVV3CjXZwDNi8xLBJBHsf5\n" +
            "hxejIdzg+EXaFT4JgjqwVT51iSl9iJQq1RLjyJHJFbslyqsvtGTTUYecHL+cHjMH\n" +
            "NdI3lJnbpD2TD6AddxEfUDH6mVx7sPTLgouArcSy03mZZVeTw5ex/FpKpSKBxyHA\n" +
            "A54DTifqXXUn6rhkgrjYm3GzNA0ZxJbbSCuEGKFkP7dIb9CEWScsa4vACmHELmr3\n" +
            "qM6dIIrqpEU6V3CidhVh+RKZILbWmVL2ilyqg7Cy7xbtQk9SnfCi3igh1mpoSCJg\n" +
            "NScy3HiWCC25Tai/hfV+aB9EFG+KVepALbws4CrYJakrGFeIbFhgO9hvEK19+I5e\n" +
            "Ao07GIW/oLskKo2INaTibylp9o3Qk/4j2sWN/o3Yqo5XwzXOMJi5qiY0pJXVLze4\n" +
            "6+xVDPFqvi3gWTjBplx/0ygUhZrlhOXSgVtrZ3zm3dgPQ4qnuWyEPgzMRKpyA00I\n" +
            "dc5bv1EdOQVjsxoSV85r+14gSIavGwJ3j8hHPl/MJlW18dZRt8JlMC9Q0z6q42Z/\n" +
            "grxOHsrn4nUuDk+pQZ5QweTGo/r3QG/5727xYYDZ0D2KS7nwDQmAURLq1qAU7b+Y\n" +
            "A+d3nhd6oCi8EGSW6RB1tq+z7GpNaU8726TN6oA5J7UxMzm82W51NCnVxk0Elxsv\n" +
            "Private-MAC: 7882dea436226e47304a9388263e0ee3ec92658a\n"; //pass = test
}
