将RSA公钥发送到iphone并使用它进行加密

时间:2010-11-18 03:39:52

标签: iphone c++ cryptography openssl rsa

我有一个TCP套接字服务器,我想使用SSL执行以下操作:

  1. 在服务器上,生成RSA密钥对(我知道如何使用openssl的加密库执行此操作)
  2. 在服务器上,将公钥发送到iphone并保留私钥。
  3. 在客户端(iphone)上,希望使用公钥加密消息,使用SecKeyEncrypt。
  4. 在服务器上解密消息。
  5. 消息足够短,因此PKCS1填充结果适合128个字节。

    我不知道怎么做2~4。有人知道吗?

2 个答案:

答案 0 :(得分:18)

这应该做你要求的 - 它用服务器的公钥加密数据。它不受MITM攻击,除非攻击者拥有您的私钥及其密码的副本(通过非SSL进行通信,但仍然是,但是使用服务器的合法公钥加密的数据几乎不可能解密) 。

我从Apple的文档,这个网站,Apple开发者论坛以及其他地方拼凑了这些。所以感谢大家,我从中抄写了代码!这段代码假定了几件事:

  1. 您已经生成了RSA密钥对(我使用的是4096位密钥,看起来足够快),并使用私钥创建了一个名为“cert.cer”的DER编码证书您放入应用程序的资源包中(显然,您也可以从服务器下载证书,但之后您再次接受MITM攻击)。默认情况下,OpenSSL生成PEM编码的证书,因此您必须使用“openssl x509 -in cert.pem -inform PEM -out cert.cer -outform DER”进行转换。 iOS将在PEM上进行barf。我使用证书的原因是它实际上更容易使用,并且在iOS中受支持。仅使用公钥(虽然可以这样做)。

  2. 您已将Security.framework添加到项目中,并且#import< Security / Security.h>。

  3. / *      返回加密文本的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];
    }
    

答案 1 :(得分:1)

好吧,我想你需要将你的公钥发布到外面的世界(在你的情况下是iPhone)。要做到最好的方法是发布包含公钥的证书,iPhone应用程序可以下载它。然后,iPhone应用程序可以利用PGP的原则,使用对称算法(如AES)加密数据,并使用公钥加密对称。服务器中的应用程序将接收消息,使用其私钥解密对称密钥,然后使用由此获得的对称密钥解密加密数据。

但正如cobbal所说,任何人都可以拦截服务器和iPhone之间的消息,并且可以更改它,并且服务器不会知道它是否“实际”从iPHone收到了数据,除非您使用SSL证书(即使用iPhone的私钥加密方法的哈希)。

我的建议是,使用有用的第三方应用程序而不是自己动手,因为它们可能在实现中有些愚蠢。 PGP是一个公共可用的库,你可以使用。