Log in to OS X, check on iOS and OSStatus -9809

I am using Apple Security Framework . I can sign and then successfully verify everything on OS X, but when I try to use SecKeyRawVerify on iOS, it fails with error -9809.

I played with various PKCS add-ons and many other attributes, but I just can't verify it correctly.

Please note that the code below probably has leaks all over the place, just trying to get it to function normally in the first place.

OS X Signature Code:

 NSData* signData(NSData* plainData, SecKeyRef privateKey) { CFErrorRef error; /* Create the transform objects */ SecTransformRef signer = SecSignTransformCreate(privateKey, &error); if (error) { CFShow(error); exit(-1); } /* Explicitly set padding type (necessary?) */ SecTransformSetAttribute(signer, kSecPaddingKey, kSecPaddingPKCS1Key, &error); if (error) { CFShow(error); exit(-1); } /* Specify digest type */ SecTransformSetAttribute(signer, kSecDigestTypeAttribute, kSecDigestSHA1, &error); if (error) { CFShow(error); exit(-1); } /* OS X calculates SHA1 hash/signature for us */ SecTransformSetAttribute(signer, kSecTransformInputAttributeName, plainData, &error); if (error) { CFShow(error); exit(-1); } CFTypeRef signature = SecTransformExecute(signer, &error); if (error || !signature) { CFShow(error); exit(-1); } CFRelease(signer); return signature; } 

and iOS verification code:

 + (NSData *)verifyData:(NSData *)data usingKey:(SecKeyRef)publicKey { size_t signatureByteLength = SecKeyGetBlockSize(publicKey); if (signatureByteLength > data.length) { NSLog(@"Signature length is greater that data length."); return nil; } NSData *signature = [data subdataWithRange:NSMakeRange(0, signatureByteLength)]; NSData *plainData = [data subdataWithRange:NSMakeRange(signatureByteLength, data.length - signatureByteLength)]; NSLog(@"signatureLength='%lu', signatureBytes='%@', plainDataLength=%lu", (unsigned long)signature.length, signature, (unsigned long)plainData.length); size_t hashByteLength = CC_SHA1_DIGEST_LENGTH; uint8_t* hashBytes = (uint8_t *)malloc(hashByteLength); if (CC_SHA1([plainData bytes], (CC_LONG)[plainData length], hashBytes)) { NSData *b = [NSData dataWithBytes:hashBytes length:hashByteLength]; NSLog(@"hashBytesLength='%lu', hashBytes=%@", (unsigned long)b.length, b); OSStatus status = SecKeyRawVerify(publicKey, kSecPaddingPKCS1SHA1, // I have also tried kSecPaddingPKCS1, doesn't work hashBytes, hashByteLength, (uint8_t *)[signature bytes], signatureByteLength); switch (status) { case errSecSuccess: NSLog(@"SecKeyRawVerify success."); return plainData; case errSSLCrypto: NSLog(@"SecKeyRawVerify failed: underlying cryptographic error"); break; case errSecParam: NSLog(@"SecKeyRawVerify failed: one or more parameters passed to a function where not valid."); break; default: NSLog(@"SecKeyRawVerify failed: error code '%d'", (int)status); break; } } return nil; } 

I created the private and public keys through the command line using the following OpenSSL commands:

 1. // Generate private and public key pair openssl genrsa -out rsaPrivate.pem 1024 1a. // Generate public key openssl rsa -in rsaPrivate.pem -pubout -outform PEM -out rsaPublic.pem 2. //Create a certificate signing request with the private key openssl req -new -key rsaPrivate.pem -out rsaCertReq.csr 3. //Create a self-signed certificate with the private key and signing request openssl x509 -req -days 3650 -in rsaCertReq.csr -signkey rsaPrivate.pem -out rsaCert.crt 4. //Convert the certificate to DER format: the certificate contains the public key openssl x509 -outform der -in rsaCert.crt -out rsaCert.der 

Any help is greatly appreciated.

+5
source share
2 answers

I understood the question. The code I posted is correct, but the padding should be set as kSecPaddingPKCS1SHA1 in the kSecPaddingPKCS1SHA1 header file:

 If you are verifying a proper PKCS1-style signature, with DER encoding of the digest type - and the signedData is a SHA1 digest - use kSecPaddingPKCS1SHA1. 

In addition, you can make sure that your public key in .der format is correct :)

+3
source
 if (CC_SHA1([plainData bytes], (CC_LONG)[plainData length], hashBytes)) { NSData *b = [NSData dataWithBytes:hashBytes length:hashByteLength]; NSLog(@"hashBytesLength='%lu', hashBytes=%@", (unsigned long)b.length, b); ... } 

It seems that you are not coding and correctly applying the add-on. Encoding and padding are applied before hashing. See RFC 3447, Public Key Cryptography Standards (PKCS) # 1: RSA Encryption Specifications Version 2.1 (or PKCS # 1 Specification).

0
source

All Articles