一、编码算法
(1)Base64编码
在MIME格式的电子邮件中,base64可以用来将binary的字节序列数据编码成ASCII字符序列构成的文本。使用时,在传输编码方式中指定base64。使用的字符包括大小写字母各26个,加上10个数字,和加号“+”,斜杠“/”,一共64个字符,等号“=”用来作为后缀用途。
完整的base64定义可见 RFC1421和 RFC2045。编码后的数据比原始数据略长,为原来的4/3。在电子邮件中,根据RFC822规定,每76个字符,还需要加上一个回车换行。可以估算编码后数据长度大约为原长的135.1%。
转换的时候,将三个byte的数据,先后放入一个24bit的缓冲区中,先来的byte占高位。数据不足3byte的话,于缓冲区中剩下的Bit用0补足。然后,每次取出6个bit,按照其值选择ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/中的字符作为编码后的输出。不断进行,直到全部输入数据转换完成。
如果最后剩下两个输入数据,在编码结果后加1个“=”;如果最后剩下一个输入数据,编码结果后加2个“=”;如果没有剩下任何数据,就什么都不要加,这样才可以保证资料还原的正确性。
(2)UrlEncode编码
百分号编码(Percent-encoding), 也称作URL编码(URL encoding), 是特定上下文的统一资源定位符 (URI)的编码机制. 实际上也适用于统一资源标志符(URI)的编码. 也用于为"application/x-www-form-urlencoded" MIME准备数据, 因为它用于通过HTTP的请求操作(request)提交HTML表单数据。
URI所允许的字符分作保留与未保留. 保留字符是那些具有特殊含义的字符. 例如, 斜线字符用于URL (或者更一般的, URI)不同部分的分界符. 未保留字符没有这些特殊含义. 百分号编码把保留字符表示为特殊字符序列. 上述情形随URI与URI的不同版本规格会有轻微的变化。
部分转换规则如下:
空格 | ! | # | $ | % | + | @ | : | = | ? |
%20 | %21 | %23 | %24 | %25 | %2B | %40 | %3A | %3D | %3F |
(3)BCD码
8421码是BCD代码中最常用的一种。在这种编码方式中每一位二值代码的1都是代表一个固定数值,把每一位的1代表的十进制数加起来,得到的结果就是它所代表的十进制数码。由于代码中从左到右每一位的1分别表示8,4,2,1,所以把这种代码叫做8421代码。每一位的1代表的十进制数称为这一位的权。8421码中的每一位的权是固定不变的,它属于恒权代码。
二、哈希摘要(Hash)
(1)MD5
Message Digest Algorithm MD5(中文名为消息摘要算法第五版)为计算机安全领域广泛使用的一种散列函数,用以提供消息的完整性保护。
MD5即Message-Digest Algorithm 5(信息-摘要算法5),用于确保信息传输完整一致。是计算机广泛使用的杂凑算法之一(又译摘要算法、哈希算法),主流编程语言普遍已有MD5实现。将数据(如汉字)运算为另一固定长度值,是杂凑算法的基础原理,MD5的前身有MD2、MD3和MD4。
MD5算法具有以下特点:
1、压缩性:任意长度的数据,算出的MD5值长度都是固定的。
2、容易计算:从原数据计算出MD5值很容易。
3、抗修改性:对原数据进行任何改动,哪怕只修改1个字节,所得到的MD5值都有很大区别。
4、强抗碰撞:已知原数据和其MD5值,想找到一个具有相同MD5值的数据(即伪造数据)是非常困难的。
MD5的作用是让大容量信息在用数字签名软件签署私人密钥前被"压缩"成一种保密的格式(就是把一个任意长度的字节串变换成一定长的十六进制数字串)。
(2)SHA
安全哈希算法(Secure Hash Algorithm)主要适用于数字签名标准(Digital Signature Standard DSS)里面定义的数字签名算法(Digital Signature Algorithm DSA)。对于长度小于2^64位的消息,SHA1会产生一个160位的消息摘要。该算法经过加密专家多年来的发展和改进已日益完善,并被广泛使用。该算法的思想是接收一段明文,然后以一种不可逆的方式将它转换成一段(通常更小)密文,也可以简单的理解为取一串输入码(称为预映射或信息),并把它们转化为长度较短、位数固定的输出序列即散列值(也称为信息摘要或信息认证代码)的过程。散列函数值可以说是对明文的一种“指纹”或是“摘要”所以对散列值的数字签名就可以视为对此明文的数字签名。
(3)MD5与SHA1的区别
因为二者均由MD4导出,SHA-1和MD5彼此很相似。相应的,他们的强度和其他特性也是相似,但还有以下几点不同:
1、对强行攻击的安全性:最显著和最重要的区别是SHA-1摘要比MD5摘要长32 位。使用强行技术,产生任何一个报文使其摘要等于给定报摘要的难度对MD5是2^128数量级的操作,而对SHA-1则是2^160数量级的操作。这样,SHA-1对强行攻击有更大的强度。
2、对密码分析的安全性:由于MD5的设计,易受密码分析的攻击,SHA-1显得不易受这样的攻击。
3、速度:在相同的硬件上,SHA-1的运行速度比MD5慢。
(4)SHA-1停止计划
2005年,密码学家就证明SHA-1的破解速度比预期提高了2000倍,虽然破解仍然是极其困难和昂贵的,但随着计算机变得越来越快和越来越廉价,SHA-1算法的安全性也逐年降低,已被密码学家严重质疑,希望由安全强度更高的SHA-2替代它。
微软第一个宣布了SHA-1弃用计划,对于SSL证书和代码签名证书,微软设定了不同的替换时间表:
1、所有Windows受信任的根证书颁发机构(CA)从2016年1月1日起必须停止签发新的SHA-1签名算法SSL证书和代码签名证书;
2、对于SSL证书,Windows将于2017年1月1日起停止支持SHA1证书。也就是说:任何在之前签发的SHA-1证书必须替换成SHA-2证书;
3、对于代码签名证书,Windows将于2016年1月1日停止接受没有时间戳的SHA-1签名的代码和SHA-1证书。也就是说,Windows仍然接受在2016年1月1日之前使用SAH-1签名的已经加上RFC3161时间戳的代码,直到微软认为有可能出现SHA-1攻击时。
Google官方博客宣布,将在Chrome浏览器中逐渐降低SHA-1证书的安全指示,逐步停止对使用SHA-1散列算法证书的支持。近日,Chrome 39新版本 PC 端发布,在部分操作系统下,该版本浏览器中已开始出现“该网站使用的安全设置已过期” 提示,在接下来的6个月内会变得越来越严格。最终,使用了有效期至2016年的SHA-1证书的站点可能会被给予黄色警告。
Mozilla也做了同样的决定,在其对外公布近期更新计划中表示:“现在依然有不少网站使用基于 SHA-1签名的 SSL证书,所以我们决定加入微软和谷歌的阵营,认为应在 2016 年 1 月 1 日前停止发放 SHA-1 证书,在 2017 年 1 月1 日后不再信任此证书。”
三、代码实现(Base64 + MD5 + SHA)
//
// main.m
// CryptoDemo
//
// Created by 555chy on 6/17/16.
// Copyright © 2016 555chy. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <CommonCrypto/CommonDigest.h>
//#import <CommonCrypto/CommonCrypto.h>
#define G_KEY @""
#define G_IV @""
#define G_SECRET_KEY_LENGTH 24
//ios的base64编码有两种方式(使用ios7系统自带的编码库和GMTBase64两种方式),这里是用的是系统自带的方法
NSString* base64Encode(const char* originalCStr, NSInteger len) {
NSData *originalData = [NSData dataWithBytes:originalCStr length:len];
/*
typedef NS_OPTIONS(NSUInteger, NSDataBase64EncodingOptions) {
// Use zero or one of the following to control the maximum line length after which a line ending is inserted. No line endings are inserted by default.
NSDataBase64Encoding64CharacterLineLength = 1UL << 0,
NSDataBase64Encoding76CharacterLineLength = 1UL << 1,
// Use zero or more of the following to specify which kind of line ending is inserted. The default line ending is CR LF.
NSDataBase64EncodingEndLineWithCarriageReturn = 1UL << 4,
NSDataBase64EncodingEndLineWithLineFeed = 1UL << 5,
} NS_ENUM_AVAILABLE(10_9, 7_0);
*/
NSData *base64Data = base64Data = [originalData base64EncodedDataWithOptions:NSDataBase64EncodingEndLineWithLineFeed];
return [[NSString alloc] initWithData:base64Data encoding:NSUTF8StringEncoding];
}
NSString* base64Decode(NSString* encodedBase64Str) {
NSData *base64Data = [[NSData alloc] initWithBase64EncodedString:encodedBase64Str options:NSDataBase64DecodingIgnoreUnknownCharacters];
return [[NSString alloc] initWithData:base64Data encoding:NSUTF8StringEncoding];
}
//加密出啦的是一个32位的16进制序列
NSString* md5Hash(NSString* originalStr, BOOL is16Or32) {
unsigned char md5CStr[CC_MD5_DIGEST_LENGTH];
//const char *cOriginalStr = [originalStr cStringUsingEncoding:NSUTF8StringEncoding];
const char *cOriginalStr = [originalStr UTF8String];
CC_MD5(cOriginalStr, (CC_LONG)strlen(cOriginalStr), md5CStr);
//NSMutableString *md5Str = [[NSMutableString alloc] init];
NSMutableString *md5Str = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH*2];
for(int i=0;i<CC_MD5_DIGEST_LENGTH;i++) {
[md5Str appendFormat:@"%02x", md5CStr[i]];
}
if(is16Or32) {
//return [[md5Str substringToIndex:24] substringFromIndex:8];
return [[md5Str substringFromIndex:8] substringToIndex:16];
}
return md5Str;
}
//SHA
/*
16进制序列位数 字节数 比特数
CC_SHA1 40 20 160
CC_SHA256 64 32 256
CC_SHA384 96 48 384
CC_SHA512 128 64 512
*/
NSString* shaHash(NSString* originalStr, unsigned char* (*CC_SHAX)(const void *data, CC_LONG len, unsigned char *md), unsigned int shaDigestLength) {
unsigned char sha1CStr[shaDigestLength];
//const char *cOriginalStr = [originalStr cStringUsingEncoding:NSUTF8StringEncoding];
const char *cOriginalStr = [originalStr UTF8String];
CC_SHAX(cOriginalStr, (CC_LONG)strlen(cOriginalStr), sha1CStr);
//NSMutableString *sha1Str = [[NSMutableString alloc] init];
NSMutableString *sha1Str = [NSMutableString stringWithCapacity:shaDigestLength*2];
for(int i=0;i<shaDigestLength;i++) {
[sha1Str appendFormat:@"%02x", sha1CStr[i]];
}
return sha1Str;
}
int main(int argc, const char * argv[]) {
@autoreleasepool {
// insert code here...
NSString *originalStr = @"welcome to chy龙神的博客";
//NSString *originalStr = @"欢迎光临JerryVon的博客";
// const char* originalCstr = [originalStr cStringUsingEncoding:NSUTF8StringEncoding];
const char *originalCstr = [originalStr UTF8String];
NSString *base64EncodeStr = base64Encode(originalCstr, strlen(originalCstr));
NSString *base64DecodeStr = base64Decode(base64EncodeStr);
NSLog(@"originalStr = %@", originalStr);
NSLog(@"base64EncodeStr = %@", base64EncodeStr);
NSLog(@"base64DecodeStr = %@", base64DecodeStr);
NSString *md5Hash16Str = md5Hash(originalStr, YES);
NSString *md5Hash32Str = md5Hash(originalStr, NO);
NSLog(@"md5Hash16Str = %@", md5Hash16Str);
NSLog(@"md5Hash32Str = %@", md5Hash32Str);
NSString *sha1HashStr = shaHash(originalStr, CC_SHA1, CC_SHA1_DIGEST_LENGTH);
NSString *sha256HashStr = shaHash(originalStr, CC_SHA256, CC_SHA256_DIGEST_LENGTH);
NSString *sha384HashStr = shaHash(originalStr, CC_SHA384, CC_SHA384_DIGEST_LENGTH);
NSString *sha512HashStr = shaHash(originalStr, CC_SHA512, CC_SHA512_DIGEST_LENGTH);
NSLog(@"sha1HashStr = %@", sha1HashStr);
NSLog(@"sha25HashStr = %@", sha256HashStr);
NSLog(@"sha384HashStr = %@", sha384HashStr);
NSLog(@"sha512HashStr = %@", sha512HashStr);
}
return 0;
}
四、执行结果
五、第三方验证
(1)Base64在线验证的网站 http://www1.tc711.com/tool/BASE64.htm
(2)MD5在线验证网站 http://md5jiami.51240.com/
(3)Hash在线计算、md5计算、sha1计算、sha256计算、sha512计算