我现在遇到麻烦了。 这些天,我正在研究objc的RSA加密功能。但是当我完成该功能时,我发现我对“钥匙串”存储钥匙一无所知。我检查了Apple文档“在钥匙串中存储密钥”和“获取现有密钥”和“生成新的加密密钥”。并尝试使用SecKeyCopyPublicKey(),SecKeyCreateEncryptedData(、、),SecItemCopyMatching(,),SecKeyCreateRandomKey(,)...……我也尝试在Google上获取一些有用的信息。
但是仍然存在问题。这些是我最近拼凑的完整代码:
AppDelegate.h
//
// AppDelegate.h
// MessagesServer
//
//
#import <Cocoa/Cocoa.h>
#import <Security/Security.h>
@interface AppDelegate : NSObject <NSApplicationDelegate>
@end
AppDelegate.m
//
// AppDelegate.m
// MessagesServer
//
#import "AppDelegate.h"
@interface AppDelegate ()
@property (weak) IBOutlet NSWindow *window;
@end
@implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
NSError * error = nil;
NSData * cipherText = [self encryptionDataUsingLocalRSAKey:[@"Hello! Nice to meet you!" dataUsingEncoding:NSUTF8StringEncoding] error:&error];
if (!cipherText){
NSLog(@"%@", error.description);
} else {
NSError * decryptErr = nil;
NSData * clearText = [self decryptionDataUsingLocalRSAKey:cipherText error:&decryptErr];
if (!clearText){
NSLog(@"%@", decryptErr.description);
} else {
NSLog(@"%@", [[NSString alloc] initWithData:clearText encoding:NSUTF8StringEncoding]);
}
}
}
- (NSData *)encryptionDataUsingLocalRSAKey:(NSData *)data error:(NSError **)encryptErr{
NSError * error = nil;
SecKeyRef privateKey = [self getRSAKeyInLocalWithError:&error];
if (!privateKey){
*encryptErr = error;
return nil;
}
SecKeyRef publicKey = SecKeyCopyPublicKey(privateKey);
CFErrorRef encryptDataErr = nil;
NSData * cipherText = (NSData *)CFBridgingRelease(SecKeyCreateEncryptedData(publicKey, kSecKeyAlgorithmRSAEncryptionOAEPSHA512, (__bridge CFDataRef)data, &encryptDataErr));
if (!cipherText){
*encryptErr = CFBridgingRelease(encryptDataErr);
return nil;
} else {
return cipherText;
}
}
- (NSData *)decryptionDataUsingLocalRSAKey:(NSData *)cipherData error:(NSError **)decryptErr{
NSError * error = nil;
SecKeyRef privateKey = [self getRSAKeyInLocalWithError:&error];
if (!privateKey){
*decryptErr = error;
return nil;
}
CFErrorRef decryptDataErr = nil;
NSData * clearText = (NSData *)CFBridgingRelease(SecKeyCreateDecryptedData(privateKey, kSecKeyAlgorithmRSAEncryptionOAEPSHA512, (__bridge CFDataRef)cipherData, &decryptDataErr));
if (!clearText){
*decryptErr = CFBridgingRelease(decryptDataErr);
return nil;
} else {
return clearText;
}
}
- (SecKeyRef)getRSAKeyInLocalWithError:(NSError **)error{
NSDictionary * query = @{(id)kSecClass: (id)kSecClassKey,
(id)kSecAttrApplicationTag: [@"com.MessageSender.Server.Signing.Key" dataUsingEncoding:NSUTF8StringEncoding],
(id)kSecAttrKeyType: (id)kSecAttrKeyTypeRSA,
(id)kSecAttrKeyClass: (id)kSecAttrKeyClassPrivate,
(id)kSecAttrIsPermanent: @YES,
(id)kSecReturnData: @YES,
(id)kSecAttrKeySizeInBits: @2048,
(id)kSecMatchLimit: (id)kSecMatchLimitOne,
};
SecKeyRef privateKey = nil;
OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, (CFTypeRef *)&privateKey);
if (status != errSecSuccess){
NSError * createError = nil;
BOOL createSuccess = [self createAnRSAKeyWithError:&createError];
if (!createSuccess){
*error = createError;
return nil;
} else {
privateKey = [self getRSAKeyInLocalWithError:nil];
}
}
return privateKey;
}
- (BOOL)createAnRSAKeyWithError:(NSError **)error{
NSDictionary * keyInfo = @{(id)kSecAttrType: (id)kSecAttrKeyTypeRSA,
(id)kSecAttrKeySizeInBits: @2048,
(id)kSecPublicKeyAttrs:
@{(id)kSecAttrLabel: @"MessageSender Server Encryption Key",
(id)kSecAttrIsPermanent: @YES,
(id)kSecAttrApplicationTag: [@"com.MessageSender.Server.Encryption.Key" dataUsingEncoding:NSUTF8StringEncoding],},
(id)kSecPrivateKeyAttrs:
@{(id)kSecAttrLabel: @"MessageSender Server Signing Key",
(id)kSecAttrIsPermanent: @YES,
(id)kSecAttrApplicationTag: [@"com.MessageSender.Server.Signing.Key" dataUsingEncoding:NSUTF8StringEncoding],},};
CFErrorRef createKeyError = nil;
SecKeyRef privateKey = SecKeyCreateRandomKey((__bridge CFDictionaryRef)keyInfo, &createKeyError);
if (!privateKey){
NSError * createKeyErr = CFBridgingRelease(createKeyError);
*error = createKeyErr;
return NO;
} else {
return YES;
}
}
- (void)applicationWillTerminate:(NSNotification *)aNotification {
// Insert code here to tear down your application
}
@end
不幸的是,在这里运行时,系统会引发错误,我用了很长时间的Google搜索,却没有得到答案...
我将不胜感激。谢谢!
答案 0 :(得分:0)
好!我想我已经解决了这个问题! 问题在这里:
NSDictionary * query = @{(id)kSecClass: (id)kSecClassKey,
(id)kSecAttrApplicationTag: [@"com.MessageSender.Server.Signing.Key" dataUsingEncoding:NSUTF8StringEncoding],
(id)kSecAttrKeyType: (id)kSecAttrKeyTypeRSA,
(id)kSecAttrKeyClass: (id)kSecAttrKeyClassPrivate,
(id)kSecAttrIsPermanent: @YES,
(id)kSecReturnData: @YES,
(id)kSecAttrKeySizeInBits: @2048,
(id)kSecMatchLimit: (id)kSecMatchLimitOne,
};
删除“ kSecReturnData”键。 原来,它返回的值不是keyRef,而是NSData! 这是修改后的代码:
NSDictionary * query = @{(id)kSecClass: (id)kSecClassKey,
(id)kSecAttrApplicationTag: [@"com.MessageSender.Server.Signing.Key" dataUsingEncoding:NSUTF8StringEncoding],
(id)kSecAttrKeyType: (id)kSecAttrKeyTypeRSA,
(id)kSecAttrKeyClass: (id)kSecAttrKeyClassPrivate,
(id)kSecAttrIsPermanent: @YES,
(id)kSecAttrKeySizeInBits: @2048,
(id)kSecMatchLimit: (id)kSecMatchLimitOne,
};
它将完美运行。我很高兴,因为我发现了这个问题!