iOS: Vérification d'un file avec un certificate et une signature – La key publique est incorrecte, la vérification échoue

J'ai trois choses: un file, un file de signature, et un file de certificate X509 .cer. Le file doit être vérifié à l'aide de la key publique du certificate et du file de signature. Je veux le faire en utilisant Security.h / CommonCrypto.

Ce que j'ai essayé jusqu'ici:

// load all the files NSData* fileData = [NSData dataWithContentsOfFile:(...)]; NSData* signatureData = [NSData dataWithContentsOfFile:(...)]; NSData* certificateeData = [NSData dataWithContentsOfFile:(...)]; SecCertificateRef certificatee = SecCertificateCreateWithData(NULL, CFBridgingRetain(certificateeData)); // load the certificatee 

Le certificate se charge très bien. Son nom peut être vérifié en utilisant

 CFSsortingngRef certificateeDescription = SecCertificateCopySubjectSummary(certificatee); 

ce qui fonctionne. Comme il n'y a pas de méthode sur iOS pour copyr directement la key publique, je crée d'abord une confiance.

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

Tout cela fonctionne très bien avec un résultat errSecSuccess.

Maintenant, j'essaie d'get la key publique.

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

Mais le contenu de publicKey

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

n'est pas la même que la key publique que je vois lors de l'ouverture du file .cer. Donc, c'est le problème numéro un.

Ensuite, j'essaie de vérifier la signature, même si je sais que la key publique est fausse. Le rembourrage est correct.

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

Cela échoue avec un OSStatus de -9809 (l'opération n'a pas pu être terminée). Je m'attends à ce que ce soit -25293 errSecAuthFailed.

Est-ce que je fais quelque chose de fondamentalement faux?

J'ai résolu le problème avec l'aide d' un indice de Apple Dev Forums .

Le problème n'avait rien à voir avec le trousseau. Mais j'ai passé les mauvais parameters à la fonction de vérification. Il a besoin d'un condensé (hachage) des données, pas des données directement.

 NSData* fileData = [NSData dataWithContentsOfFile:(...)]; NSData* signatureData = [NSData dataWithContentsOfFile:(...)]; NSData* certificateeData = [NSData dataWithContentsOfFile:(...)]; SecCertificateRef certificateeFromFile = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)certificateeData); // load the certificatee SecPolicyRef secPolicy = SecPolicyCreateBasicX509(); SecTrustRef trust; OSStatus statusTrust = SecTrustCreateWithCertificates( certificateeFromFile, 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(certificateeFromFile); if (verficationResult == errSecSuccess) NSLog(@"Verified"); 

Votre problème est lorsque vous essayez d'get datatables keys:

 SecKeyRef publicKey; publicKey = SecTrustCopyPublicKey(trust); size_t keysize = SecKeyGetBlockSize(publicKey); But the content of publicKey NSData* keyData = [NSData dataWithBytes:publicKey length:keysize]; 

Ce n'est pas la key publique. Ce sont les premiers "X" octets de la structure de données SecKeyRef ("X" étant la taille de la key publique). Ce n'est rien d'particulièrement utile.

Malheureusement, je ne connais aucun moyen de passer directement d'un SecKeyRef à un NSData . Ce que vous avez à faire est de mettre le SecKeyRef dans keychain ( SecItemAdd ), puis de le récupérer ( SecItemCopyMatching avec kSecReturnData set). Lorsque vous le récupérerez, vous aurez la key publique en tant que NSData .

(Je ne sais pas pourquoi Apple rend Security.amework si incroyablement compliqué à utiliser ….)