secitemadd和secitemcopymatching返回错误代码34018(errsecmissingentitlement)

17 篇文章 0 订阅
4 篇文章 1 订阅

转自:http://www.91r.net/ask/20344255.html

secitemadd和secitemcopymatching返回错误代码34018(errsecmissingentitlement)

Sometimes when I run an application on device from Xcode I would try to access the keychain but fail due to error -34018. This doesn't match any of the documented keychain error codes and can't be consistently reproduced. (happens maybe 30% of the time, and it's not clear to me why it happens). What makes debugging this problem very difficult is the total lack of documentation. Any idea what causes this and how to fix it? I'm using Xcode 5 and running iOS 7.0.4 on device.

There is an open issue about this here: https://github.com/soffes/sskeychain/issues/52

EDIT: Adding keychain access code per request

I'm using the SSKeychain library for interfacing with keychain. Here's the snippet.

#define SERVICE @"default"

@implementation SSKeychain (EXT)

+ (void)setValue:(NSString *)value forKey:(NSString *)key {
    NSError *error = nil;
    BOOL success = NO;
    if (value) {
        success = [self setPassword:value forService:SERVICE account:key error:&error];
    } else {
        success = [self deletePasswordForService:SERVICE account:key error:&error];
    }
    NSAssert(success, @"Unable to set keychain value %@ for key %@ error %@", value, key, error);
    if (!success) {
        LogError(@"Unable to set value to keychain %@", error);
    }
    LogTrace(@"Will set keychain account %@. is to nil? %d", key, value == nil);
    if (value == nil)
        LogWarn(@"Setting keychain %@ to nil!!!", key);
}

+ (NSString *)valueForKey:(NSString *)key {
    NSError *error = nil;
    NSString *value = [self passwordForService:SERVICE account:key error:&error];
    if (error && error.code != errSecItemNotFound) {
        NSAssert(!error, @"Unable to retrieve keychain value for key %@ error %@", key, error);
        LogError(@"Unable to retrieve keychain value for key %@ error %@", key, error);
    }
    return value;
}

+ (BOOL)removeAllValues {
    LogInfo(@"Completely Reseting Keychain");
    return [[self accountsForService:SERVICE] all:^BOOL(NSDictionary *accountInfo) {
        return [self deletePasswordForService:SERVICE account:accountInfo[@"acct"]];
    }];
}

@end

Vast majority of the time it's just fine. Sometimes I'll hit the assertion failures where I'm unable to either write to or read from keychain, causing critical assertion failure.

2017年01月17日38分46秒

This thread seems to contain the solution if the problem exits in your unit-test target.

https://devforums.apple.com/message/917498#917498

Basically you have to codesign your .xcttest folder by adding the following as a run script in your test target.

codesign --verify --force --sign "$CODE_SIGN_IDENTITY" "$CODESIGNING_FOLDER_PATH"

I got a lot of -34018 errors when testing my keychain on the device and this managed to fix it.

If the problem does not exist in your test target this is probably not the solution.

2017年01月16日38分46秒

After inspecting the source code. I have noticed that the keychain features are accessed through a security daemon that runs in its own process (separated from the app process).

Your app and the securityd process 'talk' together through a technology called XPC.

If necessary, the securityd is launched via the well-known launchd command by XPC. You can probably check that the daemon is running in the Activity Monitor App (if running in Simulator of course) and that its parent process is launchd.

My guess here is that it is possible that for any unknown reason the security daemon fails to start or do it too slowly and is not ready when you try to use it.

Maybe you could think on how to pre-launch the daemon.

I apologize for not being more precise. I hope it could help you to go a bite further in your investigations.

2017年01月16日38分46秒

An answer here, from Apple:

UPDATE: We have finally been able to reproduce the -34018 error on iOS 8.3. This is the first step in identifying the root cause and then coming up with a fix.

As usual, we can't commit to a release timeframe, but this has affected many developers and we really want to get this resolved.

Earlier I suggested adding a small delay in application:didFinishLaunchingWithOptions and applicationDidBecomeActive: before accessing the keychain as a workaround. However, that doesn't actually appear to help. That means that there's no known workaround at this time other than relaunching the app.

The issue appears to be related to memory pressure, so perhaps being more aggressive in handling memory warnings may alleviate the problem

https://forums.developer.apple.com/thread/4743#14441

UPDATE

OK, here’s the latest.
This is a complex problem with multiple possible causes:

  • Some instances of the problem are caused by incorrect app signing. You can easily distinguish this case because the problem is 100% reproducible.
  • Some instances of the problem are caused by a bug in how iOS supports app development (r. 23,991,853). Debugging this was complicated by the fact that another bug in the OS (r. 23,770,418) masked its effect, meaning the problem only cropped up when the device was under memory pressure. We believe these problems were resolved in iOS 9.3.
  • We suspect that there may be yet more causes of this problem.

So, if you see this problem on a user device (one that hasn’t been talked to by Xcode) that’s running iOS 9.3 or later, please do file a bug report about it. Try to include the device system log in your bug report (I realise that can be tricky when dealing with customer devices; one option is to ask the customer to install Apple Configurator, which lets them view the system log). And if you do file a bug, please post your bug number, just for the record.

On behalf of Apple I’d like to thank everyone for their efforts in helping to track down this rather horrid issue. Share and Enjoy

https://forums.developer.apple.com/thread/4743#126088

2017年01月16日38分46秒

I’m observing similar behavior after building and running my code in Xcode 6 beta with iOS 8 SDK (it’s working correctly with Xcode 5 / iOS 7). In Xcode 6, in iOS Simulator SecItemCopyMatching always returns -34018. It started working after turning on the “Keychain Sharing” in Capabilities tab.

However I have another issue. I’m developing static library, that is used by (among others) Demo application. The above solution works for Demo application project, but when I try to unit test my static library project, I have exactly the same error. And the problem is that my static library project doesn’t have the Capabilities tab (as it’s not the standalone application).

I’ve tried the solution posted here by JorgeDeCorte, with codesigning in the test target, but it doesn’t work for me.

2017年01月16日38分46秒

I just had the same issue on the simulator running 7.1 & 8.0. While doing some digging, I noticed that the Apple sample app had KeyChain Sharing turned on for its target capabilities. I turned it on for my app which resulted in creating an entitlement file that I left with the default values and now I am not getting anymore -34018 errors. This is not ideal but I will live the KeyChain sharing option for now.

2017年01月16日38分46秒

I have fixed this problem (I think). I had a wildcard provisioning profile on my device that showed it did not have a valid signing identity. I also had a provisioning profile for my app that was valid. When I deleted the wildcard profile, I stopped getting the -34018 errors.

I also made sure that the code signing identity and provisioning profile listed in the Code Signing section of the Build Settings of the target were identical to the one for the app (not the generic "iPhone Developer" one)

2017年01月16日38分46秒

Try disabling all breakpoints when launching the app from Xcode. You can enable them afterwards.

(None of the above workarounds worked for me)

2017年01月16日38分46秒

Codesigning a .xctest bundle isn't as easy as it sounds in some cases. Principally JorgeDeCorte is right with hisanswer that the given short line as a Run Script is enough for most of the devs.

codesign --verify --force --sign "$CODE_SIGN_IDENTITY" "$CODESIGNING_FOLDER_PATH"

But when you have multiple certificates in your keychain this will fail with the following line

iPhone Developer: ambiguous (matches "iPhone Developer: Your Name (ABC123DEF45)" and "iPhone Developer: Your Name (123ABC456DE)"

A solution to get the right certificate even with multiple ones is this short script. For sure this is not ideal, but as of my knowledge you have no chance to get the certificate that Xcode found and uses for signing your .app.

echo "codesign --verify --force --sign \"$CODE_SIGN_IDENTITY\" \"$CODESIGNING_FOLDER_PATH\""
IDENTITIES=`security find-identity -v -s "Code Signing" | grep "iPhone Developer" | awk '{ print $2 }'`

for SHA in $IDENTITIES; do
    codesign --verify --force --sign $SHA "$CODESIGNING_FOLDER_PATH"
    if [ $? -eq 0 ]; then
        echo "Matching identity found: $SHA"
        exit 0
    fi
done;

exit 1

2017年01月16日38分46秒

I was getting -34018 error in my app (iOS 8.4) very rarely. After some investigation I've found that this issue occurs when the app requests data from keychain too often.
For example, in my situation it was two read requests for one specific key at the same time from different application modules.
To fix that I've just added caching this value in memory

2017年01月16日38分46秒

I got bitten by this, too and had no success with any of the other workarounds. I then cleaned up my provisioning profiles on the devices itself by deleting all of them related to my app as well as all the wildcard profiles (this seems to be the point). To do this, go to the "Devices" Window in Xcode and right-click your (connected) phone:

Click on "Show provisioning profiles" and delete the related ones, and especially the team profiles:

including the ones with the asterisk. After reinstallation the app, everything went back to normal.

2017年01月16日38分46秒

I was having the same problem, out of the blue, running on a test device with Xcode 6.2, iPhone 6, iOS 8.3. To be clear, this was not experienced while running Xcode tests, but rather while running the actual app on my device. In the simulator it was fine, and running on the app itself it had been perfectly fine until recently.

I tried all of the suggestions I could find here, such as removing the provisioning profiles on my device (I removed ALL of them), temporarily enabling the Keychain Sharing capability in my project (even though we don't really need that), making sure my development account in Xcode was totally refreshed with all of the certificates and provisioning profiles, etc. Nothing helped.

Then I temporarily changed the accessibility level from kSecAttrAccessibleAfterFirstUnlock tokSecAttrAccessibleAlwaysThisDeviceOnly, ran the app, and it worked fine and was able to write to the Keychain. Then I changed it back to kSecAttrAccessibleAfterFirstUnlock, and the problem seems to have gone away "permanently."

2017年01月16日38分46秒

In iOS 9 I turned off Address Sanitizer and it started working on the device.

2017年01月16日38分46秒

The only solution that worked for me was first storing nil for the specified key, and then storing my new value with a separate operation. It would fail due to error -34018 if I attempted to overwrite the existing value. But as long as I stored nil first, then the updated value would be stored successfully immediately afterwards.

2017年01月16日38分46秒

I met this -34018 issue today when running SecItemDelete API. What I did to fix this is: 1. Following @k1th solution http://stackoverflow.com/a/33085955/889892 2. Run the SecItemDelete in main thread(Previously it's read from main thread, so just align this with deleting).

Sorry it comes back again :(

2017年01月16日38分46秒


翻译

转自:http://www.jianshu.com/p/b6a10e1abef2


前言:

前段时间做RSA加密的时候,在调试的过程中,经常失败,后台接收到的加密参数为空,但是这种不是经常发生,而是随机的。经过测试,发现,这种情况在单独使用真机、模拟器的时候都不发生,只有在真机连接xcode进行调试的时候才会发生。

追踪:

在笔者打了N多断点之后,终于找到了问题发生的根源。在RSA加密的类中,有这么一段代码:

 CFTypeRef persistKey = nil;
 OSStatus status = SecItemAdd((__bridge CFDictionaryRef)publicKey, &persistKey);
 if (persistKey != nil){
  CFRelease(persistKey);
 }
 if ((status != noErr) && (status != errSecDuplicateItem)) {

  return nil;
 }

 [publicKey removeObjectForKey:(__bridge id)kSecValueData];
 [publicKey removeObjectForKey:(__bridge id)kSecReturnPersistentRef];
 [publicKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnRef];
 [publicKey setObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];

 // Now fetch the SecKeyRef version of the key
 SecKeyRef keyRef = nil;
 status = SecItemCopyMatching((__bridge CFDictionaryRef)publicKey, (CFTypeRef *)&keyRef);

 if(status != noErr){
  return nil;
 }
 return keyRef;

在模拟器上测试的时候:


屏幕快照 2016-04-20 下午3.02.06.png

真机连接Xcode的时候:


屏幕快照 2016-04-20 下午3.03.43.png

问题就出在:

 OSStatus status = SecItemAdd((__bridge CFDictionaryRef)publicKey, &persistKey);

stack overflow发现有的人也遇到了类似的问题,现总问题结如下:
1.当我在连接着Xcode的真机设备上运行app的时候,我试图获取钥匙串,却由于-34018的错误导致运行失败。缺乏钥匙串错误代码开发文档,而且也很难重现此错误(发生的概率大概30%,我也不知道为什么发生)。由于缺乏相关的文档,所以调试这种错误就变得非常困难。为什么会出现此错误,如何解决?xcode5、ios7

解决方案

方案一:
你不得不通过在你的test target中添加下面的代码作为运行脚本来签名你的 .xcttest文件夹

codesign --verify --force --sign "$CODE_SIGN_IDENTITY" "$CODESIGNING_FOLDER_PATH"

方案二:
在查看源码 之后,我注意到钥匙串通过一种安全进程(区别于app的进程)获取。
app和安全进程通过一项称之为XPC的技术进行对话安全进程经由XPC的启动命令启动。你可以发现真机(模拟器也是如此)app的安全进程正在运行,它的父进程也已经启动。
我猜测,有可能某些未知的原因导致安全进程启动失败或者启动太慢,使得你使用它的时候还没有准备好。
或许,你可以考虑如何重启安全进程

方案三,来自苹果官方回复:

1.我们终于能够在ios8.3里重现-34018错误,这是我们查找问题根源和修复问题的第一步。

可是,我们并不能给出确切的解决时间,但是由于已经影响了很多的开发者,我们也非常希望尽快解决。

作为变通方案,我建议在在didFinishLaunchingWithOptions 和applicationDidBecomeActive: 两个方法之前添加一个小的延时给获取字符串争取一点时间。然而,好像并没有明显的作用,这就意味着除了重启app确实没有更好的解决方法。

这个问题似乎和内存压力也有一定的关系,在解决这个问题的时候,要积极处理内存警告的问题。

更新:
这个复杂的问题有几种可能的原因

  • 一些情况下是由于不正确的app签名造成的,你可以很清楚的辨别这种原因,因为它100%可以重现。
  • 有些情况下这种问题的造成是由于iOS支持app开发环境中的一个bug
    造成的。由于os中的另一个bug掩盖了它的影响,排查这个问题非常困难,这就意味着这个问题在内存面临巨大压力的时候会突然出现,我们相信这个问题在ios9.3中已经解决。
  • 我们猜测可能有其他的原因造成了这个问题

所以,如果你在运行ios9.3及以后系统的用户设备上(未和Xcode链接)遇到此问题,请记录此bug并报告给我们。)

方案四:
我的app(iOS8.4)现在极少遇到 -34018的错误,在做过一些调查之后,我发现当app频繁的从钥匙串请求数据的时候就会造成这种问题。例如,在同一时间,在不同的加载模块,两次读同一个specific key 的值。为了解决这个问题,我在内存中缓存了这个值。

方案五:
其他的方式对我都没有用,我清空了我设备上所有的配置文件,以及一些通配符配置文件(这些文件似乎是重点),为了这么做,去window的Devices,然后右击你的(连接)的iphone:


THffv.png


点击"Show provisioning profiles"删除相关的文件,尤其是team相关的配置文件包括带*号的文件,然后重新导入。


jyQl1.png

方案六:

我在Xcode6.2 、iphone6、ios8.3环境下,在测试设备上也出现这种问题。更清楚的说,在运行Xcode tests的时候这种情况没有发生,在我的真机,模拟器上都是正常的。

以上的方式都对我无效。

我临时的改变了获取的方式从
kSecAttrAccessibleAfterFirstUnlock 到kSecAttrAccessibleAlwaysThisDeviceOnly,运行app,完美运行,且可以写到钥匙串,然后我再改回到kSecAttrAccessibleAfterFirstUnlock,问题似乎永久性的解决了。

总结:

非常遗憾,笔者这个问题仍旧没有解决,希望笔者摘录的几种解决方式给大家一点思路。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值