Firmar y verificar en iOS usando RSA

¿Cómo firmar y verificar algunos datos en iOS con una key RSA (preferiblemente usando el sistema propio libcommonCrypto )?

Como no había casi ningún conocimiento sobre la firma y la verificación encontrada en StackOverflow y los documentos de Apple, tuve que search manualmente en los files de encabezado de iOS y encontré SecKeyRawSign y SecKeyRawVerify . Las siguientes líneas de código parecen funcionar.


Firma NSData (usando SHA256 con RSA):

 NSData* PKCSSignBytesSHA256withRSA(NSData* plainData, SecKeyRef privateKey) { size_t signedHashBytesSize = SecKeyGetBlockSize(privateKey); uint8_t* signedHashBytes = malloc(signedHashBytesSize); memset(signedHashBytes, 0x0, signedHashBytesSize); size_t hashBytesSize = CC_SHA256_DIGEST_LENGTH; uint8_t* hashBytes = malloc(hashBytesSize); if (!CC_SHA256([plainData bytes], (CC_LONG)[plainData length], hashBytes)) { return nil; } SecKeyRawSign(privateKey, kSecPaddingPKCS1SHA256, hashBytes, hashBytesSize, signedHashBytes, &signedHashBytesSize); NSData* signedHash = [NSData dataWithBytes:signedHashBytes length:(NSUInteger)signedHashBytesSize]; if (hashBytes) free(hashBytes); if (signedHashBytes) free(signedHashBytes); return signedHash; } 

Verificación (usando SHA256 con RSA):

 BOOL PKCSVerifyBytesSHA256withRSA(NSData* plainData, NSData* signature, SecKeyRef publicKey) { size_t signedHashBytesSize = SecKeyGetBlockSize(publicKey); const void* signedHashBytes = [signature bytes]; size_t hashBytesSize = CC_SHA256_DIGEST_LENGTH; uint8_t* hashBytes = malloc(hashBytesSize); if (!CC_SHA256([plainData bytes], (CC_LONG)[plainData length], hashBytes)) { return nil; } OSStatus status = SecKeyRawVerify(publicKey, kSecPaddingPKCS1SHA256, hashBytes, hashBytesSize, signedHashBytes, signedHashBytesSize); return status == errSecSuccess; } 

Alternativas (OpenSSL):

Hay una muy buena alternativa disponible que utiliza OpenSSL directamente en lugar de libCommonCrypto. MIHCrypto es una biblioteca de contenedor Objective-C bien diseñada para OpenSSL que hace que trabajar con cryptography sea muy fácil. Vea el siguiente ejemplo.

Generar una key es así de simple:

 MIHAESKeyFactory *factory = [[MIHAESKeyFactory alloc] init]; id<MIHSymmetricKey> aesKey = [factory generateKey]; 

O cargando una llave del file:

 NSData *privateKeyData = [[NSFileManager defaultManager] contentsAtPath:"mykey.pem"]; MIHRSAPrivateKey *privateKey = [[MIHRSAPrivateKey alloc] initWithData:privateKeyData]; 

Ahora firme algo:

 NSError *signingError = nil; NSData *message = // load something to sign from somewhere NSData *signature = [privateKey signWithSHA256:message error:&signingError] 

Para más ejemplos, busque la página MIHCrypto .