2010-11-18 2 views
11

У меня есть сервер TCP сокет, и я хочу сделать следующее без использования SSL:отправить открытый ключ RSA для Iphone и использовать его для шифрования

  1. На сервере, сделать пару ключей RSA (я знаю, как для этого используйте криптографическую библиотеку openssl)
  2. На сервере отправьте открытый ключ на iphone и сохраните секретный ключ.
  3. На клиенте (iphone) требуется шифровать сообщение с использованием открытого ключа, используя SecKeyEncrypt.
  4. На сервере расшифруйте сообщение.

Сообщение достаточно короткое, так что результат с дополнением PKCS1 соответствует 128 байтам.

Я не знаю, как это сделать 2 ~ 4. Кто-нибудь знает?

+0

Не вопрос, насколько я могу видеть. –

+0

Извините, Грег. Я только что добавил вопрос. –

+0

Это не будет безопасно без SSL; он будет подвергнут [человеку в средней атаке] (http://en.wikipedia.org/wiki/Man_in_the_middle_attack). – cobbal

ответ

18

Это должно делать то, что вы просите - оно шифрует данные с помощью открытого ключа сервера. Он не подлежит атакам MITM, если у злоумышленника нет копии вашего закрытого ключа и его пароля (однако, по-прежнему осуществляется связь через не-SSL, но данные, которые вы шифруете с помощью открытого открытого ключа сервера, почти невозможно расшифровать) ,

Я собрал это вместе из документов Apple, этого сайта, форумов разработчиков Apple и, возможно, в другом месте. Так спасибо всем, что я скрепил код от! Этот код предполагает несколько вещей:

  1. Мы уже сформировали свои пары ключей RSA (я использую 4096-битный ключ и, кажется, достаточно быстрый) и, используя секретный ключ, созданный DER-кодированный сертификат под названием «cert.cer», который вы вложили в свой ресурс вашего приложения (очевидно, вы также можете загрузить сертификат со своего сервера, но затем снова открыты атаки MITM). По умолчанию OpenSSL генерирует сертификат, закодированный PEM, поэтому вы должны преобразовать его с помощью «openssl x509 -in cert.pem -inform PEM -out cert.cer -outform DER». iOS будет зависеть от PEM. Причина, по которой я использую сертификат, на самом деле проще работать, и поддерживается в iOS. Использование только открытого ключа не является (хотя это можно сделать).

  2. Вы добавили Security.framework в свой проект, и вы #import <Security/Security.h>.

/* Возвращает NSData зашифрованного текста, или ноль, если шифрование не увенчалась успехом.
принимает сертификат 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]; 
} 
+3

+1 за «освободите рамки безопасности пять!» – rob5408

+0

привет, scaba, у меня есть файл public.key с сервера JAVA, теперь мне нужно зашифровать свой пароль с помощью этого ключа в ios sdk ... я не могу прочитать файл расширения .key в ios. – Apple

+0

Tapan: Вы должны использовать закодированный ключ DER. Убедитесь, что ваш public.key закодирован DER, иначе вам нужно будет его преобразовать, чтобы использовать его. См. Мой № 1 выше. – scaba

1

Ну, я думаю, вам нужно будет публиковать свой открытый ключ во внешнем мире (iPhone в вашем случае). Сделать лучший способ - опубликовать сертификат, содержащий ваш открытый ключ, и приложение iPhone может его загрузить. Затем приложение iPhone может использовать принцип PGP для шифрования данных с помощью симметричного алгоритма (например, AES) и шифрования симметричного открытого ключа. Приложение на сервере получит сообщение, расшифрует симметричный ключ своим личным ключом и затем расшифрует зашифрованные данные с полученным таким образом симметричным ключом.

Но, как сказал cobbal, любой может перехватить сообщение между сервером и iPhone и может его изменить, и сервер не будет знать, действительно ли он «получил» данные от iPHone, если вы не подписываете его, используя SSL-сертификат (т. е. шифрование хэша метода с закрытым ключом iPhone).

Мое предложение состоит в том, чтобы использовать стороннее приложение availale, а не делать это самостоятельно, так как они могут быть частью процесса реализации tghe. PGP - общедоступная библиотека, которую вы можете использовать.