简体   繁体   English

如何读取 C# (.NET Core) 中的 Brave Browser cookie 数据库加密值?

[英]How to read Brave Browser cookie database encrypted values in C# (.NET Core)?

I am attempting to read the encrypted values of cookies using a C# console app.我正在尝试使用 C# 控制台应用程序读取 cookies 的加密值。

My cookie reader class我的 cookie 阅读器 class

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using Microsoft.EntityFrameworkCore;

namespace ConsoleApp1.Models
{
    public class ChromeCookieReader
    {
        public IEnumerable<Tuple<string, string>> ReadCookies(string hostName)
        {
            if (hostName == null) throw new ArgumentNullException("hostName");

            using var context = new ChromeCookieDbContext();

            var cookies = context
                .Cookies
                .Where(c => c.HostKey.Equals("localhost"))
                .AsNoTracking();

            foreach (var cookie in cookies)
            {
                var decodedData = ProtectedData
                    .Unprotect(cookie.EncryptedValue,
                        null, 
                        DataProtectionScope.CurrentUser);

                var decodedValue = Encoding.UTF8.GetString(decodedData);

                yield return Tuple.Create(cookie.Name, decodedValue);
            }
        }
    }
}

My EF DbContext我的 EF DbContext

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Text;
using Microsoft.EntityFrameworkCore;

namespace ConsoleApp1.Models
{
    public class Cookie
    {
        [Column("host_key")]
        public string HostKey { get; set; }

        [Column("name")] 
        public string Name { get; set; }

        [Column("encrypted_value")]
        public byte[] EncryptedValue { get; set; }
    }

    public class ChromeCookieDbContext : DbContext
    {
        public DbSet<Cookie> Cookies { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            // var dbPath = Environment.GetFolderPath(
            //    Environment.SpecialFolder.LocalApplicationData) 
            //             + @"\Google\Chrome\User Data\Default\Cookies";

            var dbPath = Environment.GetFolderPath(
                             Environment.SpecialFolder.LocalApplicationData)
                         + @"\BraveSoftware\Brave-Browser\User Data\Default\Cookies";

            if (!System.IO.File.Exists(dbPath)) throw new System.IO.FileNotFoundException("Cant find cookie store", dbPath); // race condition, but i'll risk it

            var connectionString = "Data Source=" + dbPath + ";Mode=ReadOnly;";

            optionsBuilder
                .UseSqlite(connectionString);
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Cookie>().ToTable("cookies").HasNoKey();
        }
    }
}

My attempted solution was inspired by Encrypted cookies in Chrome however it doesn't look like it'll work the same despite Brave Browser being based on Chromium.我尝试的解决方案受到Chrome 中的 Encrypted cookies 的启发,但是尽管 Brave Browser 基于 Chromium,但它看起来并不相同。 Instead the Windows Data Protection API throws an exception.相反,Windows 数据保护 API 会引发异常。

Internal.Cryptography.CryptoThrowHelper.WindowsCryptographicException
  HResult=0x0000000D
  Message=The data is invalid.
  Source=System.Security.Cryptography.ProtectedData
  StackTrace:
   at System.Security.Cryptography.ProtectedData.ProtectOrUnprotect(Byte[] inputData, Byte[] optionalEntropy, DataProtectionScope scope, Boolean protect)
   at System.Security.Cryptography.ProtectedData.Unprotect(Byte[] encryptedData, Byte[] optionalEntropy, DataProtectionScope scope)
   at ConsoleApp1.Models.ChromeCookieReader.<ReadCookies>d__0.MoveNext()

Other known issues: If Brave is open EF Core "freaks out" that the SQLite database is locked and won't read anything.其他已知问题:如果 Brave 已打开,EF Core 会“吓坏”SQLite 数据库被锁定并且不会读取任何内容。

In Chromium version 80 and up, Google modified the way that cookies are encrypted to provide additional security to users.在 Chromium 80 及更高版本中,Google 修改了 cookies 的加密方式,为用户提供额外的安全性。 You cannot pass cookies to the Windows DPAPI directly for decryption anymore.您不能再将 cookies 直接传递给 Windows DPAPI 进行解密。 Rather Chrome's Local State stores an encryption key that is decrypted with the Windows DPAI, you have to use that key to decrypt the cookies.而是 Chrome 的本地 State 存储使用 Windows DPAI 解密的加密密钥,您必须使用该密钥来解密 cookies。 I am giving credit where it's due as I did not find this out on my own and used information from the answer at https://stackoverflow.com/a/60611673/6481581 to fix my issue.我在应得的地方给予信任,因为我自己没有发现这一点,并使用https://stackoverflow.com/a/60611673/6481581的答案中的信息来解决我的问题。

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using System.Security.Cryptography;
using Newtonsoft.Json.Linq;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Modes;
using Org.BouncyCastle.Crypto.Parameters;

namespace BraveBrowserCookieReaderDemo
{
    public class BraveCookieReader
    {
        public IEnumerable<Tuple<string, string>> ReadCookies(string hostName)
        {
            if (hostName == null) throw new ArgumentNullException("hostName");

            using var context = new BraveCookieDbContext();

            var cookies = context
                .Cookies
                .Where(c => c.HostKey.Equals(hostName))
                .AsNoTracking();

            // Big thanks to https://stackoverflow.com/a/60611673/6481581 for answering how Chrome 80 and up changed the way cookies are encrypted.

            string encKey = File.ReadAllText(System.Environment.GetEnvironmentVariable("LOCALAPPDATA") + @"\BraveSoftware\Brave-Browser\User Data\Local State");
            encKey = JObject.Parse(encKey)["os_crypt"]["encrypted_key"].ToString();
            var decodedKey = System.Security.Cryptography.ProtectedData.Unprotect(Convert.FromBase64String(encKey).Skip(5).ToArray(), null, System.Security.Cryptography.DataProtectionScope.LocalMachine);

            foreach (var cookie in cookies)
            {

                var data = cookie.EncryptedValue;

                var decodedValue = _decryptWithKey(data, decodedKey, 3);


                yield return Tuple.Create(cookie.Name, decodedValue);
            }
        }


        private string _decryptWithKey(byte[] message, byte[] key, int nonSecretPayloadLength)
        {
            const int KEY_BIT_SIZE = 256;
            const int MAC_BIT_SIZE = 128;
            const int NONCE_BIT_SIZE = 96;

            if (key == null || key.Length != KEY_BIT_SIZE / 8)
                throw new ArgumentException(String.Format("Key needs to be {0} bit!", KEY_BIT_SIZE), "key");
            if (message == null || message.Length == 0)
                throw new ArgumentException("Message required!", "message");

            using (var cipherStream = new MemoryStream(message))
            using (var cipherReader = new BinaryReader(cipherStream))
            {
                var nonSecretPayload = cipherReader.ReadBytes(nonSecretPayloadLength);
                var nonce = cipherReader.ReadBytes(NONCE_BIT_SIZE / 8);
                var cipher = new GcmBlockCipher(new AesEngine());
                var parameters = new AeadParameters(new KeyParameter(key), MAC_BIT_SIZE, nonce);
                cipher.Init(false, parameters);
                var cipherText = cipherReader.ReadBytes(message.Length);
                var plainText = new byte[cipher.GetOutputSize(cipherText.Length)];
                try
                {
                    var len = cipher.ProcessBytes(cipherText, 0, cipherText.Length, plainText, 0);
                    cipher.DoFinal(plainText, len);
                }
                catch (InvalidCipherTextException)
                {
                    return null;
                }
                return Encoding.Default.GetString(plainText);
            }
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM