使用DER格式的RSA公钥文件进行iOS加密

使用DER格式的RSA公钥文件进行iOS加密,ios,objective-c,encryption,public-key-encryption,Ios,Objective C,Encryption,Public Key Encryption,我正在尝试使用RSA公钥加密iOS应用程序中的数据,以便通过web发送到客户服务。密钥是使用openssl生成的: openssl genrsa -out private.pem 2048 openssl rsa -in private.pem -pubout -out public.der -outform der 然后,我尝试按如下方式使用该键: NSString *aPublicKeyPath = [[NSBundle mainBundle] pathForResource:@"publ

我正在尝试使用RSA公钥加密iOS应用程序中的数据,以便通过web发送到客户服务。密钥是使用openssl生成的:

openssl genrsa -out private.pem 2048
openssl rsa -in private.pem -pubout -out public.der -outform der
然后,我尝试按如下方式使用该键:

NSString *aPublicKeyPath = [[NSBundle mainBundle] pathForResource:@"public" ofType:@"der"];
NSFileManager* aFileMgr = [NSFileManager defaultManager];
NSData* myCertData = [aFileMgr contentsAtPath: aPublicKeyPath];
CFDataRef myCertDataRef = (__bridge CFDataRef)myCertData;
SecCertificateRef cert = SecCertificateCreateWithData (kCFAllocatorDefault, myCertDataRef);
NSString *aPublicKeyPath = [[NSBundle mainBundle] pathForResource:@"public" ofType:@"der"];
NSFileManager* aFileMgr = [NSFileManager defaultManager];
NSData* aCertData = [aFileMgr contentsAtPath: aPublicKeyPath];
SecCertificateRef aCertRef = SecCertificateCreateWithData(kCFAllocatorDefault, (__bridge CFDataRef)aCertData);

if (aCertRef != NULL) {
    SecKeyRef aPublicKeyRef = NULL;
    SecTrustRef aTrustRef = NULL;
    SecPolicyRef aPolicyRef = SecPolicyCreateBasicX509();

    if (aPolicyRef) {
        if (SecTrustCreateWithCertificates((CFTypeRef)aCertRef, aPolicyRef, &aTrustRef) == noErr) {
            SecTrustResultType result;
            if (SecTrustEvaluate(aTrustRef, &result) == noErr) {
                aPublicKeyRef = SecTrustCopyPublicKey(aTrustRef);
            }
        }
    }

    if (aPolicyRef) CFRelease(aPolicyRef);
    if (aTrustRef) CFRelease(aTrustRef);
    if (aCertRef) CFRelease(aCertRef);
    NSString* aClearTextString = @"This is the test string";
    NSString* aEncryptedString = [[self class] encryptRSA:aClearTextString
                                                      key:aPublicKeyRef];
}
证书的内容正确加载到myCertData中,但SecCertificateCreateWithData返回nil而不引发异常。没有结果代码要检查,所以我不知道为什么它不工作

仅供参考-密钥似乎有效。如果我检查键,我会得到以下输出:

$ openssl rsa -text -in public.der -inform DER -pubin
Modulus (2048 bit):
00:a7:21:90:62:96:15:38:f8:43:5b:33:9f:00:a0:
12:51:63:0e:5c:72:58:05:6a:99:93:d8:6e:f4:d8:
4a:91:cb:dc:74:de:3c:38:63:06:41:5f:63:1e:e9:
70:81:90:e9:f0:e4:78:0a:00:5c:d3:ee:6a:5a:c1:
d7:9a:62:af:f3:45:91:5a:86:bc:aa:8f:86:f5:4f:
3d:01:4b:64:11:31:6f:c1:ab:07:e5:b8:5b:46:8e:
b5:c0:a1:2c:7b:65:1b:09:a9:12:b4:99:f8:77:46:
fa:62:52:04:32:98:09:1c:69:89:52:8c:30:77:af:
51:f2:30:0d:99:33:d3:2b:39:6c:6b:0e:19:ad:67:
10:69:0f:4e:3c:7a:a4:41:bd:87:4e:1d:65:b7:62:
7e:0d:b5:f7:ab:3d:b8:40:f1:c9:8c:c3:1e:9e:7c:
02:67:3a:21:ca:3a:3c:cd:d8:98:fe:4c:ab:30:d4:
f8:2d:3e:78:c3:f0:39:54:15:8a:b7:16:77:ca:3b:
ab:42:5e:70:3e:48:fd:a3:6c:55:5e:66:4b:33:d6:
c0:9c:db:2d:d2:26:78:b8:ca:69:6c:77:6d:38:ab:
77:a0:68:ad:e5:2d:11:50:57:b6:16:dc:b3:e2:82:
bb:07:88:08:a4:87:4c:c6:37:9e:33:ea:5a:f9:b4:
0c:6f
Exponent: 65537 (0x10001)
writing RSA key
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApyGQYpYVOPhDWzOfAKAS
UWMOXHJYBWqZk9hu9NhKkcvcdN48OGMGQV9jHulwgZDp8OR4CgBc0+5qWsHXmmKv
80WRWoa8qo+G9U89AUtkETFvwasH5bhbRo61wKEse2UbCakStJn4d0b6YlIEMpgJ
HGmJUowwd69R8jANmTPTKzlsaw4ZrWcQaQ9OPHqkQb2HTh1lt2J+DbX3qz24QPHJ
jMMennwCZzohyjo8zdiY/kyrMNT4LT54w/A5VBWKtxZ3yjurQl5wPkj9o2xVXmZL
M9bAnNst0iZ4uMppbHdtOKt3oGit5S0RUFe2Ftyz4oK7B4gIpIdMxjeeM+pa+bQM
bwIDAQAB
-----END PUBLIC KEY-----
有什么建议吗

更新:

iOS似乎不支持在没有严重黑客攻击的情况下直接读取上面生成的公钥,请参阅。我能够做到这一点,但我觉得这不是一个好方法,我把我的应用程序

终于找到了一个我满意的解决方案。正如文档中所述,证书必须采用DER格式,因此我使用此命令重新生成了它,它工作正常:

$ openssl req -x509 -out public_key.crt -outform DER -new -newkey rsa:4096 -keyout private_key.pem
然后我按如下方式使用该键:

NSString *aPublicKeyPath = [[NSBundle mainBundle] pathForResource:@"public" ofType:@"der"];
NSFileManager* aFileMgr = [NSFileManager defaultManager];
NSData* myCertData = [aFileMgr contentsAtPath: aPublicKeyPath];
CFDataRef myCertDataRef = (__bridge CFDataRef)myCertData;
SecCertificateRef cert = SecCertificateCreateWithData (kCFAllocatorDefault, myCertDataRef);
NSString *aPublicKeyPath = [[NSBundle mainBundle] pathForResource:@"public" ofType:@"der"];
NSFileManager* aFileMgr = [NSFileManager defaultManager];
NSData* aCertData = [aFileMgr contentsAtPath: aPublicKeyPath];
SecCertificateRef aCertRef = SecCertificateCreateWithData(kCFAllocatorDefault, (__bridge CFDataRef)aCertData);

if (aCertRef != NULL) {
    SecKeyRef aPublicKeyRef = NULL;
    SecTrustRef aTrustRef = NULL;
    SecPolicyRef aPolicyRef = SecPolicyCreateBasicX509();

    if (aPolicyRef) {
        if (SecTrustCreateWithCertificates((CFTypeRef)aCertRef, aPolicyRef, &aTrustRef) == noErr) {
            SecTrustResultType result;
            if (SecTrustEvaluate(aTrustRef, &result) == noErr) {
                aPublicKeyRef = SecTrustCopyPublicKey(aTrustRef);
            }
        }
    }

    if (aPolicyRef) CFRelease(aPolicyRef);
    if (aTrustRef) CFRelease(aTrustRef);
    if (aCertRef) CFRelease(aCertRef);
    NSString* aClearTextString = @"This is the test string";
    NSString* aEncryptedString = [[self class] encryptRSA:aClearTextString
                                                      key:aPublicKeyRef];
}
加密例程是:

+(NSString *)encryptRSA:(NSString *)plainTextString key:(SecKeyRef)publicKey         
{
    size_t cipherBufferSize = SecKeyGetBlockSize(publicKey);
    uint8_t *cipherBuffer = malloc(cipherBufferSize);
    uint8_t *nonce = (uint8_t *)[plainTextString UTF8String];
    SecKeyEncrypt(publicKey,
              kSecPaddingOAEP,
              nonce,
              strlen( (char*)nonce ),
              &cipherBuffer[0],
              &cipherBufferSize);
    NSData *encryptedData = [NSData dataWithBytes:cipherBuffer length:cipherBufferSize];
    return [encryptedData base64EncodedStringWithOptions:0];
}
请参阅上的文档

您正在尝试加载公钥。此API需要公钥证书,而不是公钥

上面说

如果数据参数中传递的数据无效,则返回NULL DER编码的X.509证书


所以,将其设置为公钥或使用其他API加载公钥。

我可以使用什么API?我找了一整天,找不到合适的API。您可以使用OpenSSL从公钥生成证书。好的,以DER格式生成密钥证书。一旦我这样做了,我就可以加载证书了。谢谢你的建议。