在 c# .Net Framework 中解密 Google Cookies?

Decrypt Google Cookies in c# .Net Framework?

我已经创建了这个,它能够在给定特定域名时从 Google Chrome 获取 cookie。但是,这些值已解密。我知道一定有一种方法可以修改我的代码来解密这些值。

using Microsoft.Data.Sqlite;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace Test
{
    public class Test
    {
        public List<Data> GetCookies(string hostname)
        {
            List<Data> data = new List<Data>();
            if (ChromeCookiesExists())
            {
                try
                {
                    using (var conn = new SqliteConnection($"Data Source={ChromeCookiePath}"))
                    using (var cmd = conn.CreateCommand())
                    {
                        cmd.CommandText = $"SELECT name,encrypted_value,host_key FROM cookies WHERE host_key = '{hostname}'";

                        conn.Open();
                        using (var reader = cmd.ExecuteReader())
                        {
                            while (reader.Read())
                            {
                                if (!data.Any(a => a.Name == reader.GetString(0)))
                                {
                                    data.Add(new Data()
                                    {
                                        Name = reader.GetString(0),
                                        Value = reader.GetString(1)  //HERE is my problem because this returns encrypted value not decrypted
                                    });
                                }
                            }
                        }
                        conn.Close();
                    }
                }
                catch { }
            }
            return data;
        }

        private string ChromeCookiePath = @"C:\Users\" + Environment.UserName + @"\AppData\Local\Google\Chrome\User Data\Default\Cookies";


        private bool ChromeCookiesExists()
        {
            if (File.Exists(ChromeCookiePath))
                return true;
            return false;
        }

        public class Data
        {
            public string Name { get; set; }
            public string Value { get; set; }
        }
    }
}

此代码输出一个名为 Data 的结构,其中包含 cookie 的名称和值(只是未解密的 atm)。

多亏了 Topaco 的评论和 UnCavoHDMI,我才能够把它放在一起。

class ChromeManager
        {
            public List<Cookie> GetCookies(string hostname)
            {
                string ChromeCookiePath = @"C:\Users\" + Environment.UserName + @"\AppData\Local\Google\Chrome\User Data\Default\Cookies";
                List<Cookie> data = new List<Cookie>();
                if (File.Exists(ChromeCookiePath))
                {
                    try
                    {
                        using (var conn = new SqliteConnection($"Data Source={ChromeCookiePath}"))
                        using (var cmd = conn.CreateCommand())
                        {
                            cmd.CommandText = $"SELECT name,encrypted_value,host_key FROM cookies WHERE host_key = '{hostname}'";
                            byte[] key = AesGcm256.GetKey();

                            conn.Open();
                            using (var reader = cmd.ExecuteReader())
                            {
                                while (reader.Read())
                                {
                                    if (!data.Any(a => a.Name == reader.GetString(0)))
                                    {
                                        byte[] encryptedData = GetBytes(reader, 1);
                                        byte[] nonce, ciphertextTag;
                                        AesGcm256.prepare(encryptedData, out nonce, out ciphertextTag);
                                        string value = AesGcm256.decrypt(ciphertextTag, key, nonce);

                                        data.Add(new Cookie()
                                        {
                                            Name = reader.GetString(0),
                                            Value = value
                                        });
                                    }
                                }
                            }
                            conn.Close();
                        }
                    }
                    catch { }
                }
                return data;

            }

            private byte[] GetBytes(SqliteDataReader reader, int columnIndex)
            {
                const int CHUNK_SIZE = 2 * 1024;
                byte[] buffer = new byte[CHUNK_SIZE];
                long bytesRead;
                long fieldOffset = 0;
                using (MemoryStream stream = new MemoryStream())
                {
                    while ((bytesRead = reader.GetBytes(columnIndex, fieldOffset, buffer, 0, buffer.Length)) > 0)
                    {
                        stream.Write(buffer, 0, (int)bytesRead);
                        fieldOffset += bytesRead;
                    }
                    return stream.ToArray();
                }
            }

            public class Cookie
            {
                public string Name { get; set; }
                public string Value { get; set; }
            }

            

            class AesGcm256
            {
                public static byte[] GetKey()
                {
                    string sR = string.Empty;
                    var appdata = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
                    string path = @"C:\Users\" + Environment.UserName + @"\AppData\Local\Google\Chrome\User Data\Local State";

                    string v = File.ReadAllText(path);

                    dynamic json = JsonConvert.DeserializeObject(v);
                    string key = json.os_crypt.encrypted_key;

                    byte[] src = Convert.FromBase64String(key);
                    byte[] encryptedKey = src.Skip(5).ToArray();

                    byte[] decryptedKey = ProtectedData.Unprotect(encryptedKey, null, DataProtectionScope.CurrentUser);

                    return decryptedKey;
                }

                public static string decrypt(byte[] encryptedBytes, byte[] key, byte[] iv)
                {
                    string sR = String.Empty;
                    try
                    {
                        GcmBlockCipher cipher = new GcmBlockCipher(new AesEngine());
                        AeadParameters parameters = new AeadParameters(new KeyParameter(key), 128, iv, null);

                        cipher.Init(false, parameters);
                        byte[] plainBytes = new byte[cipher.GetOutputSize(encryptedBytes.Length)];
                        Int32 retLen = cipher.ProcessBytes(encryptedBytes, 0, encryptedBytes.Length, plainBytes, 0);
                        cipher.DoFinal(plainBytes, retLen);

                        sR = Encoding.UTF8.GetString(plainBytes).TrimEnd("\r\n[=10=]".ToCharArray());
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex.Message);
                        Console.WriteLine(ex.StackTrace);
                    }

                    return sR;
                }

                public static void prepare(byte[] encryptedData, out byte[] nonce, out byte[] ciphertextTag)
                {
                    nonce = new byte[12];
                    ciphertextTag = new byte[encryptedData.Length - 3 - nonce.Length];

                    System.Array.Copy(encryptedData, 3, nonce, 0, nonce.Length);
                    System.Array.Copy(encryptedData, 3 + nonce.Length, ciphertextTag, 0, ciphertextTag.Length);
                }
            }
        }