将 RSA 公钥发送到 iphone 并使用它来加密 [英] send RSA public key to iphone and use it to encrypt

查看:19
本文介绍了将 RSA 公钥发送到 iphone 并使用它来加密的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a TCP socket server and I want to do the following w/o using SSL:

  1. 在服务器上,制作 RSA 密钥对(我知道如何使用 openssl 的加密库来做到这一点)
  2. 在服务器上,将公钥发送到 iphone 并保留私钥.
  3. 在客户端 (iphone) 上,想要使用公钥加密消息,使用 SecKeyEncrypt.
  4. 在服务器上,解密消息.

消息足够短,因此 PKCS1 填充的结果适合 128 个字节.

The message is short enough so that the PKCS1 padded result fits into 128 bytes.

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

I don't know how to do 2~4. Anyone knows?

推荐答案

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

This should do what you're asking - it encrypts data with the server's public key. It's not subject to MITM attacks, unless the attacker has a copy of your private key and its password (communicating via non-SSL, however, still is, but the data you encrypt with the server's legit public key will be nearly impossible to decrypt).

我从 Apple 的文档、本网站、Apple 开发者论坛和其他地方拼凑而成.所以感谢所有我抄袭代码的人!这段代码假设了几件事:

I cobbled this together from Apple's docs, this site, the Apple developer forums and probably elsewhere. So thanks to everyone I cribbed code from! This code assumes several things:

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

  1. You've already generated your RSA key pairs (I'm using a 4096-bit key and it seems speedy enough) and, using the private key, created a DER-encoded certificate called "cert.cer" that you put in your resource bundle of your app (obviously, you can also download the cert from your server, but then you're open to MITM attacks again). By default, OpenSSL generates a PEM encoded cert, so you have to convert it with "openssl x509 -in cert.pem -inform PEM -out cert.cer -outform DER". iOS will barf on PEM. The reason I use a cert is it's actually easier to work with, and is supported in iOS. Using just the public key isn't (though it can be done).

您已将 Security.framework 添加到您的项目中,并且您 #import .

You've added Security.framework to your project and you #import <Security/Security.h>.

/*返回加密文本的 NSData,如果加密不成功,则返回 nil.
将 X.509 证书作为 NSData(例如来自 dataWithContentsOfFile:)*/

/* Returns an NSData of the encrypted text, or nil if encryption was unsuccessful.
Takes the X.509 certificate as NSData (from dataWithContentsOfFile:, for example) */

+(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] != ''; ++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];
}

这篇关于将 RSA 公钥发送到 iphone 并使用它来加密的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆