简体   繁体   中英

Swift 3: Convert SHA256 hash string to SecCertificate

Alamofire allows pinning using certificates as well as public keys (though the function to get public keys from the bundle gets the keys from the certificates in the bundle).

I am able to make the pinning work when the public keys are extracted from the certificates, but the pinning fails when I supply a SHA256 String as a public key (I receive the key string from an api call and its is supposed to be used as a public key if the first pinning fails.) I use the code below to convert the string to a [SecKey]

//Create server trust policy

let serverTrustPolicies: [String: ServerTrustPolicy] = [
                destinationURL!: .pinPublicKeys(
                    publicKeys:savePublicKeys(),
                    validateCertificateChain:true,
                    validateHost:true
                )]
            self.manager = SessionManager(
                serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPolicies))

//Get [SecKey]

func savePublicKeys() -> [SecKey]
{
    var key:SecKey?
    var publicKeys:[SecKey] = []


    //Check and use if backup key is received from beacon call
    if(KeychainService().checkIfKeyExists(tag: "backupURL"))
    {
        key = KeychainService().obtainKey(tag: backupURLKey)
        publicKeys.append(key!)
    }

    return publicKeys

}

//Functions to insert and retrieve keychain data

  func insertPublicKey(publicTag: String, data: Data) -> SecKey? {
    let query: Dictionary<String, AnyObject> = [
        String(kSecAttrKeyType): kSecAttrKeyClassPublic,
        String(kSecClass): kSecClassKey as CFString,
        String(kSecAttrApplicationTag): publicTag as CFString,
        String(kSecValueData): data as CFData,
        String(kSecReturnPersistentRef): true as CFBoolean]

    var persistentRef: AnyObject?
    let status = SecItemAdd(query as CFDictionary, &persistentRef)
    if status != noErr && status != errSecDuplicateItem {
        return nil
    }

    return obtainKey(tag: publicTag)
}

func obtainKey(tag: String) -> SecKey? {
    var keyRef: AnyObject?
    let query: Dictionary<String, AnyObject> = [
        String(kSecAttrKeyType): kSecAttrKeyClassPublic,
        String(kSecReturnRef): kCFBooleanTrue as CFBoolean,
        String(kSecClass): kSecClassKey as CFString,
        String(kSecAttrApplicationTag): tag as CFString,
        String(kSecReturnPersistentRef): true as CFBoolean
    ]

    let status = SecItemCopyMatching(query as CFDictionary, &keyRef)

    switch status {
    case noErr:
        if let ref = keyRef {
            return (ref as! SecKey)
        }
    default:
        break
    }

    return nil
}

Where am I going wrong? From what I know, the String I use is a base64encoded one and works in the Android part.

This is for others who might stumble around trying to find the answer to the same or similar question.

Short Answer: Hashing is kind of a one way street. While theoretically you might be able to try different inputs to get the hash and thus get the certificate data as desired in the question, realistically it is very difficult to do so. Hashing algorithms have been written to prevent exactly the thing you want to achieve here. To get the desired input, you might have to spend humongous amount of time, space and computing power.

Long Answer Read up more on what hashing really does.

For example, for SHA256 in the question there are 22562256 possible hashes. There is a 50% chance if you tried 22552255 different inputs. Even if you tried one every microsecond, this would take you 10631063 years. That is one of the major reasons why this is realistically difficult to achieve.

Reversing a hash is like trying to guess two numbers from their sum (x+y = 234). There are a lot of possible combinations. There are some great answers here

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM