9系统可能需要考虑的一些安全策略

 

1、指纹识别

iOS 8 SDK向开发者公开了Touch ID指纹识别功能,允许App对用户身份进行本地验证。

使用Touch ID非常简单,只需要2步即可:

1) 检查Touch ID是否可用。

2)获得指纹验证结果。

 

// 引入LocalAuthentication框架
#import <LocalAuthentication/LocalAuthentication.h>
 
/// 指纹识别的演示
- (void)laDemo {
    // 0. 版本检测,判断用户手机是否是 iOS 8.0 以上版本
    if ([UIDevice currentDevice].systemVersion.floatValue < 8.0) {
        NSLog(@"系统版本太低");
        return;
    }
    NSLog(@"%@", [UIDevice currentDevice].systemVersion);
    
    // 1. 实例化本地身份验证上下文
    LAContext *ctx = [[LAContext alloc] init];
    
    // 2. 判断是否支持指纹识别
    if (![ctx canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:NULL]) {
        NSLog(@"不支持指纹识别");
        return;
    }
    
    // 3. 指纹输入 -- 异步的输入
    [ctx evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics localizedReason:@"输入指纹登录" reply:^(BOOL success, NSError *error) {
       
        // 回调执行的线程是后台线程,如果要更新UI,需要注意线程间通讯!
        NSLog(@"%d %@ %@", success, error, [NSThread currentThread]);
        
        // 如果成功,表示手机主人按照提示的文字确认并且输入了指纹
        if (success) {
            // 代码实现中,具体的操作,不会受到影响
            // 直接登录
            [self postLogin];
        }
    }];
    
    // 判断是否异步!
    NSLog(@"come here");
}
 
2、钥匙串介绍
1) 苹果的“生态圈”,钥匙串访问,使用AES256加密算法,能够保证用户密码的安全,
钥匙串访问SDK,是苹果iOS7.0.3版本后公布的
钥匙串访问的接口是纯c语言的,但是网络的有一个哥们把它封装成OC了使用箱单简单
钥匙串访问的密码保存在哪里?只要苹果知道
钥匙串访问的第三方框架,是对C框架的封装
)第三方框架应用
     
代码示例:
   
// MARK: - 保存用户信息
#defineUserNameKey @"GZUserNameKey"
#define GZUserPwdKey @"GZUserPwdKey"
- (void)saveUserInfo {
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    
setObject:self.usernameText.textforKey:GZUserNameKey];
    
    // 同步
    [defaults synchronize];
    
    // 将密码保存到钥匙串访问
    /**
     参数:
     1. 密码(明文)- 钥匙串访问本身使用的 AES 256 的加密,就是安全的,使用的时候,直接传递密码明文即可
     2. 服务名-可以随便写
        建议使用 bundleId - 应用程序的唯一标示,每一个上架的应用程序,都有一个唯一的 bundleId
        使用第三方的 SDK,内购,远程推送...
     3. 账户名(用户名)
     
     钥匙串的密码到底保存在哪里 - 只有苹果知道!
     
     关于 SSKeyChain 的框架,是对底层 C 语言的封装,不用去看!只要会用,知道概念就好!
     
     如果没有钥匙串的访问,本地密码的保存会相当麻烦,需要使用 RSA(密钥) & AES(加密&解密的)
     */
    NSString *bundleId = [NSBundle mainBundle].bundleIdentifier;
    NSLog(@"%@", bundleId);
    [SSKeychain setPassword:self.pwdText.text forService:bundleId account:self.usernameText.text];
}
     
读取信息
 
// MARK: - 加载用户信息
- (void)loadUserInfo {
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    
    self.usernameText.text = [defaults objectForKey:HMUserNameKey];
 
    // 从钥匙串来加载用户信息,只有自己开发的应用程序,才能够互相看到账号
    NSLog(@"%@", [SSKeychain allAccounts]);
    NSString *bundleId = [NSBundle mainBundle].bundleIdentifier;
    // 如果钥匙串中没有保存对应信息,返回的是空字符串
    self.pwdText.text = [SSKeychain passwordForService:bundleId account:self.usernameText.text];
}
  
 
3、BASE64 介绍
从iOS7.0开始,苹果提供了base64的编码解码的支持,
特点:
原本的8bit一组,改为每6bit一组,不足的补0,每两个0用一个“=”表示,
用base64编码之后,结果会变大约1/3
)二进制位数是6的倍数时  
               
 
)二进制位数不是6的倍数时,向后补0
终端base64编码:echonbase64      —>   QQ==
反算:echonbase64  -D   —>    A
    
终端:echonbase64      —> QkM=
反算:echonkM=“ | base64  -D —>    BC
  
4)文件应用
base64  123.pngotxt编码16进制文本
base64 123.txtopng反解密16进制二进制数据
5)编码实现
  
// MARK: - base64 编码 & 解码
// 从 iOS 7.0 开始,苹果提供了 base64 的编码解码的支持
- (NSString *)base64Encode:(NSString *)str {
    // 1. 转换成二进制
    NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding];
    
    // 2. 转换成base64的编码结果
    return [data base64EncodedStringWithOptions:0];
}
 
// MARK: - base 64 解码
// 参数:是 base64 编码后的字符串
- (NSString *)base64Decode:(NSString *)str {
    // 1. 建立二进制数据,使用 base64 编码后的字符串实例化二进制数据
    // 结果就是解码后的二进制数据
    NSData *data = [[NSData alloc] initWithBase64EncodedString:str options:0];
    
    // 2. 返回字符串
    return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
}
 
4、散列函数
)特点:
对任意二进制数据进行散列,得到一个定长的字符串,类似“指纹”,
数据摘要,比如:如果MD5散列,总会得到一个32位字符,
不可逆
 
)常用函数
目前国内用得非常之多,被清华大学的王小云通过“碰撞算法破解”
:也被破解
           * SHA256
            *SHA512
 
)MD5用用户安全登录时的安全问题
             
方案1:早期的方案,加盐,必须够复杂,
           
方案2:HMAC,是一个结合了散列函数的加密算法,
具体是给定一个“密钥”,分别作两次加密和散列,密钥的抢夺不那么高,
国外用得比较多
实现
NSString@"test".md5String;
[pwd hmacMD5StringWithKey:key];
             
方案3:
用户密码有一个要求,相同的加密算法+相同的密码明文,每次的结果是不一样的
只要每次不一样,黑客才不好猜
用户注册安全:关于用户第一次的密码安全,被黑客拦截的几率非常低的
通常有这些辅助安全手段,比如,IP辅助、手机绑定
客户端代码  
/// 利用时间,生成密码
- (NSString *)timePassword:(NSString *)pwd {
 
    // 1. key 密钥
    NSString *key = @"test".md5String;
    NSLog(@"key - %@", key);
    
    // 2. pwd + hmac
    pwd = [pwd hmacMD5StringWithKey:key];
    
    // 3. 取当前的系统时间
    NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
    fmt.dateFormat = @"yyyy-MM-ddHH:mm";
    NSString *dateStr = [fmt stringFromDate:[NSDate date]];
    NSLog(@"当前系统时间字符串 %@", dateStr);
    
    pwd = [pwd stringByAppendingString:dateStr];
    
    // 再次 hmac
    return [pwd hmacMD5StringWithKey:key];
}
 
5、对称加密算法
)对称加密算法——传统加密算法
加密和解密使用同一个“密钥”
密钥会定期更换,密钥管理很重要
可逆
 
)对称经典算法
数据解密标准(用的少,因为强度不够)
使用三个密钥,对相同的数据执行三次加密
高级加密标准,目前是美国国家安全局使用,
苹果的钥匙串访问就是使用AES加密的
 
3)ECB  电子密码本,
原理:将大的数据块,拆分成若干小的数据块,就是说每个块都是独立加密的
 
应用:  cd Destop 
mkdir加密
cd加密
vimabc.txt
           
加密: openssl enc -des-ecb -K 616263 -nosalt -in abc.txt -out msg.bin
解密: openssl enc -des-ecb -K 616263 -nosalt -in msg.bin  -out  msg.txt -d
打开文件:xxd  msg.bin
 
4)CBC  密码块链,
原理:将大的数据块,拆分成若干小的数据块,依次加密,且每一块加密和
和前一个加密块相关联,增加破译难度
 
加密: openssl enc -des-cbc -K 616263 -iv 0102030405060708 -nosalt -in abc.txt -out msg1.bin
解密:openssl enc -des-cbc -K 616263 -iv 0102030405060708 -nosalt -in msg1.bin -out msg2.txt -d
打开文件:xxd  msg.bin
 
5)iv 初始向量
现在密码学的加密很多算法都在圆、椭圆、球上做文章,
 6)代码演练
// AES - ECB 加密
NSString@"test";
    
    NSLog(@"加密 %@", [[EncryptionTools sharedEncryptionTools] encryptString:@"hello" keyString:key iv:nil]);
    NSLog(@"解密 %@", [[EncryptionTools sharedEncryptionTools] decryptString:@"KNhIRJWjZxUtgzDDlpggMg==" keyString:key iv:nil]);
    
    // AES - CBC 加密
    // *** 一定记住 iv 在程序中定义的方式!
    uint8_t iv[8] = {1, 2, 3, 4, 5, 6, 7, 8};
    NSData *ivData = [NSData dataWithBytes:iv length:sizeof(iv)];
    
    NSLog(@"加密 %@", [[EncryptionTools sharedEncryptionTools] encryptString:@"hello" keyString:key iv:ivData]);
    NSLog(@"解密 %@", [[EncryptionTools sharedEncryptionTools] decryptString:@"gap7hnMbdynogDKpJVaTOw==" keyString:key iv:ivData]);
    
    // DES - ECB 加密
    [EncryptionTools sharedEncryptionTools].algorithm = kCCAlgorithmDES;
    NSLog(@"DES 加密 %@", [[EncryptionTools sharedEncryptionTools] encryptString:@"hello" keyString:key iv:nil]);
    NSLog(@"解密 %@", [[EncryptionTools sharedEncryptionTools] decryptString:@"lfaJnK1OAsc=" keyString:key iv:nil]);
 
打印结果:
2015-08-28 20:52:02.293 08-对称加密算法[21804:161889] 加密 KNhIRJWjZxUtgzDDlpggMg==
2015-08-28 20:52:02.294 08-对称加密算法[21804:161889] 解密 hello
2015-08-28 20:52:02.294 08-对称加密算法[21804:161889] 加密 gap7hnMbdynogDKpJVaTOw==
2015-08-28 20:52:02.294 08-对称加密算法[21804:161889] 解密 hello
2015-08-28 20:52:02.294 08-对称加密算法[21804:161889] DES 加密 lfaJnK1OAsc=
2015-08-28 20:52:02.295 08-对称加密算法[21804:161889] 解密 hello
 
终端命令:
 *  DES(ECB)加密
  $ echo -n hello | openssl enc -des-ecb -K 616263 -nosalt | base64
 
  * DES(CBC)加密
 $ echo -n hello | openssl enc -des-cbc -iv 0102030405060708 -K 616263 -nosalt | base64
 
 *  AES(ECB)加密
  $ echo -n hello | openssl enc -aes-128-ecb -K 616263 -nosalt | base64
 
 *  AES(CBC)加密
  $ echo -n hello | openssl enc -aes-128-cbc -iv 0102030405060708 -K 616263 -nosalt | base64
 
 *  DES(ECB)解密
 $ echo -n HQr0Oij2kbo= | base64 -D | openssl enc -des-ecb -K 616263 -nosalt -d
 
 *  DES(CBC)解密
 $ echo -n alvrvb3Gz88= | base64 -D | openssl enc -des-cbc -iv 0102030405060708 -K 616263 -nosalt -d
 
 *  AES(ECB)解密
 $ echo -n d1QG4T2tivoi0Kiu3NEmZQ== | base64 -D | openssl enc -aes-128-ecb -K 616263 -nosalt -d
 
 *  AES(CBC)解密
 $ echo -n u3W/N816uzFpcg6pZ+kbdg== | base64 -D | openssl enc -aes-128-cbc -iv 0102030405060708 -K 616263 -nosalt -d
 
 *  提示:
 *      1> 加密过程是先加密,再base64编码
 *      2> 解密过程是先base64解码,再解密
 */
 
 
 
 7) 对称加密:终端测试指令 
 *  DES(ECB)加密
 *  $ echo -n hello | openssl enc -des-ecb -K 616263 -nosalt | base64
 *
  * DES(CBC)加密
 *  $ echo -n hello | openssl enc -des-cbc -iv 0102030405060708 -K 616263 -nosalt | base64
 *
 *  AES(ECB)加密
 *  $ echo -n hello | openssl enc -aes-128-ecb -K 616263 -nosalt | base64
 *
 *  AES(CBC)加密
 *  $ echo -n hello | openssl enc -aes-128-cbc -iv 0102030405060708 -K 616263 -nosalt | base64
 *
 *  DES(ECB)解密
 *  $ echo -n HQr0Oij2kbo= | base64 -D | openssl enc -des-ecb -K 616263 -nosalt -d
 *
 *  DES(CBC)解密
 *  $ echo -n alvrvb3Gz88= | base64 -D | openssl enc -des-cbc -iv 0102030405060708 -K 616263 -nosalt -d
 *
 *  AES(ECB)解密
 *  $ echo -n d1QG4T2tivoi0Kiu3NEmZQ== | base64 -D | openssl enc -aes-128-ecb -K 616263 -nosalt -d
 *
 *  AES(CBC)解密
 *  $ echo -n u3W/N816uzFpcg6pZ+kbdg== | base64 -D | openssl enc -aes-128-cbc -iv 0102030405060708 -K 616263 -nosalt -d
 *
 *  提示:
 *      1> 加密过程是先加密,再base64编码
 *      2> 解密过程是先base64解码,再解密
 */
 
 
6、非对称加密算法(RSA)--现代加密算法
)非对称加密需要两个密钥:公钥和私钥
公钥加密,私钥解密
私钥加密,公钥解密
)特点
算法强度复杂、安全性依赖于算法与密钥
加密解密速度慢
所以实际应用中,应用对称加密算法加密大的数据,用非对称加密算法对对称算法的密钥进行加密。
)RSA算法原理
找出两个“很大”的质数:P & Q
              * N = P * Q
Q-1)
找出整数E,E与M互质,既除了1之外,没有其他的公约数
找出整数D,使得ED除以M于1,既(ED)%M = 1
经过上述准备工作之后,可以得到:
是公钥,负责加密
是私钥,负责加密
负责公钥和私钥之间的联系
加密算法,假定对X进行加密
(X ^E)% N = Y
解密算法,根据费尔马小小定义,可以使用以下公式解密
(Y ^ D)% N = X
 
代码演练
// 1. 加载公钥   
    [[RSACryptor sharedRSACryptor] loadPublicKey:[[NSBundle mainBundle] pathForResource:@"rsacert.der" ofType:nil]];
    
    // 2. 加载私钥 - 密码就是生成p12的时候指定的密码
    [[RSACryptor sharedRSACryptor] loadPrivateKey:[[NSBundle mainBundle] pathForResource:@"p.p12" ofType:nil] password:@"123456"];
 
实际应用中可选择:openssl框架
 
 
7、程序开发证书生成指令
//  打开终端:输入以下命令生成私钥
openssl genrsa -out private.pem 1024
 
//  创建证书请求包含公钥、组织信息、联系信息   
opensslreqnewkeyprivate.pem -out rsacert.csr
 
//  生成证书并签名,有效期10年这里面文件内容为base64文件
opensslx509 -reqdaysinrsacert.csr -signkey private.pem -out rsacert.crt
 
//  转换格式-rsacert.crt格式文件转换成DER格式实际是base64解码成二进制文件
opensslx509 -outformderinrsacert.crt -out rsacert.der
 
// 导出P12文件
opensslpkcs12 -exportoutp.p12 -inkey private.pem -in  rsacert.crt