iphone - 如何从 DER/PEM 文件获取 SecKeyRef

标签 iphone rsa public-key pem der

我需要将我的iPhone应用程序与系统集成,他们需要通过给定的公钥加密数据,有3个文件,3种不同的格式.xml .der和.pem,我研究并找到了一些关于从 DER/PEM 获取 SecKeyRef,但它们总是返回 nil。下面是我的代码:

NSString *pkFilePath = [[NSBundle mainBundle] pathForResource:@"PKFile" ofType:@"der"];
NSData *pkData = [NSData dataWithContentsOfFile:pkFilePath]; 

SecCertificateRef   cert; 
cert = SecCertificateCreateWithData(NULL, (CFDataRef) pkData);
assert(cert != NULL);

OSStatus err;

    if (cert != NULL) {
        err = SecItemAdd(
                         (CFDictionaryRef) [NSDictionary dictionaryWithObjectsAndKeys:
                                            (id) kSecClassCertificate,  kSecClass, 
                                            (id) cert,                  kSecValueRef,
                                            nil
                                            ], 
                         NULL
                         );
        if ( (err == errSecSuccess) || (err == errSecDuplicateItem) ) {
            CFArrayRef certs = CFArrayCreate(kCFAllocatorDefault, (const void **) &cert, 1, NULL); 
            SecPolicyRef policy = SecPolicyCreateBasicX509();
            SecTrustRef trust;
            SecTrustCreateWithCertificates(certs, policy, &trust);
            SecTrustResultType trustResult;
            SecTrustEvaluate(trust, &trustResult);
            if (certs) {
                CFRelease(certs);
            }
            if (trust) {
                CFRelease(trust);
            }
            return SecTrustCopyPublicKey(trust);
        }
    }
return NULL;

问题发生在 SecCertificateCreateWithData 处,即使读取文件正常,它也总是返回 nil。 有人做过这个请帮帮我,谢谢!

编辑:证书文件是 MD5 签名。

最佳答案

我为同样的问题苦苦挣扎,终于找到了解决方案。我的问题是,我需要使用外部私钥和公钥来加密/解密 iOS 应用程序中的数据,并且不想使用钥匙串(keychain)。 事实证明,您还需要 iOS 安全库的签名证书才能读取 key 数据,当然文件必须采用正确的格式。 流程基本如下:

假设您有一个 PEM 格式的私钥(带有 -----BEGIN RSA PRIVATE KEY----- 和 -----END RSA PRIVATE KEY----- 标记):rsaPrivate.pem

//Create a certificate signing request with the private key
openssl req -new -key rsaPrivate.pem -out rsaCertReq.csr

//Create a self-signed certificate with the private key and signing request
openssl x509 -req -days 3650 -in rsaCertReq.csr -signkey rsaPrivate.pem -out rsaCert.crt

//Convert the certificate to DER format: the certificate contains the public key
openssl x509 -outform der -in rsaCert.crt -out rsaCert.der

//Export the private key and certificate to p12 file
openssl pkcs12 -export -out rsaPrivate.p12 -inkey rsaPrivate.pem -in rsaCert.crt

现在您有两个与 iOS 安全框架兼容的文件:rsaCert.der(公钥)和 rsaPrivate.p12(私钥)。假设文件已添加到您的包中,下面的代码会读取公钥:

- (SecKeyRef)getPublicKeyRef {

    NSString *resourcePath = [[NSBundle mainBundle] pathForResource:@"rsaCert" ofType:@"der"];
    NSData *certData = [NSData dataWithContentsOfFile:resourcePath];
    SecCertificateRef cert = SecCertificateCreateWithData(NULL, (CFDataRef)certData);
    SecKeyRef key = NULL;
    SecTrustRef trust = NULL;
    SecPolicyRef policy = NULL;

    if (cert != NULL) {
        policy = SecPolicyCreateBasicX509();
        if (policy) {
            if (SecTrustCreateWithCertificates((CFTypeRef)cert, policy, &trust) == noErr) {
                SecTrustResultType result;
                OSStatus res = SecTrustEvaluate(trust, &result);

                //Check the result of the trust evaluation rather than the result of the API invocation.
                if (result == kSecTrustResultProceed || result == kSecTrustResultUnspecified) {
                    key = SecTrustCopyPublicKey(trust);
                }
            }
        }
    }
    if (policy) CFRelease(policy);
    if (trust) CFRelease(trust);
    if (cert) CFRelease(cert);
    return key;
}

要读取私钥,请使用以下代码:

SecKeyRef getPrivateKeyRef() {
    NSString *resourcePath = [[NSBundle mainBundle] pathForResource:@"rsaPrivate" ofType:@"p12"];
    NSData *p12Data = [NSData dataWithContentsOfFile:resourcePath];

    NSMutableDictionary * options = [[NSMutableDictionary alloc] init];

    SecKeyRef privateKeyRef = NULL;

    //change to the actual password you used here
    [options setObject:@"password_for_the_key" forKey:(id)kSecImportExportPassphrase];

    CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);

    OSStatus securityError = SecPKCS12Import((CFDataRef) p12Data,
                                             (CFDictionaryRef)options, &items);

    if (securityError == noErr && CFArrayGetCount(items) > 0) {
        CFDictionaryRef identityDict = CFArrayGetValueAtIndex(items, 0);
        SecIdentityRef identityApp =
        (SecIdentityRef)CFDictionaryGetValue(identityDict,
                                             kSecImportItemIdentity);

        securityError = SecIdentityCopyPrivateKey(identityApp, &privateKeyRef);
        if (securityError != noErr) {
            privateKeyRef = NULL;
        }
    }
    [options release];
    CFRelease(items);
    return privateKeyRef;
}

关于iphone - 如何从 DER/PEM 文件获取 SecKeyRef,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10579985/

相关文章:

iphone - Info.plist 上传中的 CFBundleVersion 显示错误

iphone - - IB 中按钮在 UIToolBar 上的定位 -

rsa - 是否可以使用 BouncyCaSTLe 以 PEM 格式而不是 DER 格式导出公钥?

javascript - Javascript 中的 RSA-OAEP 加密和 Java 中的解密

php - 如何使用 GnuPG 模块确定 PHP 中导入的 OpenPGP key 的指纹?

iphone - 选中时选中的 UItableViewCell 保持蓝色

iphone - iOS - 如何打包 SDK 以不与用户的 SDK 文件名冲突?

openssl - 从 .p12 和 .cer 创建 Apple PEM 证书和 RSA 私钥

encryption - 便宜的 SSL 与昂贵的 SSL

java - 我应该如何将公钥转换为Java中的证书