我正在创建一个iPhone Objective-C应用程序,它使用服务器和客户端之间的安全通信。我想遵循的协议是这样的。
客户端被编译并分发了服务器的公共RSA密钥(硬编码)。我们把它叫做Kspub。(代表Key Server Public)
客户端随机生成一个AES密钥。让我们把这个密钥称为Kcaes(Key Client AES的缩写)。
客户端使用Kspub对Kcaes进行加密,并生成加密后的文本。Kspub(Kcaes)
客户端向服务器发送Kspub(Kcaes)。
服务器使用服务器的私钥Kspri对Kspub(Kcaes)进行解密。这样就恢复了Kcaes。现在客户端和服务器都共享一个共同的AES密钥Kcaes。
为了验证这一点,服务器使用Kcaes对Kcaes进行加密。这将产生加密的文本Kcaes(Kcaes)。
服务器将Kcaes(Kcaes)发送给客户端。
客户端使用Kcaes密钥解密Kcaes(Kcaes)。这将产生Kcaes。如果这与原始的Kcaes相匹配,那么客户端知道它已经建立了一个安全连接。
现在客户端和服务器可以使用对称密钥Kcaes安全地交换信息。
我已经实现了服务器端和客户端的密钥生成、加密和解密方法。目前,iPhone上生成的密钥对被存储在它的密钥链中。问题是这样的。
我似乎无法在苹果的钥匙链或安全API中找到一种方法来从文本文件中导入一个公共RSA密钥。我如何通过文本文件导入密钥并将其存储在SecKeyRef对象中?
谢谢!我正在创建一个iPhone的Objective API。
你可以通过以下方式来实现 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);
确保要存储和检索的属性完全匹配。
SecKeyCreateWithData
将接受PKCS#1的RSA数据以及x509公钥格式。
因为问题中提到的是文本文件而不是二进制文件,我假设公钥是标准的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方法是不能容忍的。填充问题 和 其他标准.
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
等等。