Sign a String with SecKeyCreateSignature

Hi


I'm trying to use SecKeyCreateSignature to sign a string but seem to have missed something. Here is my code snippet:


public static func sign(using name: String, value: String, base64EncodingOptions: Data.Base64EncodingOptions = []) -> String?
{
    // Get private key by name using SecItemCopyMatching
    guard let privateKey: SecKey = getPrivateKey(name) else
    {
        return nil
    }

    let data = value.data(using: .utf8)!
     
    var error: Unmanaged<CFError>?
    guard let signedData = SecKeyCreateSignature(privateKey,
                                                    .rsaSignatureDigestPKCS1v15SHA512,
                                                    data as CFData,
                                                    &error) as Data? else
    {
        return nil
    }
   
    return signedData.base64EncodedString(options: base64EncodingOptions)
}


And to call the method:

let result = sign("MyKey", "hello world")
print(result)



Using the public key generated on iOS and exported to Java, the validation fails. I'm think it might be something to do with value.data(using: .utf8) but I'm not sure. Using the older style SecKeyRawSign you would hash the "hello world" value before invoking SecKeyRawSign


Any ideas or a simple example would be great 🙂

Accepted Reply

I figured out the probem. I thought it had to do with line 9. of the snippet where I'm creating the data variable. It turned out to be the algorithm paramter in line 12. From the snippet I was passing in rsaSignatureDigestPKCS1v15SHA512, when what I should have been passing in was rsaSignatureMessagePKCS1v15SHA512.


After updating the parameter, small and large string values are now working and can be verified against my public key. Below is the updated function:


public static func sign(using name: String, value: String, base64EncodingOptions: Data.Base64EncodingOptions = []) -> String?
{
    /
    guard let privateKey: SecKey = getPrivateKey(name) else
    {
        return nil
    }
   
    let data = value.data(using: .utf8)!
   
    var error: Unmanaged<CFError>?
    guard let signedData = SecKeyCreateSignature(privateKey,
                                                 .rsaSignatureMessagePKCS1v15SHA512,
                                                 data as CFData,
                                                 &error) as Data? else
    {
        return nil
    }
}


Hope this helps.

Replies

I figured out the probem. I thought it had to do with line 9. of the snippet where I'm creating the data variable. It turned out to be the algorithm paramter in line 12. From the snippet I was passing in rsaSignatureDigestPKCS1v15SHA512, when what I should have been passing in was rsaSignatureMessagePKCS1v15SHA512.


After updating the parameter, small and large string values are now working and can be verified against my public key. Below is the updated function:


public static func sign(using name: String, value: String, base64EncodingOptions: Data.Base64EncodingOptions = []) -> String?
{
    /
    guard let privateKey: SecKey = getPrivateKey(name) else
    {
        return nil
    }
   
    let data = value.data(using: .utf8)!
   
    var error: Unmanaged<CFError>?
    guard let signedData = SecKeyCreateSignature(privateKey,
                                                 .rsaSignatureMessagePKCS1v15SHA512,
                                                 data as CFData,
                                                 &error) as Data? else
    {
        return nil
    }
}


Hope this helps.

Thank you for share your answer! It helped me a lot 🙂😁