简体   繁体   English

将私钥(SecRefKey)转换为 NSData 或 Base64

[英]Converting a PrivateKey (SecRefKey) into NSData or Base64

I have a p12 file, from which I extract the PrivateKey, PublicKey both as SecKeyRef and the certificate as SecCertificateRef.我有一个 p12 文件,从中提取 PrivateKey、PublicKey 作为 SecKeyRef 和作为 SecCertificateRef 的证书。

The P12 file have a ECDSA PrivateKey that I need to use to sign data (ECC). P12 文件有一个 ECDSA PrivateKey,我需要用它来签署数据 (ECC)。

So I'm using a suggested library: https://github.com/ricmoo/GMEllipticCurveCrypto所以我使用了一个建议的库: https : //github.com/ricmoo/GMEllipticCurveCrypto

But I need to feed the library with the keys on Base64 or NSData, I can't feed SecKeyRef.但是我需要用 Base64 或 NSData 上的密钥提供库,我无法提供 SecKeyRef。 I managed to extract the NSData for the publicKey using the methods provided here , it works.我设法使用此处提供的方法为 publicKey 提取 NSData,它有效。

But I can't find any way to convert a SecRefKey that points to a privateKey to NSData.但是我找不到任何方法将指向私有密钥的 SecRefKey 转换为 NSData。 Any ideas on how to do this, OR, sign and verify data in iOS using ECC with SecKeyRefs.关于如何做到这一点的任何想法,或者,使用带有 SecKeyRefs 的 ECC 在 iOS 中签名和验证数据。


For reference, this method converts the P12 into iOS SecRefs:作为参考,此方法将 P12 转换为 iOS SecRefs:

- (BOOL)storeDetailsForP12CertificateData:(NSData *)certData password:(NSString*)pass identifier:(NSString*)identifier{    
    SecKeyRef publicKey, privateKey;
    SecCertificateRef certRef;

    //Extract keys and Certificate
    NSMutableDictionary * options = [[NSMutableDictionary alloc] init];
    [options setObject:pass forKey:(id)kSecImportExportPassphrase];

    CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
    OSStatus securityError = SecPKCS12Import((CFDataRef) certData,
                                             (CFDictionaryRef)options, &items);

    CFDictionaryRef identityDict = CFArrayGetValueAtIndex(items, 0);
    SecIdentityRef identityApp =
    (SecIdentityRef)CFDictionaryGetValue(identityDict,
                                         kSecImportItemIdentity);

    assert(securityError == noErr);

    //get private key
    SecIdentityCopyPrivateKey(identityApp, &privateKey);

    //get certificate
    SecIdentityCopyCertificate(identityApp, &certRef);

    //evaluate certificate.
    CFArrayRef certs = CFArrayCreate(kCFAllocatorDefault, (const void **) &certRef, 1, NULL);
    SecPolicyRef policy = SecPolicyCreateBasicX509();
    SecTrustRef trust;
    SecTrustCreateWithCertificates(certs, policy, &trust);
    (CFRelease(certs));
    SecTrustResultType trustResult;
    SecTrustEvaluate(trust, &trustResult);

    //get publickey
    publicKey = SecTrustCopyPublicKey(trust);

    //clean memory
    (CFRelease(trust));
    (CFRelease(policy));

    if (!publicKey || !privateKey || !certRef) {
        return NO;
    } else {
        KeyData *details = [[KeyData alloc] init];
        details.publicKey = publicKey;
        details.privateKey = privateKey;
        details.certificate = certRef;
        details.fileData = certData;

        return YES;
    }
}

Looks like you simply need to use SecKeyCopyExternalRepresentation :看起来你只需要使用SecKeyCopyExternalRepresentation

/*!
    @function SecKeyCopyExternalRepresentation
    @abstract Create an external representation for the given key suitable for the key's type.
    @param key The key to be exported.
    @param error On error, will be populated with an error object describing the failure.
    See "Security Error Codes" (SecBase.h).
    @result A CFData representing the key in a format suitable for that key type.
    @discussion This function may fail if the key is not exportable (e.g., bound to a smart card or Secure Enclave).
    The format in which the key will be exported depends on the type of key:
    * kSecAttrKeyTypeRSA                 PKCS#1 format
    * kSecAttrKeyTypeECSECPrimeRandom    SEC1 format (www.secg.org)
 */
CFDataRef _Nullable SecKeyCopyExternalRepresentation(SecKeyRef key, CFErrorRef *error)

Note that CFDataRef is toll-free bridged to NSData , so you can easily convert them.请注意, CFDataRef是免费桥接到NSData ,因此您可以轻松地转换它们。

To export a private key for SEC, you need to retrieve SecKey and convert it to base64 (and format the result with 64 characters max per line. Here the Swift 5 code:要为 SEC 导出私钥,您需要检索 SecKey 并将其转换为 base64(并将结果格式化为每行最多 64 个字符。这里是 Swift 5 代码:

var keyResult: CFTypeRef?
var statusCode = SecItemCopyMatching(attributes as CFDictionary, &keyResult)
if statusCode == noErr && keyResult != nil {
       if let privateKey = SecKeyCopyExternalRepresentation(keyResult as! SecKey, nil) as Data? {
            print("Private Key: \((privateKey.base64EncodedString()))")
       }
       return (keyResult as! SecKey)
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM