我将密码存储到iOS钥匙串中,以后再检索它们以在我的应用程序中实现“记住我”(自动登录)功能。
我围绕Security.framework功能(SecItemCopyMatching(),等等)实现了自己的包装器,直到iOS 12为止,它的运行都像是一种魅力。
现在,我正在测试我的应用程序不会与即将推出的iOS 13兼容,瞧瞧:
SecItemCopyMatching() 总是回来 .errSecItemNotFound
...即使我以前已经存储了要查询的数据。
我的包装是用静态特性方便地提供的价值类kSecAttrService和kSecAttrAccount组装查询字典时:
class LocalCredentialStore {
private static let serviceName: String = {
guard let name = Bundle.main.object(forInfoDictionaryKey: "CFBundleName") as? String else {
return "Unknown App"
}
return name
}()
private static let accountName = "Login Password"
// ...
Run Code Online (Sandbox Code Playgroud)
我将使用以下代码将密码插入钥匙串:
/*
- NOTE: protectWithPasscode is currently always FALSE, so the password
can later be retrieved programmatically, i.e. without user interaction.
*/ …Run Code Online (Sandbox Code Playgroud) Apple的OS X 文档谈到了使用SecItemImport获取的问题SecKeyRef.函数签名如下所示:
OSStatus SecItemImport (
CFDataRef importedData,
CFStringRef fileNameOrExtension,
SecExternalFormat *inputFormat,
SecExternalItemType *itemType,
SecItemImportExportFlags flags,
const SecItemImportExportKeyParameters *keyParams,
SecKeychainRef importKeychain,
CFArrayRef *outItems
);
Run Code Online (Sandbox Code Playgroud)
以下代码将尝试加载包含单个RSA密钥的PKCS12字节数组:
#include <Security/Security.h>
#include <Security/SecKey.h>
#include <CoreFoundation/CoreFoundation.h>
int main(void) {
CFArrayRef array = NULL;
SecItemImportExportKeyParameters params;
SecExternalItemType itemType = kSecItemTypeUnknown;
SecExternalFormat format = kSecFormatUnknown;
params.flags = kSecKeyNoAccessControl;
UInt8 bytes[] = {
0x30, 0x82, 0x2, 0x1e, 0x2, 0x1, 0x3, 0x30, 0x82, 0x1, 0xe8, 0x6, 0x9, 0x2a, 0x86, 0x48, 0x86, 0xf7,
0xd, 0x1, …Run Code Online (Sandbox Code Playgroud) 似乎钥匙串文件(带扩展名.keychain)通常会有一个与之关联的不可见文件,位于同一目录中.
这个不可见的文件总是具有以下属性:
0444(对所有用户都是只读的).它的名称.fl后跟8个十六进制字符.例如:
.fl043D1EDD
.fl947E1BDB
.fl9FAF0136
.fl12663120
.fl8E6EFC6C
.flCF600F4B
.fl1D8ECE61
.fl0D1D1BA9
.fl79E88CD1
.fl62323D2F
.fl75262C83
.fl652F188E
Run Code Online (Sandbox Code Playgroud)可以删除不可见的文件,但是当下次修改钥匙串的内容时,将使用相同的名称重新创建不可见的文件.
以下是使用Keychain Access实用程序演示的一些步骤:
使用security终端中的Apple 工具操作钥匙串时会创建相同的不可见文件:
创建一个新的钥匙串.还会创建一个不可见的文件.
$ cd ~/Desktop/
$ ls -1a
.
..
$ /usr/bin/security create-keychain ~/Desktop/Test.keychain
$ ls -1a
.
..
.fl1BCE4B9A
Test.keychain
Run Code Online (Sandbox Code Playgroud)删除不可见的文件.
$ rm .fl1BCE4B9A
$ ls -1a …Run Code Online (Sandbox Code Playgroud)我正在使用数字证书在我的应用程序中签署数据文件.当SecKeyRawVerify使用-9809返回调用时,下面的代码片段失败.这是在iPhone上运行.我甚至无法准确确定此错误代码的含义
先前的安全框架调用加载并创建SecTrustRef,从中获取公钥似乎没问题 - 没有错误.唯一的小问题是调用SecTrustEvaluate返回a kSecTrustResultUnspecified,但我认为这是因为我使用的策略是SecPolicyCreateBasicX509调用返回的样板.
非常感谢任何帮助或见解.
谢谢
SecKeyRef keyRef = SecTrustCopyPublicKey (trustRef);
fileURL = [[NSBundle mainBundle] URLForResource:@"data" withExtension:@"txt"];
NSData *data = [NSData dataWithContentsOfURL:fileURL];
fileURL = [[NSBundle mainBundle] URLForResource:@"data" withExtension:@"sgn"];
NSData *signature = [NSData dataWithContentsOfURL:fileURL];
NSLog(@"Hash block size = %zu",SecKeyGetBlockSize(keyRef));
status = SecKeyRawVerify (keyRef,
kSecPaddingPKCS1SHA1,
(const uint8_t *)[data bytes],
(size_t)[data length],
(const uint8_t *)[signature bytes],
(size_t)[signature length]
);
Run Code Online (Sandbox Code Playgroud) 许多用户空间CSPRNG都有一个问题,在fork(2)这之后,两个不同进程可能会返回相同的随机字节流.
从观察来看dtruss,很明显,SecRandomCopyBytes至少是播种/dev/random,但它是否以一种可以安全使用的方式进行fork()?
使用以下源代码:
#include <Security/Security.h>
int main() {
uint8_t data[8];
SecRandomCopyBytes(kSecRandomDefault, 8, data);
SecRandomCopyBytes(kSecRandomDefault, 8, data);
printf("%llu\n", *(uint64_t *)data);
}
Run Code Online (Sandbox Code Playgroud)
我得到以下内容dtruss(删除了无关的内容):
open("/dev/random\0", 0x0, 0x7FFF900D76F5) = 3 0
read(0x3, "\b\2029a6\020+\254\356\256\017\3171\222\376T\300\212\017\213\002\034w\3608\203-\214\373\244\177K\177Y\371\033\243Y\020\030*M\3264\265\027\216r\220\002\361\006\262\326\234\336\357F\035\036o\306\216\227\0", 0x40) = 64 0
read(0x3, "\223??3\263\324\3604\314:+\362c\311\274\326\a_Ga\331\261\022\023\265C\na\211]\356)\0", 0x20) = 32 0
Run Code Online (Sandbox Code Playgroud) 我试图通过打开附加到电子邮件的.cer/.p12,使用用户已存储的证书/身份验证我的应用程序上的用户身份.证书显示在手机的设置应用程序"组态配置文件"组下.
有没有办法使用iphone SDK访问证书(我曾尝试使用安全框架,但似乎只能访问存储在应用程序密钥链中的证书或其组中的其他密钥链)?
是否可以在使用SecKeyGeneratePair?生成RSA密钥对时更改默认公共指数(e)?
我知道65537是一个很好的默认值,所以这只是一个关于它是否在技术上可行的问题.
我正在尝试从具有相同标识符(相同配置文件)的另一个应用程序访问应用程序设置的钥匙串数据。我使用此链接来实现此目的。
钥匙串数据的保存正确发生,我得到以下语句的 errSecSuccess(在模拟器和设备中)
OSStatus status = SecItemAdd((CFDictionaryRef)dictionary, NULL);
Run Code Online (Sandbox Code Playgroud)
到目前为止一切顺利,但是当我尝试取回我的应用程序 A 保存在另一个应用程序 B 中的凭据时,它在模拟器和设备中的工作方式有所不同。
在 iOS 模拟器 6.1 中,以下语句的状态为“0”。
OSStatus status = SecItemCopyMatching((CFDictionaryRef)searchDictionary, &foundDict);
Run Code Online (Sandbox Code Playgroud)
在任何 iOS 设备中,我的状态都是“-25300”。
我知道这些是安全框架中的错误代码:
//errSecSuccess = 0, /* No error. */
//errSecUnimplemented = -4, /* Function or operation not implemented. */
//errSecParam = -50, /* One or more parameters passed to a function where not valid. */
//errSecAllocate = -108, /* Failed to allocate memory. */
//errSecNotAvailable = -25291, /* No keychain is available. You …Run Code Online (Sandbox Code Playgroud) 由于某种原因,我无法让这个简单的钥匙串代码工作。
//Let's create an empty mutable dictionary:
NSMutableDictionary *keychainItem = [NSMutableDictionary dictionary];
NSString *username = self.nwUsernameTxtFld.text;
NSString *password = self.passwordTxtFld.text;
//Populate it with the data and the attributes we want to use.
keychainItem[(__bridge id)kSecClass] = (__bridge id)kSecClassInternetPassword; // We specify what kind of keychain item this is.
keychainItem[(__bridge id)kSecAttrAccessible] = (__bridge id)kSecAttrAccessibleWhenUnlocked; // This item can only be accessed when the user unlocks the device.
keychainItem[(__bridge id)kSecAttrServer] = @"http://www.myawesomeservice.com";
keychainItem[(__bridge id)kSecAttrAccount] = username; //Our username.
if(SecItemCopyMatching((__bridge CFDictionaryRef)keychainItem, NULL) == noErr) …Run Code Online (Sandbox Code Playgroud) 我需要更新钥匙串条目的kSecAttrAccessible。我不需要更新实际数据,只需更新可访问性属性即可。
首先,我尝试找到该项目以确保我的查询字典良好:
sanityCheck = SecItemCopyMatching((__bridge CFDictionaryRef)(queryPrivateKey), (void *)&privateKeyRef);
Run Code Online (Sandbox Code Playgroud)
此行成功找到我要查找的商品(返回码为0)。
然后,使用相同的查询更新kSecAttrAccessible属性:
if (sanityCheck == noErr && privateKeyRef != nil) {
// found it, update accessibility
NSMutableDictionary *updatedAttributes = [[NSMutableDictionary alloc] init];
updatedAttributes[(__bridge id)kSecAttrAccessible] = (__bridge id)kSecAttrAccessibleAlways;
OSStatus updateItemStatus = SecItemUpdate((__bridge CFDictionaryRef)queryPrivateKey, (__bridge CFDictionaryRef)updatedAttributes);
}
Run Code Online (Sandbox Code Playgroud)
此时,updateItemStatus为-50(paramErr)。
我看了一下这个线程:是否可以更新钥匙串项目的kSecAttrAccessible值?
但是我的问题是不同的。即使我将kSecValueData添加到我的代码,它也会返回-50updatedAttributes。此外,文档还指出,我们仅需要为iOS 4和更早版本添加kSecValueData。我支持iOS 7及更高版本,所以这不是我的问题。
有人可以指出我在这里想念的东西吗?非常感谢。
ios ×7
keychain ×5
macos ×4
c ×1
certificate ×1
cryptography ×1
flock ×1
ios13 ×1
ios7 ×1
iphone ×1
locking ×1
objective-c ×1
prng ×1
security ×1