Ответ 1
Это должно делать то, что вы просите - оно шифрует данные с помощью открытого ключа сервера. Он не подвержен атакам MITM, если у злоумышленника нет копии вашего закрытого ключа и его пароля (однако, по-прежнему не выполняется SSL, но данные, которые вы шифруете с помощью открытого ключа сервера, почти невозможно расшифровать),
Я собрал это вместе с документами Apple, на этом сайте, на форумах разработчиков Apple и, возможно, в других местах. Так спасибо всем, что я скрепил код от! Этот код предполагает несколько вещей:
-
Вы уже создали пары ключей RSA (я использую 4096-битный ключ, и это кажется достаточно быстрым) и, используя закрытый ключ, создал DER-закодированный сертификат под названием cert.cer, который вы вложили в свой ресурс вашего приложения (очевидно, вы также можете загрузить сертификат со своего сервера, но затем снова открыты атаки MITM). По умолчанию OpenSSL генерирует сертификат, закодированный PEM, поэтому вы должны преобразовать его с помощью "openssl x509 -in cert.pem -inform PEM -out cert.cer -outform DER". iOS будет зависеть от PEM. Причина, по которой я использую сертификат, на самом деле проще работать, и поддерживается в iOS. Использование только открытого ключа не является (хотя это можно сделать).
-
Вы добавили Security.framework в свой проект, и вы #import < Security/Security.h > .
/* Возвращает NSData зашифрованного текста или nil, если шифрование не удалось.
Принимает сертификат X.509 как NSData (например, из dataWithContentsOfFile:)
*/
+(NSData *)encryptString:(NSString *)plainText withX509Certificate:(NSData *)certificate {
SecCertificateRef cert = SecCertificateCreateWithData(kCFAllocatorDefault, (__bridge CFDataRef)certificate);
SecPolicyRef policy = SecPolicyCreateBasicX509();
SecTrustRef trust;
OSStatus status = SecTrustCreateWithCertificates(cert, policy, &trust);
SecTrustResultType trustResult;
if (status == noErr) {
status = SecTrustEvaluate(trust, &trustResult);
}
SecKeyRef publicKey = SecTrustCopyPublicKey(trust);
const char *plain_text = [plainText UTF8String];
size_t blockSize = SecKeyGetBlockSize(publicKey);
NSMutableData *collectedCipherData = [NSMutableData data];
BOOL success = YES;
size_t cipherBufferSize = blockSize;
uint8_t *cipherBuffer = malloc(blockSize);
int i;
for (i = 0; i < strlen(plain_text); i += blockSize-11) {
int j;
for (j = 0; j < blockSize-11 && plain_text[i+j] != '\0'; ++j) {
cipherBuffer[j] = plain_text[i+j];
}
int result;
if ((result = SecKeyEncrypt(publicKey, kSecPaddingPKCS1, cipherBuffer, j, cipherBuffer, &cipherBufferSize)) == errSecSuccess) {
[collectedCipherData appendBytes:cipherBuffer length:cipherBufferSize];
} else {
success = NO;
break;
}
}
/* Free the Security Framework Five! */
CFRelease(cert);
CFRelease(policy);
CFRelease(trust);
CFRelease(publicKey);
free(cipherBuffer);
if (!success) {
return nil;
}
return [NSData dataWithData:collectedCipherData];
}