这篇文章主要给大家介绍了关于 iOS 中常见的几种加密方法, 其中包括 base64 加密, POST 加密, Token 值介绍, MD5 加密 --(信息 - 摘要算法) 哈希算法之一, 时间戳密码以及指纹识别等方法, 文中通过示例代码介绍的非常详细, 需要的朋友可以参考下.
前言
在我们日常开发中, 加密是必不可少的一部分, 而普通加密方法是讲密码进行加密后保存到用户偏好设置中, 钥匙串是以明文形式保存, 但是不知道存放的具体位置, 下面本文将详细给大家介绍 iOS 中常见的几种加密方法, 下面话不多说了, 来一起看看详细的介绍吧.
一. base64 加密
base64 编码是现代密码学的基础
基本原理:
原本是 8 个 bit 一组表示数据, 改为 6 个 bit 一组表示数据, 不足的部分补零, 每 两个 0 用 一个 = 表示
用 base64 编码之后, 数据长度会变大, 增加了大约 1/3 左右.(8-6)/6
可进行反向解密
Xcode7.0 之后出现的
编码有个非常显著的特点, 末尾有个 = 号
将文件进行加密
- // 获取需要加密文件的二进制数据
- NSData *data = [NSData dataWithContentsOfFile:@"/Users/wangpengfei/Desktop/photo/IMG_5551.jpg"];
- // 或 base64EncodedStringWithOptions
- NSData *base64Data = [data base64EncodedDataWithOptions:0];
- // 将加密后的文件存储到桌面
- [base64Data writeToFile:@"/Users/wangpengfei/Desktop/123" atomically:YES];
将文件进行解密
- // 获得加密后的二进制数据
- NSData *base64Data = [NSData dataWithContentsOfFile:@"/Users/wangpengfei/Desktop/123"];
- // 解密 base64 数据
- NSData *baseData = [[NSData alloc] initWithBase64EncodedData:base64Data options:0];
- // 写入桌面
- [baseData writeToFile:@"/Users/wangpengfei/Desktop/IMG_5551.jpg" atomically:YES];
利用终端命令进行 base64 运算:
- // 将文件 meinv.jpg 进行 base64 运算之后存储为 meinv.txt
- base64 meinv.jpg -o meinv.txt
- // 讲 meinv.txt 解码生成 meinv.PNG
- base64 -D meinv.txt -o meinv.PNG
- // 将字符串 "hello" 进行 base 64 编码 结果: aGVsbG8=cho "hello" | base64
- // 将 base64 编码之后的结果 aGVsbG8= 反编码为字符串
- echo aGVsbG8= | base64 -D
二. POST 加密
A. 搭建 UI 框架
Login.storyboard
两个 UItextFiled : 分别输入用户名和密码
UIButton : 登录按钮
Main.storyboard
直接拖一个 navigationController->tableViewController
navigationItem + 注销按钮
B. 实现基本加密
抽取出读取数据的方法
- - (void)readLocalUserInfo {
- // 1. 实例化偏好设置对象
- NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
- // 2. 取出数据进行赋值
- self.userName.text = [userDefaults objectForKey:kUserNameKey];
- // 此时读取的是加密后的密码
- self.password.text = [userDefaults objectForKey:kPasswordKey];
- }
抽取出存储数据的方法
- - (void)saveLocalUserInfo {
- // 1. 实例化偏好设置对象
- NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
- // 2. 存储用户名
- [userDefaults setObject:self.userName.text forKey:kUserNameKey];
- // 3. 将密码进行 base64 加密
- // 将密码转化为二进制数据
- NSData *data = [self.password.text dataUsingEncoding:NSUTF8StringEncoding];
- // 进行加密
- NSString *base64Str = [data base64EncodedStringWithOptions:0];
- // 4. 将加密后的密码存储到偏好设置
- [userDefaults setObject:base64Str forKey:kPasswordKey];
- // 5. 为了保证线程的一致性, 无论是存储还是读取数据, 都要进行同步
- [userDefaults synchronize];
- }
在点击事件中进行登录操作
- - (IBAction)btnLoginDidClick:(UIButton *)sender {
- // 如果两个文本框均不为空, 则进行登录操作
- if (self.userName.text.length && self.password.text.length) {
- // 1. 创建请求
- NSString *urlString = @"http://localhost/login/login.php";
- NSURL *url = [NSURL URLWithString:urlString];
- // POST 请求需要手动设置请求方法, 因此为可变请求
- NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
- // 设置请求方法
- request.HTTPMethod = @"POST";
- // 设置请求参数
- NSString *body = [NSString stringWithFormat:@"username=%@&password=%@", self.userName.text, self.password.text];
- // 将字符串转为二进制数据
- NSData *bodyData = [body dataUsingEncoding:NSUTF8StringEncoding];
- // 设置请求主体(二进制数据)
- request.HTTPBody = bodyData;
- // 2. 发送请求
- [[[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
- // 打印请求结果
- NSLog(@"data:%@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
- // 判断是否登录成功
- if (data && !error) {
- NSLog(@"网络请求成功!");
- NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
- if (dict[@"userID"]) {
- [self saveLocalUserInfo];
- }
- // 跳转到 App 主界面, 在主线程中发送通知
- dispatch_async(dispatch_get_main_queue(), ^{
- [[NSNotificationCenter defaultCenter] postNotificationName:@"loginSuccess" object:nil];
- });
- } else {
- NSLog(@"网络请求失败!");
- }
- }] resume];
- } else {
- NSLog(@"用户名或密码不能为空!");
- }
- }
C. 实现页面间跳转
在 AppDelegate.m 文件中利用通知设置页面的跳转
切换的主方法
- - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
- // 1. 注册登录成功的通知观察者
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(loginSuccess) name:@"loginSuccess" object:nil];
- // 2. 注册登录成功的通知观察者
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(logoutSuccess) name:@"logoutSuccess" object:nil];
- // 每次 App 打开后, 应该展示给用户哪个界面
- // 3. 利用偏好设置中用户保存的信息来判断用户的登录状态
- NSString *userName = [[NSUserDefaults standardUserDefaults] objectForKey:kUserNameKey];
- NSString *password = [[NSUserDefaults standardUserDefaults] objectForKey:kPasswordKey];
- if (userName && password) {
- // 显示 App 主界面
- [self loginSuccess];
- } else {
- [self logoutSuccess];
- }
- return YES;
- }
登录成功
- - (void)loginSuccess {
- NSLog(@"登录成功!");
- // 获取主界面
- UIStoryboard *mainSb = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
- // 切换控制器
- self.Windows.rootViewController = mainSb.instantiateInitialViewController;
- }
注销成功
- - (void)logoutSuccess {
- NSLog(@"注销成功!");
- // 获取登录界面
- UIStoryboard *loginSb = [UIStoryboard storyboardWithName:@"Login" bundle:nil];
- // 切换控制器
- self.Windows.rootViewController = loginSb.instantiateInitialViewController;
- }
在 Main.storyboard 关联的控制器中设置注销按钮的点击事件
- // 1. 清除本地信息
- [[NSUserDefaults standardUserDefaults] removeObjectForKey:kUserNameKey];
- [[NSUserDefaults standardUserDefaults] removeObjectForKey:kPasswordKey];
- // 同步信息
- [[NSUserDefaults standardUserDefaults] synchronize];
- // 2. 发送信息, 切换控制器
- [[NSNotificationCenter defaultCenter] postNotificationName:@"logoutSuccess" object:nil];
三. Token 值介绍
token 值: 登录令牌. 利用 token 值来判断用户的登录状态. 类似于 MD5 加密之后的长字符串.
用户登录成功之后, 在后端 (服务器端) 会根据用户信息生成一个唯一的值. 这个值就是 token 值.
基本使用:
在服务器端 (数据库) 会保存这个 token 值, 以后利用这个 token 值来检索对应的用户信息, 并且判断用户的登录状态.
用户登录成功之后, 服务器会将生成的 token 值返回给 客户端, 在客户端也会保存这个 token 值.(一般可以保存在 cookie 中, 也可以自己手动确定保存位置(比如偏好设置.)).
以后客户端在发送新的网络请求的时候, 会默认自动附带这个 token 值(作为一个参数传递给服务器.). 服务器拿到客户端传递的 token 值跟保存在 数据库中的 token 值做对比, 以此来判断用户身份和登录状态.
判断登录状态:
如果客户端没有这个 token 值, 意味着没有登录成功过, 提示用户登录.
如果客户端有 token 值, 一般会认为登录成功. 不需要用户再次登录(输入账号和密码信息).
token 值扩展:
token 值有失效时间:
一般的 App ,token 值得失效时间都在 1 年以上.
特殊的 App : 银行类 App / 支付类 App :token 值失效时间 15 分钟左右.
一旦用户信息改变(密码改变), 会在服务器生成新的 token 值, 原来的 token 值就会失效. 需要再次输入账号和密码, 以得到生成的新的 token 值.
唯一性判断: 每次登录, 都会生成一个新的 token 值. 原来的 token 值就会失效. 利用时间来判断登录的差异性.
四. MD5 加密 --(信息 - 摘要算法) 哈希算法之一
把一个任意长度的字节串变换成一定长度的十六进制的大整数.
注意, 字符串的转换过程是不可逆的, 不能通过加密结果, 反向推导出原始内容
基本介绍
需要导入第三方框架: NSString+Hash
MD5 特点:
压缩性 : 任意长度的数据, 算出的 MD5 值长度都是固定的.
容易计算 : 从原数据计算出 MD5 值很容易.
抗修改性 : 对原数据进行任何改动, 哪怕只修改一个字节, 所得到的 MD5 值都有很大区别.
弱抗碰撞 : 已知原数据和其 MD5 值, 想找到一个具有相同 MD5 值的数据 (即伪造数据) 是非常困难的.
强抗碰撞: 想找到两个不同数据, 使他们具有相同的 MD5 值, 是非常困难的
MD5 应用:
一致性验证: MD5 将整个文件当做一个大文本信息, 通过不可逆的字符串变换算法, 产生一个唯一的 MD5 信息摘要. 就像每个人都有自己独一无二的指纹, MD5 对任何文件产生一个独一无二的数字指纹.
利用 MD5 来进行文件校验, 被大量应用在软件下载站, 论坛数据库, 系统文件安全等方面(是否认为添加木马, 篡改文件内容等). 百度'MD5'第一个网站进去, 利用数据库伪解密, 即反查询
数字签名;
安全访问认证;
使用方法
利用 MD5 对字符串进行加密
- NSString *password = @"WangPengfei";
- password = [password md5String];
- NSLog(@"password1:%@", password);
加盐: 可以保证 MD5 加密之后更加安全
- NSString *salt = @"234567890-!@#$%^&*()_+QWERTYUIOP{ASDFGHJKL:XCVBNM<>";
- [password stringByAppendingString:salt];
- password = [password md5String];
- NSLog(@"password2:%@", password);
每一个公司都有自己的 "盐值", 盐值越复杂, 越安全
五. 时间戳密码
基本介绍
动态密码: 相同的密码明文 + 相同的加密算法 -->因为每次登陆时间都不同, 所以每次计算出的结果也都不相同. 可以充分保证密码的安全性.
服务器会计算两个时间值, 当期时间和前一分钟的时间(比如: 第 59S 发送的网络请求, 一秒钟后服务器收到并作出响应, 这时服务器当前时间比客户端发送时间晚一分钟, 仍然能够判断准确的值)
使用步骤
获取 MD5 首次加密的密码
- // 1. 当前密码
- NSString *password = @"zhang";
- // 2. hmacKey 值, 是对 "WangPengfei" 进行 MD5 加密之后的值(动态生成的)
- NSString *hmacKey = @"d3bba33b51acaa0a272de7a2f6dfa233";
加密过程
- // 1. 第一次加密: 第一次 HMAC 运算
- password = [password hmacMD5StringWithKey:hmacKey];
- // 2.1 获得当前的时间
- NSDate *date = [NSDate date];
- // 2.2 获得当前时间的字符串
- // 实例化时间格式器
- NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
- // 设置时间格式
- formatter.dateFormat = @"yyyy-MM-dd HH:mm";
- // 获取当前时间(要和服务器保持一致)
- NSString *dateStr = [formatter stringFromDate:date];
- // 3. 将第一次加密后的密码与当前时间的字符串拼接在一起
- password = [password stringByAppendingString:dateStr];
- // 4. 进行第二次 HMAC 加密
- password = [password hmacMD5StringWithKey:hmacKey];
访问 loginhmac.PHP 接口, 发送请求
创建请求
- NSURL *url = [NSURL URLWithString:@"http://localhost/login/loginhmac.php"];
- // POST 要手动设置方法, 因此为可变
- NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
- // 设置请求方法
- request.HTTPMethod = @"POST";
- // 设置请求体内容
- NSString *body = [NSString stringWithFormat:@"username=zhangsan&password=%@", password];
- request.HTTPBody = [body dataUsingEncoding:NSUTF8StringEncoding];
发送请求
- [[[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
- NSLog(@"%@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
- }] resume];
六. 钥匙串访问
基本介绍
苹果在 iOS 7.0.3 版本以后公布钥匙串访问的 SDK. 钥匙串访问接口是纯 C 语言的.
钥匙串使用 AES 256 加密算法, 能够保证用户密码的安全.
钥匙串访问的第三方框架 SSKeychain, 是对 C 语言框架的封装. 注意: 不需要看源码.
钥匙串访问的密码保存在哪里? 只有苹果才知道. 这样进一步保障了用户的密码安全.
简单使用
参数介绍
Password : 需要存储的密码信息.
Service : 用来标识 App ,App 的唯一标识符.
account : 账户信息, 当前密码所对应的账号.
利用钥匙串进行加密
- // 获取应用程序唯一标识.
- NSString *bundleId = [NSBundle mainBundle].bundleIdentifier;
- // 利用第三方框架, 将用户密码保存在钥匙串
- [SSKeychain setPassword:self.pwdText.text forService:bundleId account:@"wpf"];
从钥匙串加载密码
self.pwdText.text = [SSKeychain passwordForService:bundleId account:@"wpf"];
七. 指纹识别
简单介绍
指纹识别功能是 iPhone 5S 之后推出的. SDK 是 iOS 8.0 推出!
推出指纹识别功能的目的, 是为了简化移动支付环节, 占领移动支付市场.
使用步骤
导入框架
#import
获得当前系统版本号
- float version = [UIDevice currentDevice].systemVersion.floatValue;
- if (version < 8.0 ) // 判断当前系统版本 {
- NSLog(@"系统版本太低, 请升级至最新系统");
- return;
- }
实例化指纹识别对象, 判断当前设备是否支持指纹识别功能(是否带有 TouchID)
- // 1> 实例化指纹识别对象
- LAContext *laCtx = [[LAContext alloc] init];
- // 2> 判断当前设备是否支持指纹识别功能.
- if (![laCtx canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:NULL]) {
- // 如果设备不支持指纹识别功能
- NSLog(@"该设备不支持指纹识别功能");
- return;
- };
指纹登陆(默认是异步方法)
- [laCtx evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics localizedReason:@"指纹登陆" reply:^(BOOL success, NSError *error) {
- // 如果成功, 表示指纹输入正确.
- if (success) {
- NSLog(@"指纹识别成功!");
- } else {
- NSLog(@"指纹识别错误, 请再次尝试");
- }
- }];
总结:
来源: http://mobile.51cto.com/hot-594747.htm