I am calling SecKeyRawVerify with a public key extracted from a certificate. The extraction of the public key seems to work but when I try and verify the signature I get the odd and generally undocumented ( as far as I can see) -67808. ( I have also tried this with a Sha256 hash).
The only reference to -67808 I can see anywhere is some mention on people seeing something similar with iCloud - access is restricted. The key is added to the keychain and seems legit. There are no obvious restrictions.
-(SecKeyRef)getSyncrPublicKeyfromfile{
NSMutableString *string = [[NSMutableString alloc] init];
NSString *certPath = [[NSBundle mainBundle] pathForResource:@"*.acme.net" ofType:@"cer"];
NSData *certData = [NSData dataWithContentsOfFile:certPath];
SecCertificateRef localCertificate = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)certData);
SecKeyRef localKey = NULL;
SecTrustRef localTrust = NULL;
SecCertificateRef certRefs[1] = {localCertificate};
CFArrayRef certArray = CFArrayCreate(kCFAllocatorDefault, (void *)certRefs, 1, NULL);
SecPolicyRef policy = SecPolicyCreateBasicX509();
OSStatus status = SecTrustCreateWithCertificates(certArray, policy, &localTrust);
SecTrustResultType resultType;
OSStatus statusTrustEval = SecTrustEvaluate(localTrust, &resultType);
NSString *result = [NSString stringWithFormat:@"Certificate Trust Evaluate result : %@\n",[self getCertificateResultStringFromResultCode:resultType]];
[string appendString:result];
if (status == errSecSuccess)
localKey = SecTrustCopyPublicKey(localTrust);
[string appendString:[NSString stringWithFormat:@"Public Key Object : %@",localKey]];
[self.pemResultTextView setString:string];
[self verifiySignautreFromCer:localKey];
return localKey;
}- (void) verifiySignautreFromCer:(SecKeyRef)publicKeyRef {
NSString *signauteDataStr = @"SNXprRB2Z5Xg7CiiEG+QMiRcACsGBvuPo/6bJLtONcSYP5kGpQAG0ZrEtS/49vbVK6d7jhbvLK+kfpCLIc8hfeRLyhZhGehYB9Q/BDwHT1VufQXUSp9hSTN3yPznWO7V1DvscLhhHiWypTodkjYAma5aa7P/6nspWPYoxe9RjvvTEhSmnPPVVkmiwZ5AL5sC/
NSData *signatureData = [[NSData alloc] initWithBase64EncodedString:signauteDataStr options:NSDataBase64DecodingIgnoreUnknownCharacters];
NSData *plainTextData = [self plainTextFileAsData];
BOOL valid = NO;
if (publicKeyRef != NULL) {
valid = [self PKCSVerifyBytesSHA256withRSA:plainTextData signature:signatureData publicKey:publicKeyRef];
}
if (valid) {
NSLog(@"Verified");
}
}- (BOOL)PKCSVerifyBytesSHA256withRSA:(NSData *)plainData signature:(NSData *)signature publicKey:(SecKeyRef)publicKey {
size_t signedHashBytesSize = SecKeyGetBlockSize(publicKey);
const uint8_t* signedHashBytes = [signature bytes];
size_t plainDataHashSize = CC_SHA1_DIGEST_LENGTH;
uint8_t* plainDataHashBytes = malloc(plainDataHashSize);
if (!CC_SHA1([plainData bytes], (CC_LONG)[plainData length], plainDataHashBytes)) {
free(plainDataHashBytes);
return NO;
}
OSStatus status = SecKeyRawVerify(publicKey,
kSecPaddingPKCS1SHA1,
plainDataHashBytes,
plainDataHashSize,
signedHashBytes,
signedHashBytesSize);
free(plainDataHashBytes);
return status == errSecSuccess;
}
This seems to work, modified from CrytoCompatability, which turned out to be useful. Thanks for that link. I dont suppose that a bug report on the failure in SecKeyRawVerify is needed as you have a fix in later OS. I would suggest that some of the older API be marked as deprecated. Theres a lot of code on the internet use SecAddItem and SecKeyRawVerify which have problems on older OSes. As you know. Maybe the documentation should mention CryptoCompatibility in the headers.
-
(BOOL)verifyUsingTransForm:(NSData*)inputData signatureData:(NSData*)signatureData publicKey:(SecKeyRef)publicKey{
BOOL success;
SecTransformRef transform;
CFBooleanRef result;
CFErrorRef errorCF;
result = NULL;
errorCF = NULL;
/
transform = SecVerifyTransformCreate(publicKey, (__bridge CFDataRef)signatureData, &errorCF);
success = (transform != NULL);
/
if (success) {
success = setupTransformForAlgorithm(transform, &errorCF);
}
if (success) {
success = SecTransformSetAttribute(transform, kSecTransformInputAttributeName, (__bridge CFDataRef) inputData, &errorCF) != false;
}
/
if (success) {
result = SecTransformExecute(transform, &errorCF);
success = (result != NULL);
}
/
if (success) {
Boolean verified = (CFBooleanGetValue(result) != false);
if (verified){
NSLog(@"verified");
} else {
NSLog(@"Not verified");
}
} else {
NSError* error = (__bridge NSError *) errorCF;
NSLog(@"error is %@", error);
}
/
if (result != NULL) {
CFRelease(result);
}
if (errorCF != NULL) {
CFRelease(errorCF);
}
if (transform != NULL) {
CFRelease(transform);
}
return success;
}