SecKeyRawSign返回错误-1,"一般错误"?

时间:2016-09-09 12:38:44

标签: swift security public-key-encryption sha256

我正在开发一个iOS应用程序,需要在设备上生成密钥对,将私钥存储在Secure Enclave中,然后再访问它以用于签名(不需要导出,永远)。当我签名时,我总是使用SHA256散列数据,遵循几个堆栈溢出答案,并且当我打印结果时它似乎正在工作。但是,在从KeyChain获取有效私钥引用,散列要签名的数据并指定它是SHA256散列后,SecKeyRawSign仍然返回-1。这只列为“通用错误”,我的设置似乎应该有效。对于出了什么问题的一些见解将不胜感激。以下是我生成和签名的方法:

private func genKeyPair() -> (privateAlias: String, publicKey: NSData)? {

    // Generate a keyhandle, which will be returned as an alias for the private key
    let numBytes = Int(keyHandleLength)
    var randomBytes = [UInt8](count: numBytes, repeatedValue: 0)
    SecRandomCopyBytes(kSecRandomDefault, numBytes, &randomBytes)
    let data = NSData(bytes: &randomBytes, length: numBytes)
    let alias = data.base64EncodedStringWithOptions(NSDataBase64EncodingOptions(rawValue: 0))

    let access = SecAccessControlCreateWithFlags(nil, kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly, .TouchIDCurrentSet, nil)!

    // Key pair parameters
    var keyParams: [String:AnyObject] = [
        kSecAttrKeyType as String: kSecAttrKeyTypeEC,
        kSecAttrKeySizeInBits as String: 256
    ]

    // Private key parameters
    keyParams[kSecPrivateKeyAttrs as String] = [
        kSecAttrIsPermanent as String: true,
        kSecAttrLabel as String: alias,
        kSecAttrApplicationTag as String: applicationTag,
        kSecAttrAccessControl as String: access
    ]

    // Public key parameters
    keyParams[kSecPublicKeyAttrs as String] = [
        kSecAttrIsPermanent as String: true,
        kSecAttrLabel as String: alias + "-pub",
        kSecAttrApplicationTag as String: applicationTag
    ]

    var pubKeyRef, privKeyRef: SecKey?
    var err = SecKeyGeneratePair(keyParams, &pubKeyRef, &privKeyRef)

    guard let _ = pubKeyRef where err == errSecSuccess else {

        print("Error while generating key pair: \(err).")
        return nil

    }

    // Export the public key for application use
    let query = [
        kSecClass as String: kSecClassKey,
        kSecAttrLabel as String: alias + "-pub",
        kSecAttrKeyType as String: kSecAttrKeyTypeEC,
        kSecReturnData as String: true
    ]
    var pubKeyOpt: AnyObject?
    err = SecItemCopyMatching(query, &pubKeyOpt)

    if let pubKey = pubKeyOpt as? NSData where err == errSecSuccess {

        print("Successfully retrieved public key!")
        return (alias, pubKey)

    } else {

        print("Error retrieving public key: \(err).")
        return nil

    }

}

private func sign(bytes data: NSData, usingKeyWithAlias alias: String) -> NSData? {

    let query = [
        kSecClass as String: kSecClassKey,
        kSecAttrLabel as String: alias,
        kSecAttrApplicationTag as String: applicationTag,
        kSecAttrKeyType as String: kSecAttrKeyTypeEC,
        kSecReturnRef as String: true
    ]

    var privateKey: AnyObject?
    var error = SecItemCopyMatching(query, &privateKey)

    guard error == errSecSuccess else {

        print("Could not obtain reference to private key with alias \"\(alias)\", error: \(error).")
        return nil

    }

    print("\nData: \(data)")
    print("Length: \(data.length)")

    let hashedData = NSMutableData(length: Int(CC_SHA256_DIGEST_LENGTH))!
    CC_SHA256(data.bytes, CC_LONG(data.length), UnsafeMutablePointer(hashedData.mutableBytes))

    print("\nHashed data: \(hashedData)")
    print("Length: \(hashedData.length)")

    var signedHashLength = SecKeyGetBlockSize(privateKey as! SecKeyRef)
    let signedHash = NSMutableData(length: signedHashLength)!

    error = SecKeyRawSign(privateKey as! SecKeyRef, .PKCS1SHA256, UnsafePointer<UInt8>(hashedData.mutableBytes), hashedData.length, UnsafeMutablePointer<UInt8>(signedHash.mutableBytes), &signedHashLength)

    print("\nSigned hash: \(signedHash)")
    print("Length: \(signedHashLength)\n")

    guard error == errSecSuccess else {

        print("Failed to sign data, error: \(error).")
        return nil

    }

    return signedHash

}

0 个答案:

没有答案