2010-11-18 51 views
11

我有一個TCP套接字服務器,我想做到以下幾點W/O使用SSL:發送RSA公鑰到iPhone,並用它來加密

  1. 在服務器上,使RSA密鑰對(我知道如何使用openssl的加密庫來做到這一點)
  2. 在服務器上,將公鑰發送給iphone並保留私鑰。
  3. 在客戶端(iphone)上,要使用SecKeyEncrypt使用公鑰加密消息。
  4. 在服務器上,解密消息。

該消息足夠短,以便PKCS1填充結果適合128個字節。

我不知道該怎麼做2〜4。有誰知道?

+0

不是一個問題,據我可以看到。 – 2010-11-18 03:44:19

+0

格雷格對不起。我剛剛添加了一個問題。 – 2010-11-18 03:53:51

+0

沒有SSL,這將不安全;它會受到[中間人攻擊](http://en.wikipedia.org/wiki/Man_in_the_middle_attack)的影響。 – cobbal 2010-11-18 04:03:08

回答

18

這應該做你所問 - 它使用服務器的公鑰加密數據。它不受MITM攻擊,除非攻擊者擁有私鑰和密碼副本(通過非SSL進行通信,但是,現在仍然存在,但用服務器的合法公鑰加密的數據幾乎不可能解密) 。

我把蘋果的文檔,本網站,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,如果加密不成功,則返回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]; 
} 
+3

+1「免費安全框架五!」 – rob5408 2012-11-19 16:15:56

+0

你好scaba,我有public.key文件從JAVA服務器,現在我需要使用該密鑰在ios sdk中加密我的密碼...我無法讀取ios中的.key擴展名文件。 – Apple 2013-10-10 12:21:56

+0

Tapan:您必須使用DER編碼密鑰。檢查以確保您的public.key是DER編碼的,否則您需要將其轉換爲使用它。看到我上面的#1。 – scaba 2013-12-07 23:42:14

1

嗯,我想你會需要發佈你的公共密鑰到外部世界(在你的情況下iPhone)。要做到最好的方法是發佈一個包含公鑰的證書,並且iPhone應用可以下載它。然後,iPhone應用程序可以利用PGP的原理用對稱算法(如AES)對數據進行加密,並用公鑰對稱加密。服務器中的應用程序將接收到消息,使用其私鑰解密對稱密鑰,然後使用由此獲得的對稱密鑰來解密加密的數據。

但是正如cobbal所說,任何人都可以攔截服務器和iPhone之間的消息,並且可以更改它,並且服務器不知道它是否實際上從iPHone接收到數據,除非您使用SSL證書(即用iPhone的私鑰加密方法的散列)。

我的建議是,使用可用的第三方應用程序,而不是自己做,因爲它們可能會在執行過程中遇到一些問題。 PGP是一個公共可用的庫,你可以使用。