Decrypt locally-stored Chrome/Chromium passwords on Linux (GNOME Keyring) and export them to importable CSVs — one per profile.
Project description
chrome-restore-local-passwords-linux
Recover the passwords Chrome/Chromium saved on disk on Linux, and export them to Chrome-importable CSV files — one per profile.
The classic use case: your old laptop died, you mounted its disk, and you want your saved
logins back. Point this tool at the old .config directory, give it the old login password,
and it walks every profile of Google Chrome, Google Chrome Beta, and Chromium,
decrypts each Login Data database, and writes a CSV you can import via
chrome://password-manager/settings → Import.
⚠️ This decrypts your own passwords from a disk you control. Don't use it on data that isn't yours.
Why a dedicated tool?
On Linux, Chrome encrypts saved passwords with OSCrypt. Two schemes show up in Login Data:
v10— key derived from the hardcoded passwordpeanuts(used when the browser ran with--password-store=basicor had no usable keyring).v11— key derived from a random "Chrome Safe Storage" / "Chromium Safe Storage" secret stored in your GNOME login keyring (~/.local/share/keyrings/login.keyring), which is itself unlocked by your login password.
This tool handles both: it decodes the legacy GNOME keyring file offline (given your login password), extracts the Safe Storage secrets, derives the AES keys, and decrypts every entry.
Requirements
- Linux with a GNOME Keyring (libsecret) — i.e. the
v11secret lives in alogin.keyringfile. (Pure-v10data decrypts with no password and no keyring.) - Google Chrome, Google Chrome Beta, and/or Chromium profiles.
- Nothing to install if you use
uv(below); otherwise Python ≥ 3.9 and thecryptographypackage.
Usage with uvx (no install)
# See the options
uvx chrome-restore-local-passwords-linux@latest --help
# List the profiles found on a mounted old disk (no password needed)
uvx chrome-restore-local-passwords-linux@latest \
--config-dir /run/media/you/OLDDISK/home/you/.config --list
# Decrypt everything and write CSVs (prompts for the OLD login password)
uvx chrome-restore-local-passwords-linux@latest \
--config-dir /run/media/you/OLDDISK/home/you/.config \
--out ~/chrome-passwords-export
--config-dir defaults to ~/.config, so on your current machine you can just run it with no
arguments to export your own profiles. When restoring from another disk, point it at that disk's
.config; the matching login.keyring is auto-detected next to it (override with --keyring).
Options
| Option | Description |
|---|---|
--config-dir DIR |
A .config directory to read. Default: ~/.config. |
--out DIR |
Output directory for the CSV files. Default: ./chrome-passwords-export. |
--browser NAME |
Restrict to google-chrome, google-chrome-beta, google-chrome-unstable, or chromium. Repeatable. Default: all found. |
--keyring PATH |
Explicit login.keyring path. Default: auto-detected next to --config-dir. |
--password-stdin |
Read the login password from stdin instead of prompting. |
--list |
Only list discovered profiles; don't decrypt. |
The login password can also be supplied via the CHROME_KEYRING_PASSWORD environment variable
(handy for scripting; otherwise it's read interactively with getpass and never printed).
Importing the CSVs into Chrome
- Open a Chrome window in the profile you want to import into.
- Go to
chrome://password-manager/settings. - Click Import passwords and pick the CSV for that profile.
Imports land in whichever profile's window you launched the importer from, so match them up.
Clean up afterwards
The CSVs contain plaintext passwords (written 0600). Delete them securely when done:
shred -u ~/chrome-passwords-export/*.csv
How it works
- Parse the legacy GNOME keyring (
GnomeKeyring\n\r\0\nformat): read salt + iteration count, derive the AES key from your login password (iterated SHA-256), AES-128-CBC decrypt, and verify with the embedded MD5. - Extract the
Chrome Safe Storage/Chromium Safe Storagesecrets from the decrypted keyring. - For each secret, derive the OSCrypt key:
PBKDF2-HMAC-SHA1(secret, "saltysalt", 1, 16). - For each profile's
Login Data, decrypt everyv10/v11password_value(AES-128-CBC, IV = 16 spaces, strip PKCS#7), auto-selecting the secret that validates. - Write
name,url,username,passwordCSVs in Chrome's import format.
Everything runs offline. Your login password is read with getpass and is never printed,
logged, or persisted.
Limitations
- Linux + GNOME Keyring only (no KWallet, no macOS Keychain, no Windows DPAPI).
- Handles OSCrypt
v10/v11. The Windows-only app-boundv20scheme does not apply on Linux. - Reads the legacy single-file keyring format (
login.keyring). The newer keyring daemon's on-disk format is not parsed.
Development
uv run chrome_restore_passwords.py --help # run from source
uv build # build sdist + wheel
Releases are published to PyPI automatically by a GitHub Action when a GitHub Release is published (PyPI Trusted Publishing / OIDC — no API tokens).
License
MIT © Harald Schilly
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file chrome_restore_local_passwords_linux-0.1.0.tar.gz.
File metadata
- Download URL: chrome_restore_local_passwords_linux-0.1.0.tar.gz
- Upload date:
- Size: 9.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2571f1c2df0cb500919595e7c469bbad2efeb095b4a0a97e1160384db45667c2
|
|
| MD5 |
b0bfba2c1155d1d9b36e195eb345be3a
|
|
| BLAKE2b-256 |
6514aa9a6b42fa8cde661cdf90c47726e265799e61510e9bf07e74e8a6e3ed8d
|
Provenance
The following attestation bundles were made for chrome_restore_local_passwords_linux-0.1.0.tar.gz:
Publisher:
publish.yml on haraldschilly/chrome-restore-local-passwords-linux
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
chrome_restore_local_passwords_linux-0.1.0.tar.gz -
Subject digest:
2571f1c2df0cb500919595e7c469bbad2efeb095b4a0a97e1160384db45667c2 - Sigstore transparency entry: 1702215218
- Sigstore integration time:
-
Permalink:
haraldschilly/chrome-restore-local-passwords-linux@641aee57f69c3d8e778f6367042b6ae655fc99ff -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/haraldschilly
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@641aee57f69c3d8e778f6367042b6ae655fc99ff -
Trigger Event:
release
-
Statement type:
File details
Details for the file chrome_restore_local_passwords_linux-0.1.0-py3-none-any.whl.
File metadata
- Download URL: chrome_restore_local_passwords_linux-0.1.0-py3-none-any.whl
- Upload date:
- Size: 11.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5c172eefd56219a923bc163f0d7d34acb9f7431d1db9b5489abb568e090b4e2d
|
|
| MD5 |
e10c11e762a2ea6a4976d5158cf55f0f
|
|
| BLAKE2b-256 |
9fdd5b99417b8141d41e7c821beca9f28df8fb7193ee9a8856f3261913654978
|
Provenance
The following attestation bundles were made for chrome_restore_local_passwords_linux-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on haraldschilly/chrome-restore-local-passwords-linux
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
chrome_restore_local_passwords_linux-0.1.0-py3-none-any.whl -
Subject digest:
5c172eefd56219a923bc163f0d7d34acb9f7431d1db9b5489abb568e090b4e2d - Sigstore transparency entry: 1702215324
- Sigstore integration time:
-
Permalink:
haraldschilly/chrome-restore-local-passwords-linux@641aee57f69c3d8e778f6367042b6ae655fc99ff -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/haraldschilly
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@641aee57f69c3d8e778f6367042b6ae655fc99ff -
Trigger Event:
release
-
Statement type: