Chromium Browser Data Migration on Windows

Modern Chromium utilizes the Windows Data Protection API (DPAPI), specifically CryptProtectData(). Data migration cannot be done by simply copying the data directory to another computer, because the data would be encrypted with a key only available on the source computer. Fortunately, it turns out to be fairly simple to migrate Chromium user data, thanks to the design that Chromium envelops the encryption mechanism by one layer. The function CryptProtectData() does not encrypt the data directly, but rather a standalone AES key in the Local State file, and this key is in turn used to encrypt confidential data such as cookies and website credentials. Therefore, one easy way to migrate Chromium is to decrypt this Local State key and reencrypt it within the new environment. The process is simple enough to perform manually.

On the source computer

TL; DR; Copy; Paste

First, import ProtectedData to PowerShell as described in the immediate next section. Next, in your Chromium User Data directory (where there is a Local State file):

$json = (Get-Content '.\Local State' -Encoding UTF8 | ConvertFrom-Json); $encrypted_key = $json.os_crypt.encrypted_key; $encrypted_key_data = [Convert]::FromBase64String($encrypted_key)[5..9999]; [System.Security.Cryptography.ProtectedData]::Unprotect($encrypted_key_data, $null, [System.Security.Cryptography.DataProtectionScope]::CurrentUser) | Out-File '.\Local State Unprotected Key'

The individual steps for the emigration are below. After you are done with emigration, go to the next section to perform immigration.

Import ProtectedData to PowerShell

System.Security.Cryptography.ProtectedData is a Microsoft .NET Core library that handles DPAPI calls. You can download it from NuGet. The following procedure has been tested with version 4.6.1 of the library.

.nupkg packages are zip files. Change the extension and extract a System.Security.Cryptography.ProtectedData.dll file.

Then, open a Windows PowerShell window and use the following command to import the library to the current session. You may need to change your PowerShell execution policy and unblock the downloaded file for this step.

Add-Type -Path <Path to library>

Get the encrypted_key value from Chromium Local State file

Navigate to your Chromium user data directory. For example, Chrome is at %USERPROFILE%\AppData\Local\Google\Chrome\User Data\. Open Local State with a text editor. This file is a giant JSON. Search for the encrypted_key key, and copy down its value (from after the colon and double quote to before the next double quote.)

Transform the encrypted_key value

Your encrypted_key value is in base64 and has an extra header inside. Turn it into a raw byte array and remove the header with

$encrypted_key_data = [Convert]::FromBase64String($encrypted_key)[5..9999]

Unprotect the data

Now the data is ready to be processed with DPAPI. Do this:

$unprotected_key = [System.Security.Cryptography.ProtectedData]::Unprotect($encrypted_key_data, $null, [System.Security.Cryptography.DataProtectionScope]::CurrentUser)

It should be 128 bits (32 bytes) as of Chromium 107.

Somehow note down the value of $unprotected_key.

On the target computer

TL; DR; Copy; Paste

You still need to import ProtectedData. Then, in your Chromium User Data directory (where there are Local State and Local State Unprotected Key files created in the previous step):

$unprotected_key = [byte[]] (Get-Content '.\Local State Unprotected Key'); $encrypted_key_data = [System.Security.Cryptography.ProtectedData]::Protect($unprotected_key, $null, [System.Security.Cryptography.DataProtectionScope]::CurrentUser); $encrypted_key_data = [byte]68,80,65,80,73 + $encrypted_key_data; $encrypted_key = [Convert]::ToBase64String($encrypted_key_data); $json = (Get-Content '.\Local State' -Encoding UTF8 | ConvertFrom-Json); $json.os_crypt.encrypted_key = $encrypted_key; ConvertTo-Json -InputObject $json -Depth 8 -Compress | Out-File 'Local State' -Encoding utf8

You might want to delete the migration file Local State Unprotected Key.

The individual steps are below.

Import ProtectedData to PowerShell

Yeah, you have to do it again.

Protect the data

I believe you have typed your $unprotected_key carefully into PowerShell. Make sure it is a byte array. Then, do this:

$encrypted_key_data = [System.Security.Cryptography.ProtectedData]::Protect($unprotected_key, $null, [System.Security.Cryptography.DataProtectionScope]::CurrentUser)

Transform to an encrypted_key value

The following command adds that header back:

$encrypted_key_data = [byte]68,80,65,80,73 + $encrypted_key_data

And this one converts it to base64:

$encrypted_key = [Convert]::ToBase64String($encrypted_key_data)

Edit Local State with new encrypted_key value

Now you can close Chromium, copy your data, and change the encrypted_key value to what you got in the previous step.

Chromium migration is complete.

Wait, does this mean my Chromium (Electron) data is available to all programs running as the current user?

Yes.


Posted

in

by

Tags: