secItemCopyMatching返回nil数据 [英] secItemCopyMatching returns nil data

查看:128
本文介绍了secItemCopyMatching返回nil数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

首先,我观看了WWDC 2013关于使用钥匙串保护秘密的会议。我想做一个基本的密码存储。观看了整个视频,但在视频的前10分钟内找到了我需要的内容。这似乎很简单,但我并不完全理解数据编码和检索是如何工作的。

First off, I have watched the WWDC 2013 session on protecting secrets with the keychain. I want to do a basic passcode store. Watched the whole video, but found what I needed in the first 10 minutes of the video. It seems straightforward, but I don't completely understand how the data encoding and retrieval works.

问题:在secItemCopyMatching之后,我检查我的NSData对象以确保它不是在将其转换为NSString之前为零。问题是,它始终是零。下面是我如何保存钥匙串条目或更新,然后是我如何检索它。任何帮助和解释都将非常感激。

PROBLEM: after secItemCopyMatching, I check my NSData object to make sure it is not nil before converting it to a NSString. Problem is, it is always nil. Below is how I'm saving the keychain entry or update, followed by how I'm retrieving it. Any help and explanation would be very much appreciated.

更新(已编辑):
果味极客,感谢您的回复。我使用__bridge更新了下面的代码。我的问题现在归结为,我是否正确存储和检索密码?我有错了还是只有一个?我的NSData实例总是为零。我正在检查返回代码和我的SecItemAdd和SecItemUpdate(当存在keychaing条目时)正常工作。我似乎无法检索存储的数据(密码)的字符串值,以将其与用户输入的密码进行比较。欣赏帮助家伙和女孩。以下是我现在正在做的事情:

UPDATE (EDITED): Fruity Geek, thanks for the response. I've updated my code below using __bridge. My problem now boils down to, am I storing and retrieving the password correctly? Have I got both wrong or just one or the other? My NSData instance is always nil. I am checking returns codes and my SecItemAdd and SecItemUpdate (when the keychaing entry exists) are working correctly. I can't seem to retrieve the string value of the data (passcode) stored to compare it with the passcode entered by the user. Appreciate the help guys and gals. Here is what I am doing now:

更新#2 :(使用Fruity Geek的答案和最终工作版本编辑。我的编辑仅包括对以下代码的更改。)

UPDATE #2: (Edited with Fruity Geek's answers and final working version. My edits only include changes to the code below.)

设置钥匙串条目:

NSData *secret = [_backupPassword dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *query = @{
    (__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword,
    (__bridge id)kSecAttrService: twServiceName,
    (__bridge id)kSecAttrAccount: twAccountName,
    (__bridge id)kSecValueData: secret,
};
OSStatus status =
    SecItemAdd((__bridge CFDictionaryRef)query, NULL);

if (status == errSecDuplicateItem) {
    // this item exists in the keychain already, update it
    query = @{
        (__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword,
        (__bridge id)kSecAttrService: twServiceName,
        (__bridge id)kSecAttrAccount: twAccountName,
    };
    NSDictionary *changes = @{
        (__bridge id)kSecValueData: secret,
    };
    status = SecItemUpdate((__bridge CFDictionaryRef)query, (__bridge CFDictionaryRef)changes);
}

从钥匙串中取回密码:

NSDictionary *query = @{
    (__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword,
    (__bridge id)kSecAttrService: twServiceName,
    (__bridge id)kSecAttrAccount: twAccountName,
    (__bridge id)kSecReturnData: @YES,
};
NSData *data = NULL;
CFTypeRef dataTypeRef = (__bridge CFTypeRef)data;
OSStatus status =
    SecItemCopyMatching((__bridge CFDictionaryRef)query, &dataTypeRef);

NSData *data = (__bridge NSData *)dataTypeRef;

NSString *passcode = @"none";
if (status == errSecSuccess) {
    // we found a keychain entry, set the passcode
    if (data)
        passcode = [NSString stringWithUTF8String:[data bytes]];
}

twServiceName和twAccountName是静态NSStrings。

twServiceName and twAccountName are static NSStrings.

正如我所说,我对__bridge或CFTypeRef所做的并不完全。我查看了苹果文档,这里和其他网站上的大量帖子,但是钥匙串和这些术语对我来说是全新的,我仍然想弄清楚。希望有人在这里可以指出我的错误并帮助我理解。在此先感谢您的帮助。

As I said, I don't quite what I am doing with __bridge or CFTypeRef. I looked through apples docs, numerous posts here and other sites, but keychain and these terms are brand new to me and I'm still trying to figure it out. Hoping someone here can point out my error and help me understand. Thanks in advance for the help.

iOS 7 / Xcode 5

iOS 7 / Xcode 5

推荐答案

您没有任何Core Foundation对象(您没有创建或复制它们)并且您不想保留或释放它们,因此 CFBridgingRelease CFBridgingRetain 不正确。无论何时想要转换为Objective-C对象,都要使用(__ bridge id)

You don't own any of the Core Foundation objects (you didn't create or copy them) and you don't want to retain or release them, so CFBridgingRelease and CFBridgingRetainis incorrect. Use (__bridge id) instead whenever you want to cast to an Objective-C object.

(__bridge id)kSecAttrService

何时使用__bridge与CFBridgingRelease / CFBridgingRetain?

您的数据变量和dataTypeRef是两个不同的指针。在SecItemCopyMatching中只有dataTypeRef填充了数据。在之后,将您的CFTypeRef投射到NSData ,它已被SecItemCopyMatching填充,因此您的数据并非始终为零

Your data variable and dataTypeRef are two distinct pointers. Only the dataTypeRef was filled with data in SecItemCopyMatching. Cast your CFTypeRef to NSData after it has been populated by SecItemCopyMatching so your data isn't always nil

CFTypeRef dataTypeRef = NULL;
OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &dataTypeRef);
NSData *data = (__bridge NSData *)dataTypeRef;

您应该仔细查看所有SecItem函数调用返回的OSStatus。有许多可能的返回代码不成功。在您的情况下,您在SecItemAdd中检测到重复的项目 - 然后将其更新为完全相同的项目(什么都不做)。相反,您应该首先尝试使用SecItemCopyMatching检索它。如果未找到匹配项,请使用SecItemAdd。如果找到匹配项,请使用SecItemUpdate。

You should look more closely at the OSStatus returned by all your SecItem functions calls. There are many possible return codes that are not success. In your case, you are detecting a duplicate item in SecItemAdd - then updating it to the exact same item (doing nothing). Instead, you should try retrieving it first using SecItemCopyMatching. If no match is found, use SecItemAdd. If a match was found, use SecItemUpdate.

来自Apple的示例代码可怕,不是为ARC编写而且令人困惑,但它存在。特别是, writeToKeychain 方法就是您所需要的。 https://developer.apple.com/library/ios/documentation/Security/Conceptual/keychainServConcepts/iPhoneTasks/iPhoneTasks.html#//apple_ref/doc/uid/TP30000897-CH208-SW1

The example code from Apple is terrible, not written for ARC and confusing, but it exists. In particular, the writeToKeychain method is what you need. https://developer.apple.com/library/ios/documentation/Security/Conceptual/keychainServConcepts/iPhoneTasks/iPhoneTasks.html#//apple_ref/doc/uid/TP30000897-CH208-SW1

这篇关于secItemCopyMatching返回nil数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆