public static string Cipher(this string data, CypherMode mode)
        {
            var kdf2BytesGenerator = new Kdf2BytesGenerator(new Sha1Digest());
            var kdfParameters      = new KdfParameters(Key, Iv);

            kdf2BytesGenerator.Init(kdfParameters);

            var key = new byte[16];

            kdf2BytesGenerator.GenerateBytes(key, 0, key.Length);

            var engine          = new AesLightEngine();
            var blockCipher     = new CbcBlockCipher(engine);
            var cipher          = new PaddedBufferedBlockCipher(blockCipher, new Pkcs7Padding());
            var parameter       = new KeyParameter(key);
            var parameterWithIv = new ParametersWithIV(parameter, Iv, 0, 16);

            var targetBytes = mode == CypherMode.Decryption
                ? Convert.FromBase64String(data)
                : Encoding.UTF8.GetBytes(data);

            cipher.Init(mode == CypherMode.Encryption, parameterWithIv);
            var output = new byte[cipher.GetOutputSize(targetBytes.Length)];
            var length = cipher.ProcessBytes(targetBytes, output, 0);

            cipher.DoFinal(output, length);

            return(mode == CypherMode.Encryption
                ? Convert.ToBase64String(output)
                : Encoding.UTF8.GetString(output.Where(@byte => @byte != 0).ToArray()));
        }
        static byte[] Kdf2(byte[] sharedKeyBytes, byte[] ephemeralKeyBytes)
        {
            var gen = new Kdf2BytesGenerator(new Sha256Digest());

            gen.Init(new KdfParameters(sharedKeyBytes, ephemeralKeyBytes));

            byte[] encryptionKeyBytes = new byte[48];
            gen.GenerateBytes(encryptionKeyBytes, 0, encryptionKeyBytes.Length);
            return(encryptionKeyBytes);
        }