一、base64
注意:准确来说一种编码方式,编码算法完全公开,可以逆向解码。
1、简介:
Base64编码的思想是是采用64个基本的ASCII码字符对数据进行重新编码。它将需要编码的数据拆分成字节数组。以3个字节为一组。按顺序排列24位数据,再把这24位数据分成4组,即每组6位。再在每组的的最高位前补两个0凑足一个字节。这样就把一个3字节为一组的数据重新编码成了4个字节。当所要编码的数据的字节数不是3的整倍数,也就是说在分组时最后一组不够3个字节。这时在最后一组填充1到2个0字节。并在最后编码完成后在结尾添加1到2个“=”。例:将对ABC进行BASE64编码首先取ABC对应的ASCII码值。A(65)B(66)C(67)。再取二进制值A(01000001)B(01000010)C(01000011),然后把这三个字节的二进制码接起来(010000010100001001000011),再以6位为单位分成4个数据块并在最高位填充两个0后形成4个字节的编码后的值(00010000)(00010100)(00001001)(00000011)。蓝色部分为真实数据。再把这四个字节数据转化成10进制数得(16)(20)(19)(3)。最后根据BASE64给出的64个基本字符表,查出对应的ASCII码字符(Q)(U)(J)(D)。这里的值实际就是数据在字符表中的索引。
注:BASE64字符表:包括大写 A-Z 小写 a-z 数字 0-9 和+ /
解码过程就是把4个字节再还原成3个字节再根据不同的数据形式把字节数组重新整理成数据.
2、加密原则:
6 bit(原8bit) 一个字节. 不足的位数 用0 补齐.两个0 用一个 = 表示.
3、加密特点
数据加密之后,数据量会变大,变大 1/3 左右.
4、示例代码:
UIImage *image = [UIImage imageNamed:@"0.jpeg"];
NSData *data = UIImageJPEGRepresentation(image, 1.0);
NSData *base64Data = [data base64EncodedDataWithOptions:NSDataBase64Encoding64CharacterLineLength];
[base64Data writeToFile:@"/Users/chh/Desktop/123" atomically:YES];
// NSString *encodeStr = [data base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
NSData *base64Data2 = [NSData dataWithContentsOfFile:@"/Users/chh/Desktop/123"];
NSData *baseData2 = [[NSData alloc] initWithBase64EncodedData:base64Data2 options:NSDataBase64DecodingIgnoreUnknownCharacters];
[baseData2 writeToFile:@"/Users/chh/Desktop/IMG_5551.jpeg" atomically:YES];
5、三方框架
GTMBase64:pod 'GTMBase64', '~> 1.0.0'(和系统的base64有区别)
二、MD5
1、简介
MD5的全称是Message-DigestAlgorithm 5,Message-Digest泛指字节串(Message)的Hash变换,就是把一个任意长度的字节串变换成一定长的大整数。请注意我使用了"字节串"而不是"字符串"这个词,是因为这种变换只与字节的值有关,与字符集或编码方式无关。 MD5将任意长度的"字节串"变换成一个128bit的大整数,并且它是一个不可逆的字符串变换算法,换句话说就是,即使你看到源程序和算法描述,也无法将一个MD5的值变换回原始的字符串,从数学原理上说,是因为原始的字符串有无穷多个,这有点象不存在反函数的数学函数。
MD5的典型应用是对一段Message(字节串)产生fingerprint(指纹),以防止被"篡改"。举个例子,你将一段话写在一个叫readme.txt文件中,并对这个readme.txt产生一个MD5的值并记录在案,然后你可以传播这个文件给别人,别人如果修改了文件中的任何内容,你对这个文件重新计算MD5时就会发现。如果再有一个第三方的认证机构,用MD5还可以防止文件作者的"抵赖",这就是所谓的数字签名应用。
MD5还广泛用于加密和解密技术上,在很多操作系统中,用户的密码是以MD5值(或类似的其它算法)的方式保存的,用户Login的时候,系统是把用户输入的密码计算成MD5值,然后再去和系统中保存的MD5值进行比较,而系统并不"知道"用户的密码是什么。
注: MD5加密是不可逆的,也就是说, MD5加密后是不能解密的,所谓的解密只是用大数据的”试用”,来测出结果的.
2、加密方式
NSString *password = @"zhang";
password = [password MD5];
备注:单纯的 MD5加密是不安全的,因此要用到 MD5加盐的方式
3、MD5加盐
盐值:MD5加盐的值,加的盐值越高越好.(盐值可以随意添加)
// 生成盐值
NSString *salt = @"盐值";
// 拼接盐值
password = [password stringByAppendingString:salt];
// 加密
password = password.md5String;
4、第三方框架:
NSString+Hash
三、AES加密
AES加密解密需要专属的key值,如下面的password,一般都是与Base64结合起来一起使用。
NSString *message = @"top secret message"; // message 为加密字符串 与密码混合加密
NSString *password = @"p4ssw0rd"; // passwprd 为用户输入的密码
NSString *encryptedData = [AESCrypt encrypt:message password:password]; //加密
NSString *message = [AESCrypt decrypt:encryptedData password:password]; //解密
第三方框架:
AESCrypt:pod 'AESCrypt', '~> 0.0.1'
四、DES
DES算法把64位的明文输入块变为64位的密文输出块,它所使用的密钥也是64位(实际用到了56位,第8、16、24、32、40、48、56、64位是校验位, 使得每个密钥都有奇数个1),其算法主要分为两步:
a、初始置换
其功能是把输入的64位数据块按位重新组合,并把输出分为L0、R0两部分,每部分各长32位,其置换规则为将输入的第58位换到第一位,第50位换到第2位……依此类推,最后一位是原来的第7位。L0、R0则是换位输出后的两部分,L0是输出的左32位,R0是右32位,例:设置换前的输入值为D1D2D3……D64,则经过初始置换后的结果为:L0=D58D50……D8;R0=D57D49……D7。
其置换规则见下表:
58,50,42,34,26,18,10,2,60,52,44,36,28,20,12,4,
62,54,46,38,30,22,14,6,64,56,48,40,32,24,16,8,
57,49,41,33,25,17,9,1,59,51,43,35,27,19,11,3,
61,53,45,37,29,21,13,5,63,55,47,39,31,23,15,7,
b、逆置换
经过16次迭代运算后,得到L16、R16,将此作为输入,进行逆置换,逆置换正好是初始置换的逆运算,由此即得到密文输出。
此算法是对称加密算法体系中的代表,在计算机网络系统中广泛使用.
备注:数据加密标准,速度较快,适用于加密大量数据的场合。
详情见#import "CommonFunc.h"
/******************************************************************************
函数名称: + (NSData *)DESEncrypt:(NSData *)data WithKey:(NSString *)key
函数描述: 文本数据进行DES加密
输入参数: (NSData *)data
(NSString *)key
输出参数: N/A
返回参数: (NSData *)
备注信息: 此函数不可用于过长文本
******************************************************************************/
+ (NSData *)DESEncrypt:(NSData *)data WithKey:(NSString *)key
{
char keyPtr[kCCKeySizeAES256+1];
bzero(keyPtr, sizeof(keyPtr));
[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
NSUInteger dataLength = [data length];
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize);
size_t numBytesEncrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmDES,
kCCOptionPKCS7Padding | kCCOptionECBMode,
keyPtr, kCCBlockSizeDES,
NULL,
[data bytes], dataLength,
buffer, bufferSize,
&numBytesEncrypted);
if (cryptStatus == kCCSuccess) {
return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
}
free(buffer);
return nil;
}
/******************************************************************************
函数名称: + (NSData *)DESEncrypt:(NSData *)data WithKey:(NSString *)key
函数描述: 文本数据进行DES解密
输入参数: (NSData *)data
(NSString *)key
输出参数: N/A
返回参数: (NSData *)
备注信息: 此函数不可用于过长文本
******************************************************************************/
+ (NSData *)DESDecrypt:(NSData *)data WithKey:(NSString *)key
{
char keyPtr[kCCKeySizeAES256+1];
bzero(keyPtr, sizeof(keyPtr));
[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
NSUInteger dataLength = [data length];
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize);
size_t numBytesDecrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmDES,
kCCOptionPKCS7Padding | kCCOptionECBMode,
keyPtr, kCCBlockSizeDES,
NULL,
[data bytes], dataLength,
buffer, bufferSize,
&numBytesDecrypted);
if (cryptStatus == kCCSuccess) {
return [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted];
}
free(buffer);
return nil;
}
五、钥匙串访问
1、苹果在iOS 7.0.3版本以后公布钥匙串访问的SDK.钥匙串访问接口是纯C语言的.
2、钥匙串使用AES 256加密算法,能够保证用户密码的安全.
3、钥匙串访问的第三方框架SSKeychain,是对C语言框架的封装.注意:不需要看源码.
4、钥匙串访问的密码保存在哪里?只有苹果才知道.这样进一步保障了用户的密码安全.
5、使用方法
Password :需要存储的密码信息.
Service :用来标识 app ,app的唯一标识符.
account :账户信息,当前密码所对应的账号.
a、利用钥匙串进行加密
// 获取应用程序唯一标识.
NSString *bundleId = [NSBundle mainBundle].bundleIdentifier;
// 利用第三方框架,将用户密码保存在钥匙串
[SSKeychain setPassword:self.pwdText.text forService:bundleId account:@"wpf"];
b、从钥匙串加载密码
self.pwdText.text = [SSKeychain passwordForService:bundleId account:@"wpf"];
6、第三方框架
SSKeychain:pod 'SSKeychain'
六、Token值
1、介绍
token 值: 登录令牌.利用 token 值来判断用户的登录状态.类似于 MD5 加密之后的长字符串.
用户登录成功之后,在后端(服务器端)会根据用户信息生成一个唯一的值.这个值就是 token 值.
2、基本使用
a、在服务器端(数据库)会保存这个 token 值,以后利用这个 token 值来检索对应的用户信息,并且判断用户的登录状态.
b、用户登录成功之后,服务器会将生成的 token 值返回给 客户端,在客户端也会保存这个 token 值.(一般可以保存在 cookie 中,也可以自己手动确定保存位置(比如偏好设置.)).
c、以后客户端在发送新的网络请求的时候,会默认自动附带这个 token 值(作为一个参数传递给服务器.).服务器拿到客户端传递的 token 值跟保存在 数据库中的 token 值做对比,以此来判断用户身份和登录状态.
3、判断登录状态
如果客户端没有这个token 值,意味着没有登录成功过,提示用户登录.
如果客户端有token 值,一般会认为登录成功(需要验证是否有效).不需要用户再次登录(输入账号和密码信息).
4、拓展
有效期说明:
一般的app ,token值得失效时间都在 1 年以上.
特殊的app :银行类 app /支付类 app :token值失效时间 15 分钟左右.
一旦用户信息改变(密码改变),会在服务器生成新的 token 值,原来的 token值就会失效.需要再次输入账号和密码,以得到生成的新的 token 值.
唯一性判断: 每次登录,都会生成一个新的token值.原来的 token 值就会失效.利用时间来判断登录的差异性。
发表评论 取消回复