Skip to content

Make Apple Keychain format more robust - #5978

Open
kholia wants to merge 2 commits into
bleeding-jumbofrom
better-apple-keychain-support
Open

kholia wants to merge 2 commits into
bleeding-jumbofrom
better-apple-keychain-support

Conversation

@kholia

@kholia kholia commented Apr 21, 2026

Copy link
Copy Markdown
Member

Closes #3408

This only took 14 years (after the initial format release in 2012)...

CC @magnumripper @solardiz

@kholia kholia self-assigned this Apr 21, 2026
@solardiz

Copy link
Copy Markdown
Member

Thank you very much @kholia. I don't have time to look at this for real now - hopefully soon. Meanwhile, you could want to see why two CI jobs are failing here.

@kholia
kholia force-pushed the better-apple-keychain-support branch from 4476c2c to f0eb593 Compare April 25, 2026 02:47
@kholia

kholia commented Apr 25, 2026

Copy link
Copy Markdown
Member Author

The CI infrastructure is running into problems:

Configure finished.  Now "make -s clean && make -sj2" to compile.
The authenticity of host 'github.com (140.82.112.3)' can't be established.
ED25519 key fingerprint is SHA256:+DiY3wvvV6TuJJhbpZisF/zLDA0zPMSvHdkr4UvCOqU.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? make[1]: *** Deleting file 'misc.o'
make[1]: *** Deleting file 'memory.o'
make[1]: *** Deleting file 'mask.o'
make[1]: *** Deleting file 'loader.o'
make: *** [Makefile:202: default] Hangup

Too long with no output (exceeded 10m0s): context deadline exceeded

@magnumripper

Copy link
Copy Markdown
Member

Why the name change for keypass2john.py? In general that is messy and can lead to problems in some setups. Did syntax/options change?

@kholia

kholia commented Apr 27, 2026

Copy link
Copy Markdown
Member Author

Good point. I believe we can keep the same name as the script is mostly backwards compatible.

@kholia
kholia force-pushed the better-apple-keychain-support branch from f0eb593 to 59a7569 Compare April 28, 2026 04:44
@kholia

kholia commented Jul 14, 2026

Copy link
Copy Markdown
Member Author

This is ready for another rounds of reviews - thanks!

I believe that the CI failures were not related to this PR.

When no dump/export action flag is given, the old script always emitted
the JtR password hash and exited cleanly.  The rewrite introduced an
argparse default that caused check_args_no_action() to print "No action
specified." and exit(1) instead, breaking the typical JtR workflow:

    keychain2john.py login.keychain | john --format=keychain ...

Fix check_args_no_action() to set dump_keychain_password_hash=True
(instead of aborting) when the user passes no explicit action flag.
Explicit flags like --dump-all, --dump-generic-passwords etc. continue
to work as before.

Also correct the misleading default=True on --dump-all's add_argument()
call, which was already overridden to False by set_defaults() and only
caused confusion.

Addresses magnumripper's review concern about syntax/options changes.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
@kholia
kholia force-pushed the better-apple-keychain-support branch from 811d789 to c8640cf Compare September 30, 2026 05:52

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

The extractor has broken default, output, and unlock paths, and the OpenCL backend does not perform v2 verification.

Review effort: Balanced
Findings: 1 High severity · 5 Medium severity

Open (6)
What changed in this PR

This PR aims to reduce false positives when cracking Apple Keychain passwords by checking an additional encrypted key blob.

Changes:

  • Add a v2 hash format and symmetric-key verification while retaining the legacy format.
  • Replace the keychain extractor with a broader Python parser and command-line options.
File Description
src/​keychain_fmt_plug.c Verifies v2 candidates against the encrypted key blob.
src/​keychain_common.h Defines the v2 tag and additional ciphertext fields.
src/​keychain_common_plug.c Parses and validates v2 hashes.
run/​keychain2john.py Extracts v2 hashes and adds dump and export options.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread run/keychain2john.py
if len(data) % Chainbreaker.BLOCKSIZE != 0:
return b''

cipher = DES3.new(key, DES3.MODE_CBC, IV=iv)
Comment thread run/keychain2john.py
arguments = argparse.ArgumentParser(description='Dump items stored in an OSX Keychain')

# General Arguments
arguments.add_argument('keychain', help='Location of the keychain file to parse')
Comment thread run/keychain2john.py Outdated
Comment on lines +199 to +201
or args.export_x509_certificates):
logger.critical("No action specified.")
exit(1)
Comment thread run/keychain2john.py
Comment on lines +293 to +298
for record_collection in output:
if 'records' in record_collection:
for record in record_collection['records']:
if record_collection.get('write_to_console', False):
for line in str(record).split('\n'):
pass
Comment thread run/keychain2john.py
ssgp, dbkey = self._extract_ssgp_and_dbkey(record_meta, buffer)
# print(ssgp, "XXX", ssgp.EncryptedPassword, ssgp.IV)
found_ssgps = True
print("[DEBUG]", ssgp, len(ssgp.EncryptedPassword), ssgp.IV, file=sys.stderr)
Comment on lines +44 to +47
tag_len = keychain_tag_len(ciphertext);
if (!tag_len)
return 0;
is_v2 = (tag_len == FORMAT_TAG_V2_LEN);
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.

Make Apple Keychain format more robust

4 participants