使用Apple的安全框架导入/导出RSA SecKeyRef密钥

时间:2015-07-15 06:41:36

标签: ios objective-c security encryption rsa

我正在创建一个使用服务器和客户端之间安全通信的iPhone Objective-C应用程序。我想遵循的协议是这样的:

  1. 使用服务器的公共RSA密钥(硬编码)编译和分发客户端。我们称之为Kspub。 (对于Key Server Public)

  2. 客户端生成随机AES密钥。我们称这个密钥为Kcaes(用于密钥客户端AES)

  3. 客户端使用Kspub加密Kcaes,并生成加密文本:Kspub(Kcaes)

  4. 客户端将Kspub(Kcaes)发送到服务器。

  5. 服务器使用服务器的私钥Kspri解密Kspub(Kcaes)。这恢复了Kcaes。现在,客户端和服务器共享一个通用的AES密钥,Kcaes。

  6. 要验证这一点,服务器会使用Kcaes加密Kcaes。这会产生加密文本Kcaes(Kcaes)。

  7. 服务器将Kcaes(Kcaes)发送给客户端。

  8. 客户端使用Kcaes密钥解密Kcaes(Kcaes)。这产生了Kcaes。如果这与原始Kcaes匹配,则客户端知道它已建立安全连接。

  9. 客户端和服务器现在可以使用对称密钥Kca安全地交换信息。

  10. 我已经实现了服务器端和客户端密钥生成,加密和解密方法。目前,iPhone上生成的密钥对存储在其密钥链中。这是问题所在:

    我似乎无法在Apple的Keychain或Security API中找到从文本文件导入公共RSA密钥的方法。如何通过文本文件导入密钥并将其存储在SecKeyRef对象中?

    谢谢!

2 个答案:

答案 0 :(得分:0)

您通过SecItemAdd执行此操作,传递:

  

包含项目类键值对(Keychain Item Class Keys and Values)和可选属性键值对(Attribute Item Keys and Values)的字典,用于指定项目的属性值。

OSStatus err = SecItemAdd((CFDictionaryRef)
    [NSDictionary dictionaryWithObjectsAndKeys:
     (id)kSecClassKey,         kSecClass,
     kSecAttrKeyTypeRSA,       kSecAttrKeyType,
     keyTagUTF8,               kSecAttrApplicationTag,
     kSecAttrKeyClassPrivate,  kSecAttrKeyClass, 
     keyData,                  kSecValueData,
     nil],
 NULL);

确保要存储和检索的属性完全匹配。

答案 1 :(得分:0)

SecKeyCreateWithData将接受PKCS#1以及x509公钥格式的RSA数据。

因为该问题提到的是文本而不是二进制文件,所以我假定公钥采用标准PEM格式。首先,您要剥离PEM标头和新行:

NSMutableString *pemString = [textFileString mutableCopy];
[pemString replaceOccurrencesOfString:@"-----BEGIN PUBLIC KEY-----" withString:@"" options:NSCaseInsensitiveSearch range:NSMakeRange(0, [pemString length])];
[pemString replaceOccurrencesOfString:@"-----END PUBLIC KEY-----" withString:@"" options:NSCaseInsensitiveSearch range:NSMakeRange(0, [pemString length])];
[pemString replaceOccurrencesOfString:@"\n" withString:@"" options:NSCaseInsensitiveSearch range:NSMakeRange(0, [pemString length])];

现在剩下的是Base64字符串,可以将其解码为二进制数据。我想指出,苹果公司的原生Base64方法不能容忍padding issuesother standards

CFDataRef data = (__bridge CFDataRef) [NSData dataWithBase64EncodedString... // Your preferred base64 method here

现在您可以通过SecKeyRef获得SecKeyCreateWithData

if (data)
{
    CFMutableDictionaryRef dictionary = CFDictionaryCreateMutable(kCFAllocatorDefault, 3, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
    if (dictionary)
    {
        CFDictionarySetValue(dictionary, kSecAttrKeyClass, kSecAttrKeyClassPublic);
        CFDictionarySetValue(dictionary, kSecAttrIsPermanent, kCFBooleanFalse);
        CFDictionarySetValue(dictionary, kSecAttrKeyType, kSecAttrKeyTypeRSA);
        CFErrorRef error = NULL;
        SecKeyRef publicKey = SecKeyCreateWithData(data, dictionary, &error);
        if (publicKey)
        {
            if (error)
            {
                CFShow(error);
                CFRelease(error);
            }
            //...
            CFRelease(publicKey);
        }
        CFRelease(dictionary);
    }
}

您可以在此处保留引用,也可以决定通过SecItemAdd等将其保存在钥匙串中。