如何在钥匙链中保存 NSString 公钥,然后获取它的 SecKeyRef?

发布于 2025-01-06 15:29:29 字数 2291 浏览 3 评论 0原文

我有一个NSString,它应该是公钥。我想将它存储在钥匙串中,然后获取它的 SecKeyRef ,以便在其他安全相关函数中使用它,例如 SecKeyEncrypt 等。

为了存储,我使用SecItemAdd 假设我还有公钥的标识符。我尝试获取持久引用,然后通过此获取带有 SecItemCopyMatching 的 SecKeyRef 。我使用以下两个函数。在将密钥字符串传递给 putKey 之前,我将其转换为 NSData

-(SecKeyRef)putKey:(NSData *)key withIdentifier:(NSString *)identifier 
{
    OSStatus status = noErr;
    SecKeyRef keyRef = nil;
    CFTypeRef persKey = nil;

    NSData * identifierTag = [[NSData alloc] initWithBytes:(const void *)[identifier UTF8String] length:[identifier length]];
    NSMutableDictionary *queryKey = [[NSMutableDictionary alloc] init];

    [queryKey setObject:(__bridge id)kSecClassKey forKey:(__bridge id)kSecClass];
    [queryKey setObject:(__bridge id)kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
    [queryKey setObject:identifierTag forKey:(__bridge id)kSecAttrApplicationTag];
    [queryKey setObject:key forKey:(__bridge id)kSecValueData];
    [queryKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnPersistentRef];

    status = SecItemAdd((__bridge CFDictionaryRef)queryKey, (CFTypeRef *)&persKey);

    if (status == errSecDuplicateItem) NSLog(@"Key %@ already exists in the KeyStore, OSStatus = %ld.", identifier, status);
    else if (status != noErr) NSLog(@"Error putting key %@ in KeyStore, OSStatus = %ld.", identifier, status);

    keyRef = [self getKeyRefWithPersistentKeyRef:persKey];

    return keyRef;
}

- (SecKeyRef)getKeyRefWithPersistentKeyRef:(CFTypeRef)persistentRef
{
    OSStatus sanityCheck = noErr;
    SecKeyRef keyRef = NULL;

    if (persistentRef == NULL) NSLog(@"persistentRef object cannot be NULL.");

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

    // Set the SecKeyRef query dictionary.
    [queryKey setObject:(__bridge id)persistentRef forKey:(__bridge id)kSecValuePersistentRef];
    [queryKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnRef];

    // Get the key reference.
    sanityCheck = SecItemCopyMatching((__bridge CFDictionaryRef)queryKey, (CFTypeRef *)&keyRef);

    return keyRef;
 }

SecItemAdd 成功返回持久密钥引用。

But SecItemCopyMatching returns 0x0. Anyone knows why?

I have a NSString which is supposed to be a public key. I want to store it in the keychain and then get a SecKeyRef of it, in order to use it in other security related functions like SecKeyEncrypt, etc.

For storing I use the SecItemAdd supposing that I also have an identifier for the public key. I tried to get a persistent ref and then with this get a SecKeyRef with SecItemCopyMatching. I use the below two functions. Before I pass the string of key to putKey I converted it to NSData.

-(SecKeyRef)putKey:(NSData *)key withIdentifier:(NSString *)identifier 
{
    OSStatus status = noErr;
    SecKeyRef keyRef = nil;
    CFTypeRef persKey = nil;

    NSData * identifierTag = [[NSData alloc] initWithBytes:(const void *)[identifier UTF8String] length:[identifier length]];
    NSMutableDictionary *queryKey = [[NSMutableDictionary alloc] init];

    [queryKey setObject:(__bridge id)kSecClassKey forKey:(__bridge id)kSecClass];
    [queryKey setObject:(__bridge id)kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
    [queryKey setObject:identifierTag forKey:(__bridge id)kSecAttrApplicationTag];
    [queryKey setObject:key forKey:(__bridge id)kSecValueData];
    [queryKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnPersistentRef];

    status = SecItemAdd((__bridge CFDictionaryRef)queryKey, (CFTypeRef *)&persKey);

    if (status == errSecDuplicateItem) NSLog(@"Key %@ already exists in the KeyStore, OSStatus = %ld.", identifier, status);
    else if (status != noErr) NSLog(@"Error putting key %@ in KeyStore, OSStatus = %ld.", identifier, status);

    keyRef = [self getKeyRefWithPersistentKeyRef:persKey];

    return keyRef;
}

- (SecKeyRef)getKeyRefWithPersistentKeyRef:(CFTypeRef)persistentRef
{
    OSStatus sanityCheck = noErr;
    SecKeyRef keyRef = NULL;

    if (persistentRef == NULL) NSLog(@"persistentRef object cannot be NULL.");

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

    // Set the SecKeyRef query dictionary.
    [queryKey setObject:(__bridge id)persistentRef forKey:(__bridge id)kSecValuePersistentRef];
    [queryKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnRef];

    // Get the key reference.
    sanityCheck = SecItemCopyMatching((__bridge CFDictionaryRef)queryKey, (CFTypeRef *)&keyRef);

    return keyRef;
 }

The SecItemAdd returns successfully a persistent key ref.

But SecItemCopyMatching returns 0x0. Anyone knows why?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

行雁书 2025-01-13 15:29:29

查看 Apple 的加密练习。为了将公钥添加到 KeyChain,需要去掉附加的标头。 Apple 的示例表明就是这样做的,并且代码很容易重用。

Checkout Apple's Crypto Exercise. In order to add a public key to the KeyChain, it is necessary to strip off the header that is attached to it. Apple's example shows doing just that, and the code is easy to reuse.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文