如何在C#(.NET Core)中读取Brave Browser cookie数据库加密值? [英] How to read Brave Browser cookie database encrypted values in C# (.NET Core)?

查看:92
本文介绍了如何在C#(.NET Core)中读取Brave Browser cookie数据库加密值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用C#控制台应用程序读取cookie的加密值.

I am attempting to read the encrypted values of cookies using a C# console app.

我的cookie阅读器课程

My cookie reader 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);
            }
        }
    }
}

我的EF DbContext

My 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();
        }
    }
}

我尝试的解决方案是受 Chrome中的加密cookie 启发的,但并非如此尽管Brave Browser是基于Chromium的,但看起来仍然可以正常工作.相反,Windows Data Protection API会引发异常.

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. Instead the Windows Data Protection API throws an exception.

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()

其他已知问题:如果Brave打开,则EF Core会吓到" SQLite数据库已锁定,并且不会读取任何内容.

Other known issues: If Brave is open EF Core "freaks out" that the SQLite database is locked and won't read anything.

推荐答案

在Chromium版本80及更高版本中,Google修改了cookie加密的方式,以为用户提供额外的安全性.您不能再将cookie直接传递给Windows DPAPI进行解密.Chrome的本地状态"存储的是一个加密密钥,该密钥已使用Windows DPAI解密,您必须使用该密钥来解密Cookie.我要归功于它的到期日,因为我自己并没有从 https://stackoverflow的答案中找到信息,也没有使用这些信息.com/a/60611673/6481581 来解决我的问题.

In Chromium version 80 and up, Google modified the way that cookies are encrypted to provide additional security to users. You cannot pass cookies to the Windows DPAPI directly for decryption anymore. 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. 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.

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);
            }
        }
    }
}

这篇关于如何在C#(.NET Core)中读取Brave Browser cookie数据库加密值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆