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.