iOS: Verifying a File With a Certificate and Signature - Public Key is Wrong, Verification Fails

狂风中的少年 提交于 2019-12-04 10:01:38

问题


I have three things: a file, a signature file, and a X509 certificate file .cer. The file has to be verified using the public key in the certificate and the signature file. I want to do it using Security.h/CommonCrypto.

What I tried so far:

// load all the files
NSData* fileData = [NSData dataWithContentsOfFile:(...)];
NSData* signatureData = [NSData dataWithContentsOfFile:(...)];
NSData* certificateData = [NSData dataWithContentsOfFile:(...)];  

SecCertificateRef certificate = SecCertificateCreateWithData(NULL, CFBridgingRetain(certificateData)); // load the certificate

The certificate loads just fine. It's name can be checked using

CFStringRef certificateDescription = SecCertificateCopySubjectSummary(certificate);

which works. As there seems to be no method on iOS to copy the public key directly, I first create a trust.

SecTrustRef trust;
OSStatus statusTrust = SecTrustCreateWithCertificates( certificate, secPolicy, &trust);
SecTrustResultType resultType;
OSStatus statusTrustEval =  SecTrustEvaluate(trust, &resultType);

This all works fine with a errSecSuccess result.

Now I try to get the public key.

SecKeyRef publicKey;
publicKey = SecTrustCopyPublicKey(trust);
size_t keysize = SecKeyGetBlockSize(publicKey);

But the content of publicKey

NSData* keyData = [NSData dataWithBytes:publicKey length:keysize];

is not the same as the public key I see when opening the .cer file. So this is problem number one.

Then I try to verify the signature, even though I know the public key is wrong. The padding is correct.

OSStatus verficationResult = SecKeyRawVerify(publicKey,  kSecPaddingPKCS1, [fileData bytes], [fileData length], [signatureData bytes], [signatureData length]);

This fails with a OSStatus of -9809 (The operation couldn’t be completed). I expect it to be –25293 errSecAuthFailed.

Am I doing something fundamentally wrong?


回答1:


I solved the problem with the help of a hint from Apple Dev Forums.

The problem had nothing to do with the keychain. But I passed the wrong parameters to the verification function. It needs a digest (hash) of the data, not the data directly.

NSData* fileData = [NSData dataWithContentsOfFile:(...)];
NSData* signatureData = [NSData dataWithContentsOfFile:(...)];
NSData* certificateData = [NSData dataWithContentsOfFile:(...)];  

SecCertificateRef certificateFromFile = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)certificateData); // load the certificate

SecPolicyRef secPolicy = SecPolicyCreateBasicX509();

SecTrustRef trust;
OSStatus statusTrust = SecTrustCreateWithCertificates( certificateFromFile, secPolicy, &trust);
SecTrustResultType resultType;
OSStatus statusTrustEval =  SecTrustEvaluate(trust, &resultType);
SecKeyRef publicKey = SecTrustCopyPublicKey(trust);

uint8_t sha1HashDigest[CC_SHA1_DIGEST_LENGTH];
CC_SHA1([fileData bytes], [fileData length], sha1HashDigest);

OSStatus verficationResult = SecKeyRawVerify(publicKey,  kSecPaddingPKCS1SHA1, sha1HashDigest, CC_SHA1_DIGEST_LENGTH, [signatureData bytes], [signatureData length]);
CFRelease(publicKey);
CFRelease(trust);
CFRelease(secPolicy);
CFRelease(certificateFromFile);
if (verficationResult == errSecSuccess) NSLog(@"Verified");



回答2:


Your problem is when you're trying to get the key data:

SecKeyRef publicKey;
publicKey = SecTrustCopyPublicKey(trust);
size_t keysize = SecKeyGetBlockSize(publicKey);
But the content of publicKey

NSData* keyData = [NSData dataWithBytes:publicKey length:keysize];

That is not the public key. That is the first "X" bytes of the SecKeyRef data structure ("X" being the size of the public key). That's nothing particularly useful.

Unfortunately, I know of no way to go directly from a SecKeyRef to an NSData. What you have to do is put the SecKeyRef into keychain (SecItemAdd), and then fetch it back (SecItemCopyMatching with kSecReturnData set). When you fetch it back, then you'll have the public key as an NSData.

(I have no idea why Apple makes Security.framework so insanely complicated to use....)



来源:https://stackoverflow.com/questions/15438257/ios-verifying-a-file-with-a-certificate-and-signature-public-key-is-wrong-ve

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!