Invalid Checksum

I have a problem creating a checksum that matches for OpenSSL and iOS' CommonCrypto implementation. I currently have a .plist file that I want to validate using a checksum. What I have done is the following:

openssl dgst -sha256 file.plist
SHA256(file.plist)= a33184700a1f61f80d4a1d092e83457c9abdf794c20daa276bd3e1e8a4ceb55c


Alternatively used the internal shasum function

shasum -a 256 file.plist
a33184700a1f61f80d4a1d092e83457c9abdf794c20daa276bd3e1e8a4ceb55c  file.plist


So I now have the sha256 hash of the file. I will create base64 data that can be used in Swift

echo -n 'a33184700a1f61f80d4a1d092e83457c9abdf794c20daa276bd3e1e8a4ceb55c' | xxd -r -p | base64
ozGEcAofYfgNSh0JLoNFfJq995TCDaona9Ph6KTOtVw=


So right now, I have the hash and I can use that in iOS. Note that I hashed the exact file that is in Xcode's file inspector.

let calculatedHash = Data(base64Encoded: "ozGEcAofYfgNSh0JLoNFfJq995TCDaona9Ph6KTOtVw=")!
let fileURL = Bundle.main.url(forResource: "file", withExtension: "plist")!
let fileData = try! Data(contentsOf: fileURL)

var hash = Data(count: Int(CC_SHA256_DIGEST_LENGTH))
hash.withUnsafeMutableBytes { hashBuffer in
   fileData.withUnsafeBytes { buffer in
        _ = CC_SHA256(buffer.baseAddress!, CC_LONG(buffer.count), hashBuffer.bindMemory(UInt8.self).baseAddress)
   }
}

print(caluclatedHash as NSData)
print(hash as NSData)

// <a3318470 0a1f61f8 0d4a1d09 2e83457c 9abdf794 c20daa27 6bd3e1e8 a4ceb55c>
// <96d172a8 48235f59 66ff2af3 dae8220d df33f0aa 3be78c46 9d5a18e4 9c73aecd>


As you can see, the output is different for the iOS hash. Why is that and how do I solve it?


Thanks in advance!

Craz1k0ek

Accepted Reply

Solved by using a python library.


import plistlib
import hashlib

def calc_hash(file_name):
    try:
        f = open(file_name, 'r')
        f_data = f.read()
        f.close()
        file = plistlib.loads(f_data.encode())
    except (ValueError, Exception) as e:
        print("Failed to load file {}".format(file_name))
        return
    dump = plistlib.dumps(file, fmt=plistlib.FMT_BINARY)
  
    hasher = hashlib.sha256()
    hasher.update(dump)
    digest = hasher.digest()
  
    print("{} {}".format(file_name, digest.hex()))

file_name = str(input('Please enter the relative path to the plist (i.e. path/to/plist.plist):\n'))
calc_hash(file_name)

Replies

You are getting this property list from your bundle. I suspect that the problem here is that the Xcode build system will convert property list files to a binary format, which changes the checksum. You should dump

fileData
to make sure it matches what you expect.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Is there a way to prevent that from happening? In direct reply to your answer, I did convert it to binary myself:


plutil -convert binary1 file.plist

Solved by using a python library.


import plistlib
import hashlib

def calc_hash(file_name):
    try:
        f = open(file_name, 'r')
        f_data = f.read()
        f.close()
        file = plistlib.loads(f_data.encode())
    except (ValueError, Exception) as e:
        print("Failed to load file {}".format(file_name))
        return
    dump = plistlib.dumps(file, fmt=plistlib.FMT_BINARY)
  
    hasher = hashlib.sha256()
    hasher.update(dump)
    digest = hasher.digest()
  
    print("{} {}".format(file_name, digest.hex()))

file_name = str(input('Please enter the relative path to the plist (i.e. path/to/plist.plist):\n'))
calc_hash(file_name)