SecKeyCreateDecryptedData returns "RSAdecrypt wrong input" for OpenSSL's PKCS1

Hello
I have created a signature of a chunk of text using the following OpenSSL CLI command:

echo -n "sample text" | openssl dgst -sha1 -binary | openssl rsautl -sign -inkey "privatekey.pem"

Basically what it does it calculating sha1 digest of text, and then signing this calculated digest as a binary blob with OpenSSL RSA signing using a private key in a PEM format.

Now I would like to verify whether this "sample text" was signed by the owner of the privatekey.pem using a matching publickey.pem file, from within a macOS application.

I can easily verify the signature by "decrypting" it using openssl dylib, something like this:

Code Block
int returnedDigestSize = RSA_public_decrypt((int)signatureLength, signatureBytes, destination, rsa_key, RSA_PKCS1_PADDING);


(this will return me an original SHA1 digest, which I can then compare with the original string's SHA1 digest)

However I wouldn't like to have any dependencies on openssl, and would like to move to MacOS security libraries

I ended up attempting to use Security framework, since it is supported in earlier versions of macOS (I need all the way back to High Sierra).

What I am doing is the following:
Code Block
NSData *pubKeyData = [kPublicRSAKey dataUsingEncoding:NSUTF8StringEncoding];
SecExternalFormat keyFormat = kSecFormatOpenSSL;
SecExternalItemType keyType = kSecItemTypePublicKey;
CFArrayRef cfImportedItems = NULL;
OSStatus retval = 0;
retval = SecItemImport((CFDataRef)pubKeyData, NULL, &keyFormat, &keyType, 0, NULL, NULL, &cfImportedItems);
NSArray *importedItems = (bridge NSArray*)cfImportedItems;
if(!retval && importedItems && importedItems.count == 1) {
SecKeyRef pubKeyAppleFormat = (bridge SecKeyRef)(importedItems[0]);
CFErrorRef cfError = NULL;
Boolean b = SecKeyIsAlgorithmSupported(pubKeyAppleFormat, kSecKeyOperationTypeDecrypt, kSecKeyAlgorithmRSAEncryptionPKCS1);
NSLog(@"Algorithm supported: %d", b);
CFDataRef cfDigestData = SecKeyCreateDecryptedData(pubKeyAppleFormat, kSecKeyAlgorithmRSAEncryptionPKCS1, (CFDataRef)signatureData, &cfError);
if(!cfDigestData) {
NSLog(@"SecKeyCreateDecryptedData error%@", (bridge NSError*)cfError);
} else {
NSLog(@"%@", (bridge NSData*)cfDigestData);
}
}



This gives me an error: SecKeyCreateDecryptedData errorError Domain=NSOSStatusErrorDomain Code=-50 "RSAdecrypt wrong input (err -27)" (paramErr: error in user parameter list) UserInfo={numberOfErrorsDeep=0, NSDescription=RSAdecrypt wrong input (err -27)}

Note that OpenSSL code above can decrypt this with RSA_PKCS1_PADDING argument.

If instead of kSecKeyAlgorithmRSAEncryptionPKCS1 I put kSecKeyAlgorithmRSAEncryptionRaw, I do get some bytes and no errors, however they are incorrect, as OpenSSL CLI uses PKCS1.

Is there a way to get a matching to OpenSSL signature verification via macOS APIs?

Replies

Is there a way to get a matching to OpenSSL signature verification via
macOS APIs?

Try using SecKeyVerifySignature.

For specific code, check out my CryptoCompatibility sample code, which shows how to do various cryptographic operations with Security framework in a way that’s compatible with various third-party security libraries.

I can easily verify the signature by "decrypting" it using openssl
dylib, something like this:

FYI, this approach only works for RSA. For other asymmetric key formats the decrypt and verify operations are different. And you shouldn’t be using RSA anyway (-:

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@apple.com"