using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SecurityDriven.Inferno;
using SecurityDriven.Inferno.Extensions;
using SecurityDriven.Inferno.Kdf;

namespace PasswordAES_final {
    class Program {
        static void Main(string[] args) {
            // Ask for password
            Console.Write("Enter encryption password: ");
            var encPass = Console.ReadLine();

            // Generate key from password
            byte[] encKey, encSalt;
            using (var kdf = new PBKDF2(SuiteB.HmacFactory, encPass, saltSize: 32)) {
                encKey = kdf.GetBytes(32);
                encSalt = kdf.Salt;
            }
            Console.WriteLine($"Key:  {encKey.ToBase16()}");
            Console.WriteLine($"Salt: {encSalt.ToBase16()}");
            Console.WriteLine();

            // Get message
            Console.Write("Get message to encrypt: ");
            var message = Console.ReadLine();
            var messageArray = message.ToBytes().AsArraySegment();

            // AEAD encrypt
            var encData = SuiteB.Encrypt(encKey, messageArray);
            var encString = encData.ToBase16();
            Console.WriteLine($"Encrypted data: {encString}");
            Console.WriteLine();

            // Get message to decrypt
            Console.Write("Enter message to decrypt (or just ENTER for original one): ");
            var ciphertextString = Console.ReadLine();
            if (string.IsNullOrEmpty(ciphertextString)) ciphertextString = encString;
            var ciphertextArray = ciphertextString.FromBase16().AsArraySegment();

            // Ask for password
            Console.Write("Enter decryption password: ");
            var decPass = Console.ReadLine();

            // Ask for salt
            Console.Write("Enter decryption salt: ");
            var decSaltString = Console.ReadLine();
            var decSalt = decSaltString.FromBase16();

            // Generate key from password
            byte[] decKey;
            using (var kdf = new PBKDF2(SuiteB.HmacFactory, encPass, decSalt)) {
                decKey = kdf.GetBytes(32);
            }

            // Authenticate
            var isAuthenticated = SuiteB.Authenticate(encKey, ciphertextArray);
            if (!isAuthenticated) {
                Console.WriteLine("Message is not authenticated!");
            } else {
                Console.WriteLine("Message authenticated successfully.");

                var plaintextBytes = SuiteB.Decrypt(encKey, ciphertextArray);
                var plaintextString = plaintextBytes.FromBytes();
                Console.WriteLine($"Decrypted message: {plaintextString}");
            }
        }
    }
}
