将 SecKeyRef 设备生成的公钥/私钥对保存在磁盘上

Posted

技术标签:

【中文标题】将 SecKeyRef 设备生成的公钥/私钥对保存在磁盘上【英文标题】:Saving SecKeyRef device generated public/private key pair on disk 【发布时间】:2011-08-24 17:29:16 【问题描述】:

我在设备上使用SecKeyGeneratePair() 在设备上生成了一个 RSA 对称密钥对。我有每个键的SecKeyRef struct 指针。那么,如何将SecKeyRef 保存到磁盘?甚至传输它(我也想正确编码也有问题)? Apple 的“证书、密钥和信任服务”指南说明

您可以将您的公钥发送给任何人,然后谁可以使用它来加密数据。

我特别想保存私钥;所以我可以在部署的设备上使用它来解密用公钥加密的数据。

附:我不介意每个键的结果数据是 DER 编码的 ASN.1 还是 base-64;我只需要弄清楚如何从SecKeyRef 中拔出钥匙。我也很清楚 OS X 的 SecKeychainItemExport() 不存在。

【问题讨论】:

【参考方案1】:

您可以使用ios最新的加密API,您可以将密钥保存为NSData并从NSData中检索密钥

SecKeyRef key = <# a key #>;
CFErrorRef error = NULL;
NSData* keyData = (NSData*)CFBridgingRelease(  // ARC takes ownership
                       SecKeyCopyExternalRepresentation(key, &error)
                   );
if (!keyData) 
    NSError *err = CFBridgingRelease(error);  // ARC takes ownership
    // Handle the error. . .

https://developer.apple.com/documentation/security/certificate_key_and_trust_services/keys/storing_keys_as_data?language=objc

【讨论】:

此方案仅适用于iOS10+【参考方案2】:

请参阅证书、密钥和信任服务编程指南的 Encrypting and Decrypting Data 部分,其中包含用于生成、保存和使用公钥/私钥对的代码示例。

【讨论】:

【参考方案3】:

啊,自己找到了答案;您可以使用SecItemCopyMatching() 获取公钥的字节数。

- (NSData *)getPublicKeyBits 
    OSStatus sanityCheck = noErr;
    NSData * publicKeyBits = nil;

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

    // Set the public key query dictionary.
    [queryPublicKey setObject:(id)kSecClassKey forKey:(id)kSecClass];
    [queryPublicKey setObject:publicTag forKey:(id)kSecAttrApplicationTag];
    [queryPublicKey setObject:(id)kSecAttrKeyTypeRSA forKey:(id)kSecAttrKeyType];
    [queryPublicKey setObject:[NSNumber numberWithBool:YES] forKey:(id)kSecReturnData];

    // Get the key bits.
    sanityCheck = SecItemCopyMatching((CFDictionaryRef)queryPublicKey, (CFTypeRef *)&publicKeyBits);

    if (sanityCheck != noErr)
    
        publicKeyBits = nil;
    

    [queryPublicKey release];

    return publicKeyBits;

以上内容来自 Apple 的 CryptoExercise。不确定它是否适用于私钥。

【讨论】:

不。我填写了一份错误报告,但从未得到承认。 在上面的代码中,publicTag 是什么?当我使用SecKeyRef 代替publicTag 时,我收到“属性列表对格式无效:200(属性列表不能包含'SecKey' 类型的对象)”SecKeyRef 是不透明的 RSA 公钥(Apple ) 格式。

以上是关于将 SecKeyRef 设备生成的公钥/私钥对保存在磁盘上的主要内容,如果未能解决你的问题,请参考以下文章

如何使用openssl生成RSA公钥和私钥对 / 蓝讯

将 JSON 公钥/私钥对转换为 rsa.PrivateKey 和 rsa.PublicKey

openssl生成RSA公钥和私钥对

如何使用openssl生成RSA公钥和私钥对

用openssl生成SSL使用的私钥和证书,并自己做CA签名

java中RSA用私钥加密公钥解密问题