Objective c 将客户端标识复制到Mac OS上的私钥链 背景
我正在使用客户身份的大型多平台库中工作。要求是应用程序私下维护客户机标识,并且可以从系统存储导入客户机标识(在Mac OS默认密钥链的情况下) 所以基本上API必须包括以下内容Objective c 将客户端标识复制到Mac OS上的私钥链 背景,objective-c,swift,macos,security,keychain,Objective C,Swift,Macos,Security,Keychain,我正在使用客户身份的大型多平台库中工作。要求是应用程序私下维护客户机标识,并且可以从系统存储导入客户机标识(在Mac OS默认密钥链的情况下) 所以基本上API必须包括以下内容 从默认密钥链设置客户端标识 设置客户端标识表单文件(系统keychian不应看到它) 删除客户端标识(这不应破坏其他应用程序) 如果将从默认密钥链中删除标识(例如使用密钥链访问),则我的应用程序不应受到影响 基本问题 起初,我计划将身份存储在一些私人加密文件中,但事实证明,苹果API不允许在没有密钥链的情况下导入客户
- 从默认密钥链设置客户端标识
- 设置客户端标识表单文件(系统keychian不应看到它)
- 删除客户端标识(这不应破坏其他应用程序)
- 如果将从默认密钥链中删除标识(例如使用密钥链访问),则我的应用程序不应受到影响
NSDictionary *options =
@{
(id)kSecImportExportPassphrase:password.stringValue,
(id)kSecImportExportKeychain:(__bridge id)keychain,
};
CFArrayRef arrayResult = NULL;
OSStatus status = SecPKCS12Import((CFDataRef)pkcs12,
(CFDictionaryRef)options,
&arrayResult);
if (status != errSecSuccess)
现在的问题是如何将客户身份从默认密钥复制到私有密钥链
下面是我用来创建钥匙链的代码:
- (void)setupOpenMyKeychain
{
NSString *keychainPath = [self keychainPath];
NSString *pass = @"dasndiaisdfs"; // used only for testing
OSStatus status = SecKeychainCreate(keychainPath.UTF8String,
(UInt32)strlen(pass.UTF8String),
pass.UTF8String,
NO,
NULL,
&keychain);
if (status == errSecDuplicateKeychain)
{
status = SecKeychainOpen(keychainPath.UTF8String, &keychain);
if (status == errSecSuccess)
{
status = SecKeychainUnlock(keychain,
(UInt32)strlen(pass.UTF8String),
pass.UTF8String,
TRUE);
if (status != errSecSuccess)
{
[self showOSStatusFailureAlert: status forAction: @"Unlock failure"];
}
}
}
if (status != errSecSuccess)
{
[self showOSStatusFailureAlert: status forAction: @"Open/Create failure"];
}
}
现在,我在默认密钥链中有SecIdentityRef和SecCertificate(在CFArrayRef中),我想将其复制到我的自定义密钥链:
- (NSData *)persistantRefFor: (id)item
{
CFTypeRef result = NULL;
NSDictionary *dic =
@{
(id)kSecValueRef:(id)item,
(id)kSecReturnPersistentRef:(id)kCFBooleanTrue,
//(id)kSecUseKeychain:(__bridge id)keychain,
};
OSStatus status = SecItemCopyMatching((CFDictionaryRef)dic,
&result);
if (status != errSecSuccess)
{
[self showOSStatusFailureAlert: status
forAction: @"Failed to find reference"];
return nil;
}
return (__bridge_transfer NSData *)result;
}
-(OSStatus)copyItemWithPersistantRef:(NSData *)persistantReference
{
SecKeychainItemRef item = NULL;
OSStatus result = SecKeychainItemCopyFromPersistentReference((__bridge CFDataRef)persistantReference, &item);
if (result != errSecSuccess)
{
[self showOSStatusFailureAlert: result forAction: @"Get item from reference"];
return result;
}
CFAutorelease(item);
SecKeychainRef soruceKeychain = NULL;
result = SecKeychainItemCopyKeychain(item, &soruceKeychain);
if (result == errSecSuccess)
{
if (soruceKeychain == keychain)
{
CFRelease(soruceKeychain);
// item is already in desired keychain
return result;
}
} else {
[self showOSStatusFailureAlert: result forAction: @"Fetching source keychain"];
return result;
}
SecAccessRef access = NULL;
result = SecKeychainCopyAccess(keychain, &access);
if (result != errSecSuccess)
{
[self showOSStatusFailureAlert: result forAction: @"Get Access object"];
// return result;
} else {
CFAutorelease(access);
}
SecKeychainItemRef itemCopy = NULL;
result = SecKeychainItemCreateCopy(item, keychain, access, &itemCopy);
if (result != errSecSuccess)
{
[self showOSStatusFailureAlert: result forAction: @"Create copy in private keychain"];
return result;
}
CFAutorelease(itemCopy);
NSLog(@"Copied item %@", itemCopy);
NSData *copyPersistantRef = [self persistantRefFor: (__bridge id)itemCopy];
NSLog(@"Old persisntatn reference %@\n"
"New persisntatn reference %@\n"
"%@", persistantReference, copyPersistantRef,
[persistantReference isEqualToData: copyPersistantRef]?@"SAME":@"DIFFRENT");
return result;
}
- (IBAction)copyIdentityToPrivateKeychain:(id)sender
{
if (!identity)
{
return;
}
NSData *perRef = [self persistantRefFor: (__bridge id)identity];
OSStatus status = [self copyItemWithPersistantRef: perRef];
if (status != errSecSuccess)
{
[self showOSStatusFailureAlert: status forAction: @"Copy Identity has failed"];
}
}
尝试将SecCertificateRef复制到我的私钥链时。发生了以下事情:
NSData*copyPersistantRef=[self-peristantRefor:(_桥id)itemCopy]代码>失败。我无法获取对复制项目的永久引用。没有此引用,我无法在应用程序启动时加载正确的证书
错误:0xFFFF9D28-25304指定的项不再有效。它可能已从钥匙链中删除。
这是一个用于快速测试的工具。使用
SecPKCS12Import
,而不是secitemport
。将kSecFormatPKCS12
作为inputFormat传递,kSecItemTypeAggregate
作为itemType传递(以要求标识或kSecItemTypeUnknown
,它将尝试为您检测该类型),并将importKeychain设置为NULL
,这将阻止导入到keychain