对称加密
-
常见的算法
-
DES
数据加密标准(用的少,因为强度不够) -
3DES
使用3个密钥,对相同的数据执行3次加密,强度增强 -
AES
高级别密码标准(加密强度很高,加密后文件变大)
-
-
应用模式
-
ECB
(Electronic Code Book):。每一块数据独立加密。-
最基本的加密模式,也就是通常理解的加密,相同的明文将永远加密成相同的密文,无初始向量,容易受到密码本重放攻击,一般情况下很少用。
-
-
CBC
(Cipher Block Chaining):。使用一个密钥和一个对数据进行加密。- 明文被加密前要与前面的密文进行 异或 运算后再加密,因此只要选择不同的初始化向量,相同的密文加密后会形成不同的密文,这是目前应用最广泛的模式。
CBC
加密后的密文是上下文相关的,但明文的错误不会传递到后续分组,但如果一个分组丢失,后面的分组将全部作废(同步错误)。 -
CBC
可以有效的保证密文的 完整性,如果一个数据块在传递的过程中丢失或被改变,后面的数据将无法正常解密。
- 明文被加密前要与前面的密文进行 异或 运算后再加密,因此只要选择不同的初始化向量,相同的密文加密后会形成不同的密文,这是目前应用最广泛的模式。
-
了解了理论之后,接下来我们来使用一下对称加密。
这里我们会用到一个工具类EncryptionTools
#import "EncryptionTools.h"
@interface EncryptionTools : NSObject
+ (instancetype)sharedEncryptionTools;
/**
@constant kCCAlgorithmAES 高级加密标准,128位(默认)
@constant kCCAlgorithmDES 数据加密标准
*/
@property (nonatomic, assign) uint32_t algorithm;
/**
* 加密字符串并返回base64编码字符串
*
* @param string 要加密的字符串
* @param keyString 加密密钥
* @param iv 初始化向量(8个字节)
*
* @return 返回加密后的base64编码字符串
*/
- (NSString *)encryptString:(NSString *)string keyString:(NSString *)keyString iv:(NSData *)iv;
/**
* 解密字符串
*
* @param string 加密并base64编码后的字符串
* @param keyString 解密密钥
* @param iv 初始化向量(8个字节)
*
* @return 返回解密后的字符串
*/
- (NSString *)decryptString:(NSString *)string keyString:(NSString *)keyString iv:(NSData *)iv;
@end
这里面有有一个概念iv(向量)
,这是一个几何概念,在CBC
的时候会用到。如果不使用CBC
那么调用函数的时候,置空就可以了。这里的话,iv
需要根据项目自行设置(如果有要求的话)。下面我们看一下使用:
在iOS里面默认的是
AES
类型的加密:
我们可以通过修改
algorithm
来指定自己需要的加密算法:
[EncryptionTools sharedEncryptionTools].algorithm = kCCAlgorithmDES;
我们还可以通过终端来验证我们的加密是否成功,终端指令如下:
终端测试指令
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解码,再解密
上面指令中:
616263
对应的是abc
(ASCII码)
应用签名
-
这里我们会涉及到三个概念:
- 代码签名
- 双层代码签名
- 描述文件
-
代码签名
代码签名是对可执行文件 或 脚本进行数字签名。用来确认软件在签名后未被修改或损坏的措施。和数字签名的原理一样,只不过要签名的数据是代码而已。- 简单的代码签名
在iOS出来之前,以前的主流操作系统(Mac/Windows)软件随便从哪里下载都能运行,系统安全存在隐患,盗版软件、病毒入侵、静默安装等等。Apple为了解决这个问题,保证每一个安装到iOS上的APP都是通过Apple认证过的,于是就有了代码签名。
如果要实现验证,最简单的方式就是通过Apple官方生成非对称加密的一对公私钥,在iOS的系统中内置一个公钥,私钥由Apple后台保存。我们们上传APP到App Store时,Apple后天使用私钥对APP数据进行签名,iOS系统下载这个APP后,用公钥验证这个签名,若签名正确,这个APP肯定是由Apple后台认证的,并且没有被修改过的,这也就达到了Apple的需求:保证每一个安装的APP都是经过Apple官方允许的。
- 双层代码签名
上面我们了解到了简单的代码签名,但是这样的签名满足不了Apple的需求。因为大家都知道,iPhone上安装APP不仅仅是App Store一个渠道,我们还可以通过Debug模式去安装APP,还可以通过企业级的账号去安装,等等。那么这个时候,简单的代码签名就无能为力了,于是就有了双层代码签名。
我们先来分析一下Apple的需求:安装包不需要上传App Store,可以直接安装到手机上。
-
Apple为力保证系统的安全性,必须对安装的APP有绝对的控制权
- 经过Apple的允许才可以安装
- 不能被滥用导致非开发APP也能被安装
-
我们来梳理一下双层代码签名的流程
1、
在Mac系统中生成非对称加密算法的一对公钥&私钥(Xcode会自动完成);这里称之为公钥M
&私钥M
(M 代表 Mac)。
2、
Apple自己有固定的一对公钥&私钥,跟上面的简单代码签名,私钥放在Apple后台,公钥内置在iOS系统中;这里称之为公钥A
&私钥A
(A 代表 Apple)。
3、
把公钥M
以及一些开发者信息,传到Apple后台(这个就是CSR文件),用Apple后台的私钥A
去签名公钥M
;得到一份数据包含了公钥M
以及其签名,把这份数据成为证书。
4、
在开发时,编译完一个APP后,用本地的私钥M(今后你导出的p12文件)
对这个APP进行签名,同时把第三步得到的证书一起打包进APP包里面,安装到手机上。
5、
在安装的时候,iOS系统取到证书,通过系统内置的公钥A
去验证正式的数字签名是否正确。
6、
验证证书后,确保了公钥M
是Apple认证过的,再用公钥M
去验证APP的签名,这里就间接验证了这个APP的安装行为是否经过Apple的官方许可。(⚠️ 注意:这里只验证安装行为,不验证APP是否被改动,因为开发阶段APP内容总是不断变化的,Apple不需要管。)
- 简单的代码签名
- 描述文件
在上面的过程中,已经可以保证开发者的认证和程序的安全性了。但是,要知道iOS的程序,主要渠道是要通过App Store才能分发到用户设备的,如果只有上述的过程,那岂不是只要申请一个证书,就可以安装到所有iOS设备了?
那么什么是描述文件呢?
Apple为了解决应用滥用的问题,所以加了两个限制。
i
:限制在Apple后台注册过的设备才可以安装。
ii
:限制签名只能针对某一个具体的APP。
并且Apple还想控制APP里面的iCloud、Push、后台运行、调试器附加这些权限,所以Apple把这些权限开关统一称为Entitlements(授权文件)
,并将这个文件放在一个叫做Provisioning Profile(描述文件)
文件中。
描述文件是AppleDevelop网站创建的(在Xcode中填上AppleID它会代办创建),Xcode运行时会打包进入APP内,所以我们使用CSR申请证书时,我们还要申请一个东西,就是描述文件。
在开发时,编译完一个APP后,用本地的私钥M
对这个APP进行签名,同时把从Apple服务器得到的Provisioning Profile
文件打包进APP里面,文件名问embedded.mobileprovision
,把APP安装到手机上,最后系统进行验证。