Skip to content
This repository has been archived by the owner on Jan 30, 2018. It is now read-only.

Password format option #13

Open
MagerValp opened this issue Aug 2, 2012 · 5 comments
Open

Password format option #13

MagerValp opened this issue Aug 2, 2012 · 5 comments
Milestone

Comments

@MagerValp
Copy link
Owner

Add an option to store the password in salted SHA1 (10.5+) or PBKDF2 (10.7+) format. Salted SHA1 might not be secure enough for some environments.

@keeleysam
Copy link

Would it be possible to revisit this now?

@MagerValp
Copy link
Owner Author

Yep. Plan is to release 1.2.4 as a last bugfix release, then for 1.3 I'm ditching 10.5 and 10.6 support. Busy with AutoDMG at the moment though.

@ab
Copy link

ab commented Jan 13, 2017

Ping! I know the whole package is up for adoption, but any pointers on where to start on a PR?

https://magervalp.github.io/2016/12/07/createuserpkg-up-for-adoption.html

@MagerValp
Copy link
Owner Author

First there's some detective work that needs to be done to determine what the current format is for /private/var/db/dslocal/nodes/Default/users plists, particularly the ShadowHashData and how it varies from 10.7-10.12. Then the following needs to be replaced with PBKDF2:

- (void)calculateShadowHash:(NSString *)pwd
{
CC_SHA1_CTX ctx;
unsigned char salted_sha1_hash[24];
union _salt {
unsigned char bytes[4];
u_int32_t value;
} *salt = (union _salt *)&salted_sha1_hash[0];
unsigned char *hash = &salted_sha1_hash[4];
// Calculate salted sha1 hash.
CC_SHA1_Init(&ctx);
salt->value = arc4random();
CC_SHA1_Update(&ctx, salt->bytes, sizeof(salt->bytes));
CC_SHA1_Update(&ctx, [pwd UTF8String], (CC_LONG)[pwd lengthOfBytesUsingEncoding:NSUTF8StringEncoding]);
CC_SHA1_Final(hash, &ctx);
// Generate new shadow hash.
[self.shadowHash setString:@""];
[self.shadowHash appendFormat:@"%0168X", 0];
assert([self.shadowHash length] == SALTED_SHA1_OFFSET);
for (int i = 0; i < sizeof(salted_sha1_hash); i++) {
[self.shadowHash appendFormat:@"%02X", salted_sha1_hash[i]];
}
while ([self.shadowHash length] < SHADOW_HASH_LEN) {
[self.shadowHash appendFormat:@"%064X", 0];
}
assert([self.shadowHash length] == SHADOW_HASH_LEN);
}

create_package.py also has to be adjusted accordingly.

@ab
Copy link

ab commented Jan 17, 2017

I don't know Obj-C at all, so I might not be able to provide a PR.

Some notes on what I've learned, in case it's useful to anyone:

The new ShadowHashData format seems pretty straightforward: it's a binary plist that contains the SALTED-SHA512-PBKDF2 hash. Judging from my own hash it uses ~40K iterations and generates a 128-byte output hash.

The macadmin ruby library has some examples of generating this plist.

https://github.com/dayglojesus/macadmin/blob/b35d0bec2b5299b6d2813726ddff0e3ae5d28c4d/lib/macadmin/shadowhash.rb#L199
https://github.com/dayglojesus/macadmin/blob/b35d0bec2b5299b6d2813726ddff0e3ae5d28c4d/ext/macadmin/password/crypto.c#L42

Here's an example ShadowHashData file with the Base64 blobs replaced by all A characters. The entropy key represents the PBKDF2 output. I'm not sure what the SRP hash is for, but it looks to be generated in much the same way, only with a longer PBKDF2 output.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>SALTED-SHA512-PBKDF2</key>
    <dict>
        <key>entropy</key>
        <data>
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
        </data>
        <key>iterations</key>
        <integer>39840</integer>
        <key>salt</key>
        <data>
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
        </data>
    </dict>
    <key>SRP-RFC5054-4096-SHA512-PBKDF2</key>
    <dict>
        <key>iterations</key>
        <integer>34602</integer>
        <key>salt</key>
        <data>
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
        </data>
        <key>verifier</key>
        <data>
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAA=
        </data>
    </dict>
</dict>
</plist>

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants