2010-11-18 26 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是一个公共可用的库,你可以使用。