Skip to content

Support AES/mixed keys. Add tests & new configs.#72

Open
gamesguru wants to merge 6 commits intolouisabraham:masterfrom
gamesguru:master
Open

Support AES/mixed keys. Add tests & new configs.#72
gamesguru wants to merge 6 commits intolouisabraham:masterfrom
gamesguru:master

Conversation

@gamesguru
Copy link
Contributor

Large PR with many enhancements.

• v0.6.0: Import & export for AES and mixed keys.
• Fix errors w/ Windows & w/ GitHub runner. Configs.

    - GH Actions on Windows/macOS
    - Add argcomplete (optional end-user add-on).
    - Add fixes & tests for master password.

    - tests: Generate mixed key test data. Use some mocks.
    - tests: Avoid modifying .json files, use temp storage.
    - tests: Add test for AES export/import (AES, 3DES, and mixed keys).

    - Tidy up, lint, and format.
    - Fix edge cases with argcomplete.
    - Windows: Fix profile discovery and CSV printing.
    - Better loop logic (for imports w/ empty row or missing header).

    - Config files.
    - Add stuff back that was removed accidentally in a frenzy.
@github-actions
Copy link

github-actions bot commented Dec 26, 2025

Unit Test Results

10 tests  ±0   10 ✅ ±0   0s ⏱️ ±0s
 1 suites ±0    0 💤 ±0 
 1 files   ±0    0 ❌ ±0 

Results for commit 53b3875. ± Comparison against base commit b6efa11.

♻️ This comment has been updated with latest results.

Copy link
Contributor Author

@gamesguru gamesguru left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Initial self-review with suggested follow-ups and shipstops in comments.

from Crypto.Cipher import AES, DES3

# noqa: W503
# line break before binary operator
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is redundant and i meant to remove

if: always()
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: python -m coveralls --service=github
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This may break coverage reporting, and should possibly be reverted. It's just what I had a working reference copy of at the time that I could use, sorry.

logging.debug(f"row: {row}")

# Peek at the first line to detect if it is a header or normal row
if first_row is None:
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is convoluted logic, which is perhaps best left to the user as a --header flag, without which input is assumed to be headerless (i.e., first row is already an (url, username, password) tuple/list?

Or default the other way if you prefer.

But this feels excessive, when I look at it with fresh eyes. Not tested on export to file, either, unsure if there is/was a test for that.

dirs = {
"darwin": "~/Library/Application Support/Firefox/Profiles",
"linux": "~/.mozilla/firefox",
"win32": os.path.expandvars(r"%LOCALAPPDATA%\Mozilla\Firefox\Profiles"),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This did not work for me on Windows 10 nor Hiren's USB. It's possible though we may need logic for supporting/checking both local and roaming. I am a Linux user and defer to your knowledge on this matter.

argcomplete.autocomplete(parser)

except (ImportError, ModuleNotFoundError):
sys.stderr.write(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logger uninitialized here (in effort to avoid messy circular logic edge cases)...... so, this is only available method to print to stderr at this point.

try:
main()
except SystemExit:
pass
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can potentially be wrapped in an assertRaises() call, while reflecting overall on the ratio of unit:e2e integration tests.

HEADER = 'url,username,password'
IMPORT_CREDENTIAL = 'https://www.example.com,foo,bar'
EXPECTED_EXPORT_OUTPUT = [HEADER, 'http://www.stealmylogin.com,test,test']
EXPECTED_IMPORT_OUTPUT = EXPECTED_EXPORT_OUTPUT + [IMPORT_CREDENTIAL]
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ugly, but it works. Open to alternate suggestions!


if mode == 'import':
ffpass_input = HEADER + IMPORT_CREDENTIAL
ffpass_input = "\n".join([HEADER, IMPORT_CREDENTIAL])
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tested without issue in both Windows 10 cmd.exe as well as Git Bash shell.


def test_legacy_firefox_export():
r = run_ffpass('export', 'tests/firefox-70')
def stdout_splitter(input_text):
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May be unnecessary and can be reverted, as per earlier comments regarding fixes at the csv module level in the source code.

profile_path = clean_profile('firefox-70')

# modifies the temp file, not the original
r = run_ffpass_cmd('import', profile_path)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an important fix imo. It's best not to modify files in the source tree that are used for tests!

Someone could accidentally commit changes and break it.

Better to use a temp copy.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant