Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Date: Thu, 30 Mar 2023 01:21:56 +0200
From: Solar Designer <solar@...nwall.com>
To: john-users@...ts.openwall.com
Subject: Re: Cracking 1Password8 iOS password. How to use JTR if 1password2john isn't suited for my case?

Hi Gonn Zerg,

I'm sorry no one replied to you sooner.

I don't normally top-post, but this time my reply is to your messages as
a whole rather than to the individual points.

Unfortunately, Dhiru Kholia who got 1password2john.py and Agile and
Cloud Keychain formats into JtR is currently inactive with the
project, and anyway I doubt he would readily know what's changed since
or on desktop vs. iOS.

Reading Dhiru's source code comments and git history, his work back in
2012-2013 was building upon https://github.com/Roguelazer/onepasswordpy
and I see this repo was last updated in 2015.  The one you refer to:

> I relied heavily on this repository https://github.com/dschuetz/1password.

is newer, with one and only commit in 2018.

The algorithm you describe doesn't appear to exactly match an existing
JtR format, so I think to add support you or someone else would need
to implement both a new format (or two, for CPU and OpenCL) and a new
extraction script.  Normally, 1password2john.py would output "hashes"
for the Agile or Cloud Keychain formats.  I just took a look at those,
and one uses PBKDF2 with SHA-1, the other with SHA-512.  The algorithm
you describe uses it with SHA-256.  There are other differences as well,
but this is sufficient to conclude that it's different from those two.

Did I read you right that you got a cracker for your target input file
working in Python, as tested on other files like it with known password?
If so, you'd need to start with that and implement the extraction script
and the format(s) for JtR.  You'd reuse our existing optimized
implementations of PBKDF2-HMAC-SHA256 (and more, but that one matters
for performance), in OpenCL on GPU and with SIMD on CPU.

You can indeed use some of our existing extraction scripts and formats
as templates, but it looks like you'll need to make substantial changes
and write some new code.

Also, to preserve the research you already did regardless of whether
you proceed further or not, it makes sense for you to create an issue at
https://github.com/openwall/john/issues and to publish your Python
script under a suitable license.  Oh, and please add your sample input
files and the corresponding known password(s) via a pull request to
https://github.com/openwall/john-samples - these would also be handy for
regression testing and benchmarks even after we have the support in JtR.

Thank you!

Alexander

On Mon, Mar 20, 2023 at 01:53:26AM +0000, Gonn Zerg wrote:
> Okay so I think I have a better understanding of 1password2john. But
> I?m still stuck.
> 
> 
> After going through 1password2john.py I see that the .sqlite parsing
> does the following:
> 
> 
> SELECT master_key_data, salt, iterations FROM profiles
> 
> 
> So since I didn?t have that table in my database from my iOS backup
> I created it and inserted the ?data? as master_key_data, ?p2s?
> as salt and ?p2c? as iterations for each respective field that I do have
> in ?enc_sym_key?. I encoded the strings before inserting them using
> this method from the repository I mentioned on my previous message.
> I was getting errors about ?utf-8? chars the way I was doing it so
> just relied on it again.
> 
> 
> def get_binary(prompt):
>         raw_dat = prompt
>         try:
>                 bin = binascii.a2b_hex(raw_dat)
>         except:
>                 try:
>                         bin = opb64d(raw_dat)
>                 except:
>                         try:
>                                 bin = base64.b64decode(raw_dat)
>                         except:
>                                 print ("Unable to decode the input. Enter in hex or base64.")
>                                 sys.exit(1)
>         return bin
> 
> 
> I did get a different error so I believe I?m moving forward. I get
> output like:
> 
> 
> $cloudkeychain$16$[hex-salt]$650000$173$[hex-data]
> 
> 
> Now I get the following error in ?opdata1_unpack()?. I?m still
> trying to figure out what I can do to fix it.
> 
> 
> binascii.Error: Invalid base64-encoded string: number of data
> characters (49) cannot be 1 more than a multiple of 4
> 
> 
> python
> def opdata1_unpack(data):
>             HEADER_LENGTH = 8
>             TOTAL_HEADER_LENGTH = 32
>             HMAC_LENGTH = 32
>             if data[:HEADER_LENGTH] != b"opdata01":
>                         data = base64.b64decode(data)
> 
> 
> Is this just a matter of the tool being incompatible with the newer
> format or hashing methods used now compared to then?
> 
> 
> Though I see that [1password2john.py](http://1password2john.py) was
> last modified 2 years ago so I think it would be mostly a matter of the
> tool supporting desktop platforms and not the iOS sqlite database,
> rather than old format or hashing method.
> 
> 
> I was also going through the last AES in to better understand what
> the hash needed really is and which ?data? 1password2john
> actually needs. I?m now thinking that the ?data? is not the one I
> found in the ?enc_sym_key? part of the keyset by itself but rather
> a combination of the b?opdata01? header, iv, data?
> 
> 
> I see that the header is not present because the error presents itself
> inside the if statement. So maybe I could concatenate them like this?
> ciphertext = b?opdata01? + iv + data? I was reading that I would
> need to append the Authentication Tag to the end of the ciphertext
> but the data I already have would already contain the Authentication
> Tag, I would think.
> 
> 
> I would really appreciate any input on this, I am a software engineer
> but I?ve never worked in the field and before this ?redemption
> project? I was trying to get into indie game development haha.
> 
> 
> Regarding my redemption, I got into this mess because I set up the
> 1Password account for my mom and we both forgot the master
> password and never wrote it down on the Emergency Kit. She had
> everything on her notes app, without encryption as well, so I put my
> nose where I shouldn?t and messed up her ?password management
> system? without a clue of how to fix it. But I will, eventually.
> 
> 
> Thank you for reading me!
> 
> 
> 
> 
> From: Gonn Zerg<mailto:gonnzerg@...look.com>
> Sent: March 18, 2023 12:53 PM
> To: john-users@...ts.openwall.com<mailto:john-users@...ts.openwall.com>
> Subject: [john-users] Cracking 1Password8 iOS password. How to use JTR if 1password2john isn't suited for my case?
> 
> 
> Hi all,
> 
> 
> I?m trying to format this as best as I can for the mailing list, I
> apologize in advance if it doesn?t meet standards.
> 
> 
> I?m looking for advice on how to achieve this using JTR. I have
> tried passing my .sqlite file to 1password2john but it doesn?t
> appear to be compatible. The account only exists in iOS so I can?t
> obtain a macOS or Windows database.
> 
> 
> So, I?ve written a script in Python that goes through the same
> process 1Password goes through to generate the AUK. I do this
> for each password in a dictionary.
> I would like to know how the following process could be achieved
> using JTR. Or maybe this method is the wrong way to go about this.
> 
> 
> I relied heavily on this repository https://github.com/dschuetz/1password.
> 
> 
> So these things I know or have from a backup of the device:
> - secret Key (version, account id, secret)
> - email
> - algorithm
> - iterations
> - salt
> - encrypted sqlite database (keysets, account, vaults, etc.)
> 
> 
> 1. With this I then get the HKDF salt:
> 
> 
> hkdf_salt = HKDF(ikm=p2s, len=32, salt=email, hash=SHA256, count=1, info=algorithm)
> 
> 
> 2. Then the derived password key using the HKDF salt:
> 
> 
> password_key = PBKDF2(sha256, password, salt=hkdf_salt, iterations=p2c, 32 bytes)
> 
> 
> 3. Then the HKDF secret key:
> 
> 
> hkdf_key = HKDF(ikm=secret, len=32, salt=AcctID, hash=SHA256, count=1, info=version)
> 
> 
> 4. Then XOR the password key and the HKDF secret key:
> 
> 
> auk = bytes(a ^ b for a, b in zip(password_key, hkdf_key))
> 
> 
> 5. Then I check if the resulting auk is valid by trying to decrypt and verify the data in the symmetric key:
> 
> 
> C = AES.new(auk, AES.MODE_GCM, enc_sym_key_iv, mac_len=16)
>     try:
>         PT_enc_sym_key = C.decrypt_and_verify(enc_sym_key_data[:-16], enc_sym_key_data[-16:])
>         if PT_enc_sym_key is not None:
>                 jwk_loaded = json.loads(jwk_json)
>                 decrypted_kid = jwk_loaded['kid']
>                 if(decrypted_kid == keyset_uuid):
>                     # Found password!
>     except ValueError:
>         continue
> 
> 
> I did manage to divide the dictionary into chunks and divide it into 12
> processes which was better than my first copy/paste Apple Shortcut.
> 
> 
> After attempting this with a new 1Password account on another iOS
> device, getting the data needed from the backup and going through a
> wordlist that contained the correct password I managed to confirm that
> this works and it's very likely that it will work on the main device.
> 
> 
> So, how can I do better?
> 
> 
> I tried to optimize the code bit by bit and I understand there's
> plenty more to improve in it. However, I'd like to move to doing
> something like this on an environment that would make this a lot
> faster or more efficient. I know I won't be able to code more
> efficient solutions than the ones already out there by experts, even
> if I wanted to reinvent the wheel.
> 
> 
> I started to feel the lack of optimization in my solution when John
> The Ripper output a wordlist in the almost hundreds of millions of
> lines from a set of rules I thought could contain the right password
> but no luck yet. I know I have to grow the list even more but optimize
> my approach even more. I would appreciate any help pointing me in the
> right direction.
> 
> 
> Thank you for reading me!

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.