https://www.jianshu.com/p/c1e9bffc76f4

最近项目的需求用到RSA的加密解密,并且需要把公钥信息保存到Keychain里面,网上很多文章都是用Keychain保存账号密码什么的,自己在实现保存的公钥过程中也踩了不少坑。现在来整理一下实现的方法。

首先肯定是先要导入 Security

  1. import Security

然后定义一个常量 Identifier

  1. // 密钥唯一标示
  2. fileprivate let publicKeyIdentifier = "com.hhh.publicKey"
  3. fileprivate let privateKeyIdentifier = "com.hhh.privateKey"
  4. fileprivate let publicKeyTag = publicKeyIdentifier.data(using: .utf8)!
  5. fileprivate let privateKeyTag = privateKeyIdentifier.data(using: .utf8)!

实现一个把SecKey转换成Data的方法

  1. private static func getKeyDataFrom(secKey: SecKey, tag: Data) -> Data {
  2. var data: Data?
  3. var query = [String: Any]()
  4. query[kSecClass as String] = kSecClassKey
  5. query[kSecAttrApplicationTag as String] = tag
  6. query[kSecAttrKeyType as String] = kSecAttrKeyTypeRSA
  7. var attributes = query
  8. attributes[kSecValueRef as String] = secKey
  9. attributes[kSecReturnData as String] = true
  10. var result: CFTypeRef?
  11. let status = SecItemAdd(attributes as CFDictionary, &result)
  12. if status == errSecSuccess {
  13. data = result as? Data
  14. SecItemDelete(query as CFDictionary)
  15. }
  16. return data!
  17. }

这个方法的原理其实就是先把SecKey存到Keychain里面然后再读取出Data类型的数据

接下来就是实现存到Keychain的方法

  1. // keySize 就是RSA密钥的长度
  2. // isPrivate 判断存储的是否为私钥(true为私钥、false为公钥)
  3. static func saveRSAKeyToKeychain(key: SecKey, keySize: size_t, isPrivate: Bool) {
  4. var saveDictionary = [String: Any]()
  5. let keyClass = isPrivate ? kSecAttrKeyClassPrivate : kSecAttrKeyClassPublic
  6. // 设置keychain字典
  7. saveDictionary[kSecClass as String] = kSecClassKey
  8. saveDictionary[kSecAttrKeyType as String] = kSecAttrKeyTypeRSA
  9. saveDictionary[kSecAttrApplicationTag as String] = isPrivate ? privateKeyTag : publicKeyTag
  10. saveDictionary[kSecAttrKeyClass as String] = keyClass
  11. saveDictionary[kSecValueData as String] = getKeyDataFrom(secKey: key, tag: isPrivate ? privateKeyTag : publicKeyTag)
  12. saveDictionary[kSecAttrKeySizeInBits as String] = keySize
  13. saveDictionary[kSecAttrEffectiveKeySize as String] = keySize
  14. saveDictionary[kSecAttrCanDerive as String] = kCFBooleanFalse
  15. saveDictionary[kSecAttrCanEncrypt as String] = kCFBooleanTrue
  16. saveDictionary[kSecAttrCanDecrypt as String] = kCFBooleanTrue
  17. saveDictionary[kSecAttrCanVerify as String] = kCFBooleanTrue
  18. saveDictionary[kSecAttrCanSign as String] = kCFBooleanFalse
  19. saveDictionary[kSecAttrCanWrap as String] = kCFBooleanTrue
  20. saveDictionary[kSecAttrCanUnwrap as String] = kCFBooleanFalse
  21. saveDictionary[kSecAttrApplicationLabel as String] = isPrivate ? privateKeyIdentifier : publicKeyIdentifier
  22. // 删除旧数据
  23. SecItemDelete(saveDictionary as CFDictionary)
  24. let status = SecItemAdd(saveDictionary as CFDictionary, nil)
  25. assert(status == errSecSuccess, "keychain存储密钥失败")
  26. }

最后就是实现从Keychain取出密钥信息的方法

  1. // isPrivate 判断存储的是否为私钥(true为私钥、false为公钥)
  2. static func getRSAKeyFromKeychain(isPrivate: Bool) -> SecKey! {
  3. var queryDictionary = [String: Any]()
  4. let keyClass = isPrivate ? kSecAttrKeyClassPrivate : kSecAttrKeyClassPublic
  5. queryDictionary[kSecClass as String] = kSecClassKey
  6. queryDictionary[kSecAttrKeyType as String] = kSecAttrKeyTypeRSA
  7. queryDictionary[kSecAttrApplicationTag as String] = isPrivate ? privateKeyTag : publicKeyTag
  8. queryDictionary[kSecAttrKeyClass as String] = keyClass
  9. queryDictionary[kSecReturnRef as String] = kCFBooleanTrue
  10. queryDictionary[kSecAttrApplicationLabel as String] = isPrivate ? privateKeyIdentifier : publicKeyIdentifier
  11. var key: CFTypeRef?
  12. let status = SecItemCopyMatching(queryDictionary as CFDictionary, &key)
  13. if status == errSecSuccess {
  14. // 强转SecKey类型
  15. return key as! SecKey
  16. }
  17. assert(false, "keychain读取密钥失败")
  18. }

因为在开头我们已经定义了公钥私钥的 Identifier 所有我们只需要判断存/取的是私钥还是公钥就可以将密钥信息进行读写操作。

作者:小天枢丶
链接:https://www.jianshu.com/p/c1e9bffc76f4

Swift语言操作KeyChain

https://blog.csdn.net/liulegend/article/details/51504592

2016年05月26日 09:53:28 liulegend 阅读数:3093

关于利用KeyChain保存信息到iphone上,网上有一些信息,但往往有各种问题。尤其是更新KeyChain信息时,常常遇到错误代码-50。苹果在对开发者的支持力度上与微软的差距不是一般的大。还好有stackoverflow.com这个平台,可以看到一些其他人碰到的类似问题和处理方式,虽然没有找到满意的答复,但参考多方的代码总算把程序调通了。现分享如下:

1、引用Security:

import Security

2、添加KeyChain:

var addQuery : [NSString : AnyObject] = [

kSecClass : kSecClassGenericPassword,

kSecAttrService : "MyService",

kSecAttrLabel : "My UUID",

kSecAttrAccount : "MyUsername",

kSecValueData : "12345678".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)!

]

let result = SecItemAdd(addQuery, nil)

if result == errSecSuccess {

//操作成功处理

}

else {

//操作失败处理

}

3、获取KeyChain内容

var requestQuery : [NSString : AnyObject] = [

kSecClass : kSecClassGenericPassword,

kSecAttrService : "MyService",

kSecReturnAttrbutes : true,

kSecReturnData : true

]

var requestResult : AnyObject?

let err = SecItemCopyMatching(requestQuery, &requestResult)

if err == errSecSuccess {

if let results = requestResult as? [NSString : AnyObject],

let username = results[lSecAttrAccount] as? String,

let passdata = results[kSecValueData] as? NSData,

let password = NSString(data:passdata, encoding:NSUTF8StringEncoding) as? String {

//获取成功后的处理

}

}

else if err == errSecItemNotFound {

//未获取到信息的处理

}

else {

//其他错误的处理

}

4、更新KeyChain

var updateQuery : [NSString : AnyObject] = [

kSecClass : kSecClassGenericPassword,

kSecAttrService : "MyService",//非必需,建议加上

kSecAttrLabel : "My UUID",//非必需,建议加上

kSecAttrAccount : "MyUsername"//非必需,建议加上

]

var updateValue : [NSString : AnyObject] = [

kSecValueData : "87654321".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)!

]

let err = SecItemUpdate(updateQuery, updateValue)

if err == errSecSuccess {

//成功处理

}

else {

//失败处理

}

5、删除KeyChain

var query : [NSString : AnyObject] = [

kSecClass : kSecClassGenericPassword,

kSecAttrService : "MyService"

]

let status = SecItemDelete(query)

if status == errSecSuccess {

//删除成功处理

}

else {

//删除失败处理

}

以上代码在Xcode7.3.1及iphone 6 plus 9.3.2上验证成功。

82-Swift之密码管理(Keychain)的介绍和使用

https://www.jianshu.com/p/31e5654166db

2017.11.21 14:25 字数 505 阅读 1309评论 1喜欢 1

引言

App的开发中,用户登录的模块是必不可少的。用户登录一次之后,就可以使用自动登录功能。自动登录需要知道用户的账号和密码。那么用户的账户和密码是保密性的,为实现App的自动登录功能,我们要稳妥的管理好用户的账号和密码的安全。所以 Keychain 就被使用的上了。下面将给你介绍 Keychain 是什么、如何使用等。友情链接:Object-C 版的密码管理 Keychain 的连接地址 iOS的密码管理系统 Keychain的介绍和使用

Keychain 是什么?

Keychain 是苹果公司 Mac OS(也包含 Mac OSX) 中的密码管理系统。

Keychain 的作用是什么?

Keychain 可以包含许多种类型的数据:密码(包括网站、FTP服务器、SSH账户、网络共享、无线网络、群组软件、加密磁盘镜像),私钥,电子证书、加密笔记等。

Keychain 的四个方法的介绍

1、数据的存储方法

@available(iOS 2.0, *)

public func SecItemAdd(_ attributes: CFDictionary, _ result: UnsafeMutablePointer<CoreFoundation.CFTypeRef?>?) -> OSStatus

@ attributes  : 要存储的数据。

@ result : 存储数据后,返回的指向该数据的引用。

2、根据查询条件获取数据

@available(iOS 2.0, *)

public func SecItemCopyMatching(_ query: CFDictionary, _ result: UnsafeMutablePointer<CoreFoundation.CFTypeRef?>?) -> OSStatus

@ query  :  获取数据的查询条件。

@ result  :  查询后获取到数据的引用。

3、更新数据

@available(iOS 2.0, *)

public func SecItemUpdate(_ query: CFDictionary, _ attributesToUpdate: CFDictionary) -> OSStatus

@ query : 要更新数据的查询条件。

@ attributesToUpdate : 要更新的数据内容。

4、删除数据

@available(iOS 2.0, *)

public func SecItemDelete(_ query: CFDictionary) -> OSStatus

@ query : 删除数据的查询条件。

总结,以上四个方法,就是 Keychain 的增、删、改、查的四个基本方法。这四个方法基本满足大部分App的使用需求。

Keychain 的整理和封装为一个类: KeychainManager.swift

KeychainManager.swift 的完整代码展示:

//

//  KeychainManager.swift

//  KeyChain

//

//  Created by MAC on 2017/11/20.

//  Copyright © 2017年 NetworkCode小贱. All rights reserved.

//

import UIKit

class KeychainManager: NSObject {

// TODO: 创建查询条件

class func createQuaryMutableDictionary(identifier:String)->NSMutableDictionary{

// 创建一个条件字典

let keychainQuaryMutableDictionary = NSMutableDictionary.init(capacity: 0)

// 设置条件存储的类型

keychainQuaryMutableDictionary.setValue(kSecClassGenericPassword, forKey: kSecClass as String)

// 设置存储数据的标记

keychainQuaryMutableDictionary.setValue(identifier, forKey: kSecAttrService as String)

keychainQuaryMutableDictionary.setValue(identifier, forKey: kSecAttrAccount as String)

// 设置数据访问属性

keychainQuaryMutableDictionary.setValue(kSecAttrAccessibleAfterFirstUnlock, forKey: kSecAttrAccessible as String)

// 返回创建条件字典

return keychainQuaryMutableDictionary

}

// TODO: 存储数据

class func keyChainSaveData(data:Any ,withIdentifier identifier:String)->Bool {

// 获取存储数据的条件

let keyChainSaveMutableDictionary = self.createQuaryMutableDictionary(identifier: identifier)

// 删除旧的存储数据

SecItemDelete(keyChainSaveMutableDictionary)

// 设置数据

keyChainSaveMutableDictionary.setValue(NSKeyedArchiver.archivedData(withRootObject: data), forKey: kSecValueData as String)

// 进行存储数据

let saveState = SecItemAdd(keyChainSaveMutableDictionary, nil)

if saveState == noErr  {

return true

}

return false

}

// TODO: 更新数据

class func keyChainUpdata(data:Any ,withIdentifier identifier:String)->Bool {

// 获取更新的条件

let keyChainUpdataMutableDictionary = self.createQuaryMutableDictionary(identifier: identifier)

// 创建数据存储字典

let updataMutableDictionary = NSMutableDictionary.init(capacity: 0)

// 设置数据

updataMutableDictionary.setValue(NSKeyedArchiver.archivedData(withRootObject: data), forKey: kSecValueData as String)

// 更新数据

let updataStatus = SecItemUpdate(keyChainUpdataMutableDictionary, updataMutableDictionary)

if updataStatus == noErr {

return true

}

return false

}

// TODO: 获取数据

class func keyChainReadData(identifier:String)-> Any {

var idObject:Any?

// 获取查询条件

let keyChainReadmutableDictionary = self.createQuaryMutableDictionary(identifier: identifier)

// 提供查询数据的两个必要参数

keyChainReadmutableDictionary.setValue(kCFBooleanTrue, forKey: kSecReturnData as String)

keyChainReadmutableDictionary.setValue(kSecMatchLimitOne, forKey: kSecMatchLimit as String)

// 创建获取数据的引用

var queryResult: AnyObject?

// 通过查询是否存储在数据

let readStatus = withUnsafeMutablePointer(to: &queryResult) { SecItemCopyMatching(keyChainReadmutableDictionary, UnsafeMutablePointer($0))}

if readStatus == errSecSuccess {

if let data = queryResult as! NSData? {

idObject = NSKeyedUnarchiver.unarchiveObject(with: data as Data) as Any

}

}

return idObject as Any

}

// TODO: 删除数据

class func keyChianDelete(identifier:String)->Void{

// 获取删除的条件

let keyChainDeleteMutableDictionary = self.createQuaryMutableDictionary(identifier: identifier)

// 删除数据

SecItemDelete(keyChainDeleteMutableDictionary)

}

}

上面展示的代码已经注释非常详细了,就不在多介绍了。如果还有不了解的地方可以查看iOS版本的Keychain,连接如下:iOS的密码管理系统 Keychain的介绍和使用

KeychainManager.swift 类的测试和使用

1、测试代码

// 存储数据

let saveBool = KeychainManager.keyChainSaveData(data: "我期待的女孩" as Any, withIdentifier: KeyChain)

if saveBool {

print("存储成功")

}else{

print("存储失败")

}

// 获取数据

let getString = KeychainManager.keyChainReadData(identifier: KeyChain) as! String

print(getString)

// 更新数据

let updataBool = KeychainManager.keyChainUpdata(data: "眼睛像云朵", withIdentifier: KeyChain)

if updataBool {

print("更新成功")

}else{

print("更新失败")

}

// 获取更新后的数据

let getUpdataString = KeychainManager.keyChainReadData(identifier: KeyChain) as! String

print(getUpdataString)

// 删除数据

KeychainManager.keyChianDelete(identifier: KeyChain)

// 获取删除后的数据

let getDeleteString = KeychainManager.keyChainReadData(identifier: KeyChain)

print(getDeleteString)

2、测试结果的展示

DAB86C95-248D-45B7-B9B6-D748DB7F9BE1.png

下载Demo 的方法

iOS Keychain,SSKeychain,使用 理解 原理

 

我的邮件:m4email@163.com 如果有这篇文章对您有帮助就点下推荐或者随意评论一个呗,谢谢谢谢,随便转载,标明出处就好。

Keychain 使用? ---为了实用最大化我觉得我应该直接先说使用!

当然是使用第三方库啦:sskeychain 3000+星星的库不开玩笑。github地址:https://github.com/soffes/sskeychain

导入完之后首先,编译一下有无错。

如果是自己手动导入:

1.把SSKeychain.h SSKeychain.m SSKeychainQuery.h SSKeychainQuery.m 复制到工程

2.添加Security.framework 怎么添加?点一下那个+

3.SSKeychain.h有错?把SSKeychain.h 中的#import <SSKeychain/SSKeychainQuery.h> 换成 #import <Foundation/Foundation.h> #import "SSKeychainQuery.h" 吧。

还有错?作为小白我的也不知道了,发我邮件一起讨论吧。

接下来演示4个过程

基本说明:储存的数据有三个 1.服务名(这个方便对账号密码进行分类)2.账号3.密码 而这三个数据都是NSString (如果要存其他类型呢,请看后面吧)

所用到的API :

添加和更新都用这个: + (BOOL)setPassword:(NSString *)password forService:(NSString *)serviceName account:(NSString *)account ;

查询密码:+ (NSString *)passwordForService:(NSString *)serviceName account:(NSString *)account;

删除:+ (BOOL)deletePasswordForService:(NSString *)serviceName account:(NSString *)account;

1.添加一条钥匙    (这个钥匙的信息 由 服务名+账号+密码 组成)

记得添加头文件

#import "SSKeychain.h"

#import "SSKeychainQuery.h"

//先定义一下要用的东东

NSString *serviceName= @"com.keychaintest.data";

NSString *account = @"m4abcd";

NSString *password = @"12345678";

//加入钥匙串!

if ([SSKeychain setPassword:password forService:serviceName account:account]) {

NSLog(@"success !");

}

说明:就是这么简单咯。

2.查询

1.查询某service 下 count 的密码并且打印出来:

  NSLog(@"%@",[SSKeychain passwordForService:serviceName account:account]);

2.查询service下所有钥匙:

NSArray *keys = [SSKeychain accountsForService:serviceName];

这是我的输出:

2016-03-04 15:08:43.785 keychaintest[31342:4403403] (

        {

        acct = m4abcd;

        agrp = test;

        cdat = "2016-03-03 07:10:58 +0000";

        mdat = "2016-03-04 07:08:43 +0000";

        pdmn = ak;

        svce = "com.keychaintest.data";

        sync = 0;

        tomb = 0;

    }

)

说明:返回的结果为数组,数组成员就是我们查询的钥匙,这里只有一个钥匙,而钥匙信息以字典的形式构建的,键acct 就是count,键svce 就是serviceName。密码在哪里?用方法1去取吧骚年!

3.查询本appkeychain的所有钥匙

  NSArray *keys = [SSKeychain allAccounts];

3.更新

if([SSKeychain setPassword:@"321321" forService:serviceName account:account]){

    NSLog(@"set success!");

  }

4.删除 

if([SSKeychain deletePasswordForService:serviceName account:account]){

    NSLog(@"delete success!");

  }

说明:删除就是把这一条钥匙删除哦,不是只删除密码!

另外的说明:如果你的password 是NSData

查询: + (NSData *)passwordDataForService:(NSString *)serviceName account:(NSString *)account;

设置or更新:+ (BOOL)setPasswordData:(NSData *)password forService:(NSString *)serviceName account:(NSString *)account;

下面开始浅浅的理解还有对苹果API进行一点点说明吧

1.Keychain 是什么?

keychain 就是放钥匙柜子!就是苹果提供给我们的一个保险柜。

这篇文章仅针对iOS。

在iOS中每个APP 都有属于自己的Keychain,最常用就是保存用户的账户和密码,就是记住密码,放在这里很安全(苹果负责帮我们加密再存起来,如果出了问题怪他咯!),假如用NSUserDefault 保存这些秘密数据,生成的plist文件(就放在那个Library/Preferences 下)容易被拿到,而且还要自己做加密。

特性:1.当app删除了,又再次重新安装,这个保险柜里的信息还存在哦。 所以当你的某女同学登了APP并保存了密码,你重装了APP,如果不删除记录,你女票还是可以发现的。

   2.安全!作为小白的我并不知道它实际上是存在哪里的。

2.Keychain 组成?

1.组成部分由  {N个标签(属性) + 一个重要数据} 组成!

2.结构可以看成是一个字典的形式大概是这样的: @{@"属性key1":@"属性值1",@"属性keyN":@"属性值N",@"valueData":@数据}

3.内容说明:

一个重要数据:就是密码password!

N个标签:也是属性,都是用来表明这条钥匙的,如我们的serviceName ,account 都是属性,他们对应的键为 kSecAttrAccount 和 kSecAttrAccount,还有系统给我们加的创建时间,修改时间等还有label,type,port,你自己打开文件进去看看吧,这些标签的任务就是来表明这条钥匙是独一无二的。

3.原始API操作

先来看看几个API

添加钥匙:        OSStatus SecItemAdd(CFDictionaryRef attributes, CFTypeRef * __nullable CF_RETURNS_RETAINED result)

查询密码与查询标签:     OSStatus SecItemCopyMatching(CFDictionaryRef query, CFTypeRef * __nullable CF_RETURNS_RETAINED result)

更新钥匙信息:             OSStatus SecItemUpdate(CFDictionaryRef query, CFDictionaryRef attributesToUpdate)

删除钥匙:        OSStatus SecItemDelete(CFDictionaryRef query)

先说明一下 这些API的关键在于1.是理解和配置好这个操作字典 2.注意返回的OSStatus 状态 3.CF对象与OC 之间的bridge

1.先来一发查找

过程:

1.(关键)先配置一个操作字典内容有:

kSecAttrService(属性),kSecAttrAccount(属性) 这些属性or标签是查找的依据

kSecReturnData(值为@YES 表明返回类型为data),kSecClass(值为kSecClassGenericPassword 表示重要数据为“一般密码”类型) 这些限制条件是返回结果类型的依据

2.然后用查找的API 得到查找状态和返回数据(密码)

3.最后如果状态成功那么将数据(密码)转换成string 返回

//用原生的API 实现查询密码

- (NSString *)passwordForService:(nonnull NSString *)service account:(nonnull NSString *)account{

//生成一个查询用的 可变字典

NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithCapacity:4];

[dict setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass]; //表明为一般密码可能是证书或者其他东西

[dict setObject:service forKey:(__bridge id)kSecAttrService];    //输入service

[dict setObject:account forKey:(__bridge id)kSecAttrAccount];  //输入account

[dict setObject:@YES forKey:(__bridge id)kSecReturnData];     //返回Data

//查询

OSStatus status = -1;

CFTypeRef result = NULL;

status = SecItemCopyMatching((__bridge CFDictionaryRef)dict,&result);//核心API 查找是否匹配 和返回密码!

if (status != errSecSuccess) { //判断状态

return nil;

}

//返回数据

NSString *password = [[NSString alloc] initWithData:(__bridge_transfer NSData *)result encoding:NSUTF8StringEncoding];//转换成string

return password;

}

说明:其实关键就在于这个操作字典的配置上!

2.添加&更新

说明:当添加的时候我们一般需要判断一下当前钥匙串里面是否已经存在我们要添加的钥匙。如果已经存在我们就更新好了,不存在再添加,所以这两个操作一般写成一个函数搞定吧。

过程关键:1.检查是否已经存在 构建的查询用的操作字典:kSecAttrService,kSecAttrAccount,kSecClass(标明存储的数据是什么类型,值为kSecClassGenericPassword 就代表一般的密码)

   2.添加用的操作字典: kSecAttrService,kSecAttrAccount,kSecClass,kSecValueData

   3.更新用的操作字典1(用于定位需要更改的钥匙):kSecAttrService,kSecAttrAccount,kSecClass

        操作字典2(新信息)kSecAttrService,kSecAttrAccount,kSecClass ,kSecValueData

//用原生的API 添加一条钥匙

-(BOOL)addItemWithService:(NSString *)service account:(NSString *)account password:(NSString *)password{

//先查查是否已经存在

//构造一个操作字典用于查询

NSMutableDictionary *searchDict = [[NSMutableDictionary alloc]initWithCapacity:4];

[searchDict setObject:service forKey:(__bridge id)kSecAttrService];                         //标签service

[searchDict setObject:account forKey:(__bridge id)kSecAttrAccount];                         //标签account

[searchDict setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass];//表明存储的是一个密码

OSStatus status = -1;

CFTypeRef result =NULL;

status = SecItemCopyMatching((__bridge CFDictionaryRef)searchDict, &result);

if (status == errSecItemNotFound) {                                              //没有找到则添加

NSData *passwordData = [password dataUsingEncoding:NSUTF8StringEncoding];    //把password 转换为 NSData

[searchDict setObject:passwordData forKey:(__bridge id)kSecValueData];       //添加密码

status = SecItemAdd((__bridge CFDictionaryRef)searchDict, NULL);             //!!!!!关键的添加API

}else if (status == errSecSuccess){                                              //成功找到,说明钥匙已经存在则进行更新

NSData *passwordData = [password dataUsingEncoding:NSUTF8StringEncoding];    //把password 转换为 NSData

NSMutableDictionary *dict = [[NSMutableDictionary alloc] initWithDictionary:searchDict];

[dict setObject:passwordData forKey:(__bridge id)kSecValueData];             //添加密码

status = SecItemUpdate((__bridge CFDictionaryRef)searchDict, (__bridge CFDictionaryRef)dict);//!!!!关键的更新API

}

return (status == errSecSuccess);

}

其他操作的重要都在操作字典上-_-! 有特殊的东东遇到了再写上!

Swift保存RSA密钥到Keychain的更多相关文章

  1. RSA密钥生成与使用

    RSA密钥生成与使用 openssl生成工具链接:http://pan.baidu.com/s/1c0v3UxE 密码:uv48 1. 打开openssl密钥生成软件打开 openssl 文件夹下的  ...

  2. Java与.NET兼容的RSA密钥持久化方法

    默认情况下,.NET生成的RSA密钥对可以用XML或字节流来保存,而JAVA中生成的RSA密钥对只能用字节流来保存.而它们的字节流格式不同,就导致Java中生成的RSA密钥对不能在.NET中使用,而. ...

  3. [Linux] 在 Linux CLI 使用 ssh-keygen 生成 RSA 密钥

    RSA 是一种公钥加密算法,在 1977 年由麻省理工学院的 Ron Rivest, Adi Shamir, Leonard Adleman 三人一起提出,因此该算法命名以三人姓氏首字母组合而成. S ...

  4. RSA密钥之C#格式与Java格式转换

    前言 最近由于项目需求,服务端由c#编写,客户端由java编写.通信数据使用RSA非对称加密.但是java和c#生成的密钥格式是不一样的,所以需要转换格式才可以正常使用.网上搜到使用java进行格式转 ...

  5. RSA密钥,JAVA与.NET之间转换

    最近在做银联的一个接口,用到RSA签名,悲剧来了,.net用的RSA密钥格式和JAVA用的不一样 .net为XML格式 <RSAKeyValue><Modulus>53Knuj ...

  6. JAVA,NET RSA密钥格式转换

    JAVA和NET RSA密钥格式相互转换(公钥,私钥) 做了一个小项目遇到java和.net非对称加密问题,java的公钥和私钥就直接是一个字符串的形式展示的,但是.net是以xml简单包裹形式展示的 ...

  7. Atitit.rsa密钥生成器的attilax总结

    Atitit.rsa密钥生成器的attilax总结 1.1. 密钥生成器 1 1.2. 生成固定的密钥 2 1.2.1. 设置或重置 SecureRandom 对象的随机数种子 2 1.3. 密钥结构 ...

  8. RSA密钥的跨平台通用

    RSA使用public key加密,用private key解密(签名相反,使用private key签名,用public key验证签名).比如我跟合作方D之间的数据传输,我使用D提供给我的publ ...

  9. cmd命令进行RSA 密钥加密操作

    --参考 http://msdn.microsoft.com/zh-cn/library/2w117ede http://msdn.microsoft.com/zh-cn/library/yxw286 ...

随机推荐

  1. 白手起家Django项目发布中篇_Centos下Python2和3并存环境部署

    python环境部署 我们今天学习的内容是如何将Django项目部署到linux服务器上,我们部署的linux系统是centos7首先,我们先在linux上搭建我们的Python3环境: 在这里首先强 ...

  2. 用 k8s 运行一次性任务【转】

    容器按照持续运行的时间可分为两类:服务类容器和工作类容器. 服务类容器通常持续提供服务,需要一直运行,比如 http server,daemon 等.工作类容器则是一次性任务,比如批处理程序,完成后容 ...

  3. RTL8711AM

    官方文档主要修改 为了实现log服务 1,在log_service.h 取消注释 #ifndef LOG_SERVICE_H #define LOG_SERVICE_H #include " ...

  4. 2013蓝桥杯预赛C/C++本科B组

    题目标题: 高斯日记 大数学家高斯有个好习惯:无论如何都要记日记. 他的日记有个与众不同的地方,他从不注明年月日,而是用一个整数代替,比如:4210 后来人们知道,那个整数就是日期,它表示那一天是高斯 ...

  5. 010、MySQL日期时间戳转化为文本日期时间

    #时间戳转化文本时间 SELECT from_unixtime( unix_timestamp( curdate( ) ) ); #时间戳转化文本时间格式化 SELECT from_unixtime( ...

  6. 10 Class文件结构

  7. HDU 4960 Handling the past 2014 多校9 线段树

    首先确定的基本思想是按时间离散化后来建线段树,对于每个操作插入到相应的时间点上 但是难就难在那个pop操作,我之前对pop操作的处理是找到离他最近的那个点删掉,但是这样对于后面的peak操作,如果时间 ...

  8. MongoDB_01

    解释:MongoDB可应对 --三高需求 High performance-对数据库高并发读写的需求 Huge Storage -对海量数据的高效率存储和访问的需求 High Scalability ...

  9. Ubuntu安装Python版本管理工具pyenv

    gyf@gyf-VirtualBox:~$ git clone https://github.com/yyuu/pyenv.git ~/.pyenvCloning into '/home/gyf/.p ...

  10. WFP之WFP简介

    ·过滤引擎是WFP的核心组成部分,过滤引擎分为两大层:用户态基础过滤引擎和内核态过滤引擎.基础过滤引擎会与内核过滤引擎交互.·内核态过滤引擎是整个过滤引擎的主体,内部分为多个分层,每分层都代表着网络协 ...