Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Mon, 20 Mar 2023 01:53:26 +0000
From: Gonn Zerg <gonnzerg@...look.com>
To: "john-users@...ts.openwall.com" <john-users@...ts.openwall.com>
Subject: RE: Cracking 1Password8 iOS password. How to use JTR if
 1password2john isn't suited for my case?

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.