我正在使用Apple的安全框架.我能够在OS X上签名然后成功验证所有内容,但是当我尝试SecKeyRawVerify在iOS 上使用时,它会因-9809错误而失败.
我玩过各种PKCS填充选项和许多其他属性,但我只是无法正确验证.
请注意,下面的代码可能在整个地方都有泄漏,只是试图让它首先正常运行.
OS X签名代码:
NSData* signData(NSData* plainData, SecKeyRef privateKey) {
CFErrorRef error;
/* Create the transform objects */
SecTransformRef signer = SecSignTransformCreate(privateKey, &error);
if (error) { CFShow(error); exit(-1); }
/* Explicitly set padding type (necessary?) */
SecTransformSetAttribute(signer,
kSecPaddingKey,
kSecPaddingPKCS1Key,
&error);
if (error) { CFShow(error); exit(-1); }
/* Specify digest type */
SecTransformSetAttribute(signer,
kSecDigestTypeAttribute,
kSecDigestSHA1,
&error);
if (error) { CFShow(error); exit(-1); }
/* OS X calculates SHA1 hash/signature for us */
SecTransformSetAttribute(signer,
kSecTransformInputAttributeName,
plainData, …Run Code Online (Sandbox Code Playgroud) 我试图从快速代码中调用Security.framework中的函数.忘记"错误输出"(最后)参数一秒,如果我调用这样的函数:
let accessControlRef = SecAccessControlCreateFlags(
kCFAllocatorDefault,
kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
SecAccessControlCreateFlags.UserPresence,
nil
)
Run Code Online (Sandbox Code Playgroud)
我发现以下错误:
找不到类型为'SecAccessControlCreateFlags'的初始值设定项,它接受类型'(CFAllocator!,CFStringRef,SecAccessControlCreateFlags,nil)'的参数列表
...但是,如果我将代码重新格式化为以下内容:
let allocator:CFAllocatorRef! = kCFAllocatorDefault
let protection:AnyObject! = kSecAttrAccessibleWhenUnlockedThisDeviceOnly
let flags:SecAccessControlCreateFlags = SecAccessControlCreateFlags.UserPresence
let accessControlRef = SecAccessControlCreateWithFlags(
allocator,
protection,
flags,
nil
)
Run Code Online (Sandbox Code Playgroud)
(特定类型-eg,CFAllocatorRef- 取自Xcode自动完成时的函数原型)...它编译没有问题.这是怎么回事?
接下来是错误参数.我应该通过什么?迁移我的Objective-C代码,我很想传递以下变量(&当然是前缀):
var accessControlError:CFErrorRef! = nil
Run Code Online (Sandbox Code Playgroud)
...给出了错误:
无法使用类型'(CFAllocatorRef!,AnyObject!,SecAccessControlCreateFlags,inout CFErrorRef!)的参数列表调用'SecAccessControlCreateWithFlags'
相反,如果我传递了以下变量(再次使用address-of运算符):
var accessControlError:UnsafeMutablePointer<Unmanaged<CFError>?>
Run Code Online (Sandbox Code Playgroud)
(与原型自动完成建议的类型相同),我得到:
无法使用类型'(CFAllocatorRef!,AnyObject!,SecAccessControlCreateFlags,inout UnsafeMutablePointer?>)的参数列表调用'SecAccessControlCreateWithFlags'
......那么,是什么给出的?
编辑:忘记错误参数.我好像在拿地址两次(即指向指针的指针).相反,我应该这样做:
var accessControlError:UnsafeMutablePointer<Unmanaged<CFError>?> = nil
// ^ Already a 'pointer'
let allocator:CFAllocatorRef! = kCFAllocatorDefault
let protection:AnyObject! = kSecAttrAccessibleWhenUnlockedThisDeviceOnly
let flags:SecAccessControlCreateFlags = …Run Code Online (Sandbox Code Playgroud) 我们有一个启动守护进程(必然由于各种原因)以root身份运行,并通过网络与服务器组件通信.它需要对服务进行身份验证,因此在首次获取密码时,我们会将其保存到系统密钥链中.在随后的发布中,我们的想法是从密钥链中检索密码并使用它来验证网络服务.
这一直运行良好,但在macOS 10.12上,现有代码停止工作,我们已经完全不知道如何解决这个问题.归结为:
无论我们是保存新密码还是检索旧密码,我们都会使用以下方法获取对系统密钥链的引用:
SecKeychainCopyDomainDefault(kSecPreferencesDomainSystem, &system_keychain);
Run Code Online (Sandbox Code Playgroud)
我们还禁用了用户交互以获得良好的衡量标准,尽管我们希望它在守护进程的上下文中已经关闭.
SecKeychainSetUserInteractionAllowed(false);
Run Code Online (Sandbox Code Playgroud)
将新密码保存到钥匙串时,我们会使用
OSStatus status = SecKeychainAddInternetPassword(
system_keychain,
urlLength, server_base_url,
0, NULL,
usernameLength, username,
0, NULL,
0,
kSecProtocolTypeAny, kSecAuthenticationTypeAny,
passwordLength, password,
NULL);
Run Code Online (Sandbox Code Playgroud)
这很有用.报告成功,我可以在Keychain Access.app的"系统"钥匙串中看到该项目.
在我们的守护进程的后续运行中检索它是通过以下行完成的:
status = SecKeychainFindInternetPassword(
system_keychain,
urlLength, url,
0, NULL,
usernameLength, username,
0, NULL,
0,
kSecProtocolTypeAny, kSecAuthenticationTypeAny,
&passwordLength, &password_data,
NULL);
Run Code Online (Sandbox Code Playgroud)
不幸的是,errSecAuthFailed由于我们不清楚的原因,这已经开始返回.
我们检查了一些额外的细节以及我们尝试过的东西,但无济于事:
SecKeychainAddInternetPassword,但这似乎没有任何区别.SecKeychainUnlock(),但正如文档所示,这似乎是多余的.Keychain Access.app原因SecKeychainFindInternetPassword()产生errSecItemNotFound,正如你所期望的.所以它绝对可以找到保存的项目,它不允许读取它.钥匙串文档不是很容易阅读,而是部分相当重复.("为了做Y,你需要做Y",但没有提到为什么你想要做Y.)尽管如此,我认为我已经完成并理解了大部分内容.我们特定设置的各个方面都没有详细介绍(从守护程序访问),但似乎很清楚,访问以前由同一个应用程序保存的项目不需要任何特殊授权或身份验证.这与我们所看到的行为直接矛盾.
有任何想法吗?
我想与我的服务器安全地沟通,这就是我在做什么......
NSURLProtectionSpace *protectionSpace = [challenge protectionSpace];
SecTrustRef trust = [protectionSpace serverTrust];
NSURLCredential *credential = [NSURLCredential credentialForTrust:trust];
SecPolicyRef myPolicy = SecPolicyCreateBasicX509();
NSArray * certs = [[NSArray alloc] initWithObjects:(id)certificate,nil]; //certificate is my server's cert.
credential = [NSURLCredential credentialForTrust:trust];
SecTrustSetAnchorCertificates(trust,
(CFArrayRef) [NSArray arrayWithObject:(id) certificate ]);
OSStatus status = SecTrustCreateWithCertificates(certs, myPolicy, &trust);
SecTrustResultType trustResult = 0;
if (status == noErr) {
status = SecTrustEvaluate(trust, &trustResult);
}
NSLog(@"Trust I get: %d", trustResult);
[certs release];
if (trustResult == kSecTrustResultRecoverableTrustFailure) {
NSLog(@"Recoverable Failure");
CFAbsoluteTime trustTime,currentTime,timeIncrement,newTime;
CFDateRef newDate; …Run Code Online (Sandbox Code Playgroud) 所以OS X Keychain有三条信息:
我显然总是知道ServiceName.有没有办法找到该ServiceName的任何已保存用户名?(一旦知道用户名,就很容易找到密码.)
我更喜欢使用一个漂亮的Cocoa包装器,如EMKeychain来做到这一点.但EMKeychain要求UserName获取任何钥匙串项目!
+ (EMGenericKeychainItem *)genericKeychainItemForService:(NSString *)serviceNameString withUsername:(NSString *)usernameString;
如果您需要用户名来查找凭据,您希望如何充分利用钥匙串中的保存凭据?将用户名保存在.plist文件中的最佳做法是什么?
我试图在我的iOS应用程序中实现RSA加密算法,但是当我尝试生成公钥和私钥对时,该函数返回errSecUnimplemented错误.我目前正在使用5.1 SDK并定位到5.1.
我可以不使用此功能,还是在尝试生成该对时设置了错误?
这是密钥生成的代码:
SecKeyRef publicKey, privateKey;
CFDictionaryRef parameters;
const void* keys[] = {kSecAttrKeyType, kSecAttrKeyTypeRSA};
int keySize = 1024;
const void *values[] = {kSecAttrKeySizeInBits, &keySize};
parameters = CFDictionaryCreate(kCFAllocatorDefault, keys, values, 2, NULL, NULL);
OSStatus ret = SecKeyGeneratePair(parameters, &publicKey, &privateKey);
if ( ret == errSecSuccess )
{
NSLog(@"Key success!");
}
else
{
NSLog(@"Key Failure! %li", ret);
}
Run Code Online (Sandbox Code Playgroud) 我正在尝试使用这个类:
http://log.scifihifi.com/post/55837387/simple-iphone-keychain-code
将数据保存到iPhone上的钥匙串.我已经在我的应用程序中包含了头文件和.m文件,并包含了安全框架,但是我仍然得到这些未声明的错误.
我似乎无法在项目中找到任何教程或帮助文件来设置这个类,所以我认为这并不困难.只是给我带来麻烦.
我正在运行3.0 sdk,但我认为这不会对事情产生太大影响.
提前干杯!
我特别考虑在Security框架中使用SecKeyGeneratePair()方法并在params字典中指定[kSecAttrKeyType:kSecAttrKeyTypeEC].
但我无法找到Apple文档中使用的EC曲线.
有没有办法指定使用什么曲线,还是应该导入openssl?