I'm trying to obtain a digital signature for a XML string using a RSA private key using Swift as command-line script (to be called from FileMaker later).
The compiler kept crashing with "segmentation fault 11" and then "Illegal Instruction: 4" and I kept drilling down until I (think) I found the problem, but it's completely beyond me, so please, please help!! ;) :)
As the title says, when I invoke SecTransformExecute on my SecSignTransform, with a binary version of my String as input attribute, I get the following error message:
Error Domain=Internal CSSM error Code=-2147415790 "The operation couldn’t be completed. (Internal CSSM error error -2147415790 - Internal error #80010912 at __SignTransform_block_invoke_2 /SourceCache/Security/Security-57031.1.35/Security/libsecurity_transform/lib/SecSignVerifyTransform.c:279)" UserInfo=0x7fc620e23aa0 {NSDescription=Internal error #80010912 at __SignTransform_block_invoke_2 /SourceCache/Security/Security-57031.1.35/Security/libsecurity_transform/lib/SecSignVerifyTransform.c:279, Originating Transform=CoreFoundationObject}
Here is the relevant part of my code:
import Foundation
import CoreFoundation
import Security
var signer: SecTransformRef
var signedData, digestData: NSData
var error: Unmanaged<CFErrorRef>?
var status: OSStatus
var key: SecKey
var anyItem: Unmanaged<AnyObject>?
var keySearchDict: [String : AnyObject]
let keyMatch = "[*place search tag here*]" as String
// turns a string into a binary to sign
let str = "Hello World"
let uintData = [UInt8](str.utf8)
let sourceData = CFDataCreate(kCFAllocatorDefault, uintData, countElements(uintData))
// sets up keySearchDict to query Keychain
keySearchDict = [(kSecClass as String): (kSecClassKey as String), (kSecMatchSubjectContains as String): keyMatch, (kSecReturnRef as String): kCFBooleanTrue]
// gets private key using keySearchDict
status = SecItemCopyMatching(keySearchDict, &anyItem)
key = (anyItem!.takeRetainedValue() as SecKey)
if status != 0 { println("status is: \(SecCopyErrorMessageString(status, &error).takeRetainedValue())") }
// creates SecTransform object using key
signer = SecSignTransformCreate(key, &error).takeRetainedValue()
if error == nil { println("signer transform creation error == nil") } else { println(error) }
// signer to get data from sourceData
SecTransformSetAttribute(signer, kSecTransformInputAttributeName, sourceData!, &error)
if error == nil { println("signer attribute setting error == nil") } else { println(error) }
// execute the transform
//signedData = (SecTransformExecute(signer, &error) as NSData)
let anything = SecTransformExecute(signer, &error)
if error == nil { println("signer execute error == nil") } else { println("erro: \(error!.takeRetainedValue())"); println(CFErrorGetCode(error!.takeRetainedValue())) }
println("anything = \(anything)")
//println(signedData)
I'm not very familiar with objc and actually not quite a proper coder, so please forgive my poor coding style ;) Also, sorry if I'm posting too much of it, but I figured better more than less...
Maybe I'm doing something wrong when transforming the String to binary for signing? I tried it both using CFData and NSData (to make this self contained, I'm using "Hello World" as my String, but in my code I actually load a UTF8 encoded XML from a file using NSData(contentsOfFile:) yet both generate the same error...)
Thanks you so much for your help! It's being a great learning experience, but I've been at it for over a week full-time now, so I really can use a break!! ;) :D