谈谈iOS中的密码学(常用的加密方式)

2017-09-21  本文已影响335人  9d8c8692519b

本文中所有代码演示均有GitHub源码,点击下载SecurityWrapper

之前的项目中接触过一些加密的方法,也没有进行仔细的记录和研究。最近正值项目正常迭代期间;借此时机,对我们常用的加密方式做一个笔记。

为什么要做加密操作?

  1. 加密就是为了保证我们的数据安全,即不被他人篡改或截取到有用的信息的操作。
  2. 在互联网发展到今天,安全早已是一个不容忽视的问题了。走在码农的道路上,对自己经手的产品要更注重质的问题,那么安全绝对放在第一位。下面我们来介绍iOS常用到的加密方式。

iOS开发中常用加密方式

常见的iOS代码加密常用加密方式包括Base64加密、MD5加密(加盐)、SHA1、SHA256、SHA384、SHA512(SHA即Secure Hash Algorithm 安全散列算法)、AES加密、RSA加密等。无论选择哪种加密算法,最终目的都是为了保证代码安全,捍卫自己的产品原创性、安全性。

一. Base64编码

Base64简单说明:

描述:Base64可以成为密码学的基石,非常重要。
特点:可以将任意的二进制数据进行Base64编码
结果:所有的数据都能被编码为并只用65个字符就能表示的文本文件。

Base64编码原理:
1)将所有字符转化为ASCII码;

2)将ASCII码转化为8位二进制;

3)将二进制3个归成一组(不足3个在后边补0)共24位,再拆分成4组,每组6位;

4)统一在6位二进制前补两个0凑足8位;

5)将补0后的二进制转为十进制;

6)从Base64编码表获取十进制对应的Base64编码;
Base64加密特点:

原本是 8个bit 一组表示数据,改为 6个bit一组表示数据,不足的部分补零,每 两个0 用 一个 = 表示
用base64 编码之后,数据长度会变大,增加了大约 1/3 左右.(8-6)/6
可进行反向解密
编码有个非常显著的特点,末尾有个 = 号

Base64加密实现:

base64在iOS7之后有直接集成的API,在Foundation框架的#import <Foundation/NSObject.h>里。几句代码即可实现,非常简单。
如:

// Decoder
- (NSData *)base64:(NSString *)string
{
    return [[NSData alloc] initWithBase64EncodedString:string options:0];
}

// convert NSData to Base64  Encoder
- (NSString *)base64:(NSData *)data
{
    return [data base64EncodedStringWithOptions:0];
}
Base64加密小结:

有人说这是一个加密算法,可它给人的感觉更像是一个编码工具,因为它完全是可逆的,分分钟就可以被破解,而且网络上有很多破解的工具,直接可以破解,所以这个一定不能用于密码的“加密”,一些不需要特别加密的,例如用户昵称、登录名等,我们可以用base64进行编码,让人不是一眼就能看出来是什么。

二. MD5加密(MD5是一种摘要,而非加密,只是经常与加密配合使用))

MD5加密简单说明和编码原理:

1、MD5的全称是Message-DigestAlgorithm 5,翻译为“消息摘要算法第5版”,Message-Digest泛指字节串(Message)的Hash变换,就是把一个任意长度的字节串变换成一定长的大整数。请注意我使用了字节串而不是字符串这个词,是因为这种变换只与字节的值有关,与字符集或编码方式无关。
2、MD5将任意长度的字节串变换成一个128bit的大整数,并且它是一个不可逆的字符串变换算法,换句话说就是,即使你看到源程序和算法描述,也无法将一个MD5的值变换回原始的字符串,从数学原理上说,是因为原始的字符串有无穷多个,这有点象不存在反函数的数学函数。
3、MD5的典型应用是对一段Message(字节串)产生fingerprint(指纹),以防止被"篡改"。举个例子,你将一段话写在一个叫readme.txt文件中,并对这个readme.txt产生一个MD5的值并记录在案,然后你可以传播这个文件给别人,别人如果修改了文件中的任何内容,你对这个文件重新计算MD5时就会发现。如果再有一个第三方的认证机构,用MD5还可以防止文件作者的"抵赖",这就是所谓的数字签名应用。
4、MD5还广泛用于加密和解密技术上,在很多操作系统中,用户的密码是以MD5值(或类似的其它算法)的方式保存的,用户Login的时候,系统是把用户输入的密码计算成MD5值,然后再去和系统中保存的MD5值进行比较,而系统并"不知道"用户的密码是什么。
5、MD5加密大体都应用在:验证数据或文件一致性、数字签名、安全访问认证等等。大概可比喻为:人的指纹来理解。
注:MD5加密是不可逆的,也就是说,MD5加密后是不能解密的,所谓的解密只是用大数据的”试用”,来测出结果的。

MD5加密特点:

a. 压缩性 : 任意长度的数据,算出的MD5值长度都是固定的。
b. 容易计算 : 从原数据计算出MD5值很容易。
c. 抗修改性 : 对原数据进行任何改动,哪怕只修改一个字节,所得到的MD5值都有很大区别。
d. 弱抗碰撞 : 已知原数据和其MD5值,想找到一个具有相同MD5值的数据(即伪造数据)是非常困难的。
e. 强抗碰撞 : 想找到两个不同数据,使他们具有相同的MD5值,是非常困难的。

MD5加密实现:

实现的核心代码如下: demo中均有源码注释

+ (JKSecurityWrapperResult *)md5WithData:(NSData *)hashData
{
    unsigned char *digest;
    digest = malloc(CC_MD5_DIGEST_LENGTH);
    
    CC_MD5([hashData bytes], (CC_LONG)[hashData length], digest);
    JKSecurityWrapperResult *result = [[JKSecurityWrapperResult alloc] initWithBytes:digest length:CC_MD5_DIGEST_LENGTH];
    free(digest);
    
    return result;
}

加盐:可以保证 MD5加密之后更加安全

#pragma mark - MD5
+ (JKSecurityWrapperResult *)md5:(NSString *)hashString;
+ (JKSecurityWrapperResult *)md5WithData:(NSData *)hashData;
#pragma mark HMAC-MD5
+ (JKSecurityWrapperResult *)hmacMd5:(NSString *)hashString hmacKey:(NSString *)key;
+ (JKSecurityWrapperResult *)hmacMd5WithData:(NSData *)hashData hmacKey:(NSString *)key;

#pragma mark - HMAC-MD5
+ (JKSecurityWrapperResult *)hmacMd5:(NSString *)hashString hmacKey:(NSString *)key
{
    return [self hmacMd5WithData:[hashString dataUsingEncoding:NSUTF8StringEncoding] hmacKey:key];
}
+ (JKSecurityWrapperResult *)hmacMd5WithData:(NSData *)hashData hmacKey:(NSString *)key
{
    unsigned char *digest;
    digest = malloc(CC_MD5_DIGEST_LENGTH);
    const char *cKey = [key cStringUsingEncoding:NSUTF8StringEncoding];
    
    CCHmac(kCCHmacAlgMD5, cKey, strlen(cKey), [hashData bytes], [hashData length], digest);
    JKSecurityWrapperResult *result = [[JKSecurityWrapperResult alloc] initWithBytes:digest length:CC_MD5_DIGEST_LENGTH];
    free(digest);
    cKey = nil;
    
    return result;
}
SHA:Secure Hash Algorithm 安全散列算法

demo有如下方法的实现,需要可由本文开头前往下载查看。

#pragma mark - SHA
+ (JKSecurityWrapperResult *)sha1:(NSString *)hashString;
+ (JKSecurityWrapperResult *)sha1WithData:(NSData *)hashData;
+ (JKSecurityWrapperResult *)sha224:(NSString *)hashString;
+ (JKSecurityWrapperResult *)sha224WithData:(NSData *)hashData;
+ (JKSecurityWrapperResult *)sha256:(NSString *)hashString;
+ (JKSecurityWrapperResult *)sha256WithData:(NSData *)hashData;
+ (JKSecurityWrapperResult *)sha384:(NSString *)hashString;
+ (JKSecurityWrapperResult *)sha384WithData:(NSData *)hashData;
+ (JKSecurityWrapperResult *)sha512:(NSString *)hashString;
+ (JKSecurityWrapperResult *)sha512WithData:(NSData *)hashData;
#pragma mark HMAC-SHA
+ (JKSecurityWrapperResult *)hmacSha1:(NSString *)hashString hmacKey:(NSString *)key;
+ (JKSecurityWrapperResult *)hmacSha1WithData:(NSData *)hashData hmacKey:(NSString *)key;
+ (JKSecurityWrapperResult *)hmacSha224:(NSString *)hashString hmacKey:(NSString *)key;
+ (JKSecurityWrapperResult *)hmacSha224WithData:(NSData *)hashData hmacKey:(NSString *)key;
+ (JKSecurityWrapperResult *)hmacSha256:(NSString *)hashString hmacKey:(NSString *)key;
+ (JKSecurityWrapperResult *)hmacSha256WithData:(NSData *)hashData hmacKey:(NSString *)key;
+ (JKSecurityWrapperResult *)hmacSha384:(NSString *)hashString hmacKey:(NSString *)key;
+ (JKSecurityWrapperResult *)hmacSha384WithData:(NSData *)hashData hmacKey:(NSString *)key;
+ (JKSecurityWrapperResult *)hmacSha512:(NSString *)hashString hmacKey:(NSString *)key;
+ (JKSecurityWrapperResult *)hmacSha512WithData:(NSData *)hashData hmacKey:(NSString *)key;

三. AES加密(对称加密)

AES加密简单说明:

AES加密算法是密码学中的高级加密标准,该加密算法采用对称分组密码体制,密钥长度的最少支持为128、192、256,分组长度128位,算法应易于各种硬件和软件实现。这种加密算法是美国联邦政府采用的区块加密标准,这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用。AES加密算法被设计为支持128/192/256位(/32=nb)数据块大小(即分组长度);支持128/192/256位(/32=nk)密码长度,,在10进制里,对应34×1038、62×1057、1.1×1077个密钥。

AES加密特点:

优点:简单、可并行计算、误差不传递
缺点:不能隐藏明文模式(比如图像加密轮廓仍在)、主动攻击(改明文,后续内容不影响,只要误差不传递该缺点就存在)
用途:需要并行加密的应用
AES强安全性、高性能、高效率、易用和灵活。
在软件及硬件上都能快速地加解密且只需要很少的存储资源。

AES加密、解密实现:

demo提供方法如下,更加具体的实现代码就不再这里贴出来了,你可以通过本文前往下载demo查看即可。

#pragma mark - AES Encrypt
+ (JKSecurityWrapperResult *)encryptString:(NSString *)string key:(NSString *)key;
+ (JKSecurityWrapperResult *)encryptString:(NSString *)string hexKey:(NSString *)key hexIv:(NSString *)iv;
+ (JKSecurityWrapperResult *)encryptString:(NSString *)string key:(NSData *)key iv:(NSData *)iv;
+ (JKSecurityWrapperResult *)encryptData:(NSData *)data key:(NSData *)key iv:(NSData *)iv;
#pragma mark AES Decrypt
+ (JKSecurityWrapperResult *)decryptBase64:(NSString *)base64 key:(NSString *)key;
+ (JKSecurityWrapperResult *)decryptBase64:(NSString *)base64 hexKey:(NSString *)key hexIv:(NSString *)iv;
+ (JKSecurityWrapperResult *)decryptBase64:(NSString *)base64 key:(NSData *)key iv:(NSData *)iv;
+ (JKSecurityWrapperResult *)decryptData:(NSData *)data key:(NSData *)key iv:(NSData *)iv;

四. RSA加密、解密(非对称加密)

RSA简单说明:

RSA非对称加密算法
非对称加密算法需要两个密钥:公开密钥(publickey)和私有密钥(privatekey)公开密钥与私有密钥是一对,如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密;如果用私有密钥对数据进行加密,那么只有用对应的公开密钥才能解密。
RSA加密大体都应用在:本地数据加密、网络传输数据加密、方法体和方法名高级混淆以及程序结构混排加密。例如:对客户端传输数据提供加密方案,有效防止通过网络接口的拦截获取。

RSA基本加密原理:

加密原理理解起来有点难度,大致如下:

 (1)找出两个“很大”的质数:P & Q
 (2)N = P * Q
 (3)M = (P – 1) * (Q – 1)
 (4)找出整数E,E与M互质,即除了1之外,没有其他公约数
 (5)找出整数D,使得E*D除以M余1,即 (E * D) % M = 1

经过上述准备工作之后,可以得到:E是公钥,负责加密D是私钥,负责解密N负责公钥和私钥之间的联系加密算法,假定对X进行加密(X ^ E) % N = Yn根据费尔马小定义,根据以下公式可以完成解密操作(Y ^ D) % N = X
但是RSA加密算法效率较差,对大型数据加密时间很长,一般用于小数据。常用场景:分部要给总部发一段报文,先对报文整个进行MD5得到一个报文摘要,再对这个报文摘要用公钥加密。然后把报文和这个RSA密文一起发过去。总部接收到报文之后要先确定报文是否在中途被人篡改,就先把这个密文用私钥解密得到报文摘要,再和整个报文MD5一下得到的报文摘要进行对比 如果一样就是没被改过。

RSA加密特点:

非对称密码体制的特点:算法强度复杂、安全性依赖于算法与密钥,但是由于其算法复杂,而使得加密解密速度没有对称加密解密的速度快,对称密码体制中只有一种密钥,并且是非公开的,如果要解密就得让对方知道密钥。所以保证其安全性就是保证密钥的安全,而非对称密钥体制有两种密钥,其中一个是公开的,这样就可以不需要像对称密码那样传输对方的密钥了。即

 RSA密钥管理的方便,计算量很大速度相对比较慢。
 RSA安全性很高,能够抵抗到目前为止已知的绝大多数密码攻击。
RSA加密、解密实现:

同样,这里不做过多代码展示,把demo中提供的方法列出如下:需要的可以通过本文前往下载demo查看!

#pragma mark - RSA Encrypt
/**
 *  加密 公钥加密
 *  IOS-SDK默认不支持私钥加密,如果需要请使用OPENSSL框架库
 *
 */
+ (JKSecurityWrapperResult *)encryptString:(NSString *)string publicKey:(NSString *)pubKey;
+ (JKSecurityWrapperResult *)encryptData:(NSData *)data publicKey:(NSString *)pubKey;

#pragma mark RSA Decrypt
/**
 *  解密 公钥、私钥解密
 *
 */
+ (JKSecurityWrapperResult *)decryptBase64:(NSString *)base64 publicKey:(NSString *)pubKey;
+ (JKSecurityWrapperResult *)decryptData:(NSData *)data publicKey:(NSString *)pubKey;

+ (JKSecurityWrapperResult *)decryptBase64:(NSString *)base64 privateKey:(NSString *)privKey;
+ (JKSecurityWrapperResult *)decryptData:(NSData *)data privateKey:(NSString *)privKey;

可能写得不够详细,在iOS 开发过程中对于加密的应用是会越来越多,越来越重要的。对于各种加密方式有一定的认识和了解会对业务场景、需求等方面选型出更适合自己的产品、达到在安全加密方面得最优解! 点击下载SecurityWrapper

上一篇下一篇

猜你喜欢

热点阅读