dushine00 2019-06-27
声明:
Base64编码是一种用64个字符(其实是65个字符,“=”是填充字符)来表示任意二进制数据的方法,编码后的数据是一个字符串。
原理
特点
应用
iOS代码示例
NSString *base0 = [data base64EncodedStringWithOptions:0]; NSString *base1 = [data base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength]; //每行最大长度64,行之间添加“\r\n” NSString *base2 = [data base64EncodedStringWithOptions:NSDataBase64Encoding76CharacterLineLength]; //每行最大长度76,行之间添加“\r\n” NSString *base3 = [data base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithCarriageReturn]; NSString *base4 = [data base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];
消息摘要算法主要分为三类,即:消息摘要(Message Digest:MD)、安全散列(Secure Hash Algorithm:SHA)和消息认证码(Message Authentication Code:MAC),主要作用是验证数据的完整性。消息摘要算法的主要特点有:①变长输入,定长输出。②单向、不可逆。③虽然“碰撞”是肯定存在的,但是很难找到“碰撞”。
MD算法系列最新为MD5,Message-Digest Algorithm 5(信息-摘要算法5)一种被广泛使用的散列算法,可以产生出一个128位的散列值(hash value),用于确保信息传输完整一致。下面以MD5为例进行分析:
原理
处理分组数据,分组数为N+1(块长:512位),每个分组进行4轮变换。
① 四个非线性函数,用于4轮变换。
F(X,Y,Z)=(X&Y)|((~X)&Z) G(X,Y,Z)=(X&Z)|(Y&(~Z)) H(X,Y,Z)=X^Y^Z I(X,Y,Z)=Y^(X|(~Z))
②每组的4轮变换
/* F :一个非线性函数,一个函数运算一次 Mi :表示一个 32-bits 的输入数据 Ki:表示一个 32-bits 常数,用来完成每次不同的计算。假设Mj表示消息的第j个子分组(从0到15),常数ti是4294967296*abs( sin(i) )的整数部分,i 取值从1到64,单位是弧度。(4294967296=2^(32))*/ FF(a ,b ,c ,d ,Mj ,s ,ti) 操作为 a = b + ( (a + F(b,c,d) + Mj + ti) << s) // 第一轮用,共16次 GG(a ,b ,c ,d ,Mj ,s ,ti) 操作为 a = b + ( (a + G(b,c,d) + Mj + ti) << s) // 第二轮用,共16次 HH(a ,b ,c ,d ,Mj ,s ,ti) 操作为 a = b + ( (a + H(b,c,d) + Mj + ti) << s) // 第三轮用,共16次 II(a ,b ,c ,d ,Mj ,s ,ti) 操作为 a = b + ( (a + I(b,c,d) + Mj + ti) << s) // 第四轮用,共16次
③ 每组完成之后,将a、b、c、d分别在原来基础上再加上A、B、C、D。即a = a + A,b = b + B,c = c + C,d = d + D,然后用下一分组数据继续运行以上算法。
④ 最后的输出是a、b、c和d的级联,由四个32位分组组成,将这四个32位分组级联后将生成一个128位散列值。
特点
iOS代码示例
//相关类文件:#include <CommonCrypto/CommonDigest.h> -(NSString *)md5 { if(self == nil || [self length] == 0){ return nil; } const char *src = [self UTF8String]; unsigned char result[CC_MD5_DIGEST_LENGTH]; CC_MD5(src, (CC_LONG)strlen(src), result); return [NSString stringWithFormat:@"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", result[0], result[1], result[2], result[3], result[4], result[5], result[6], result[7], result[8], result[9], result[10], result[11], result[12], result[13], result[14], result[15] ]; }
安全散列算法(英语:Secure Hash Algorithm,缩写为SHA)是一个密码散列函数家族,是FIPS所认证的安全散列算法。能计算出一个数字消息所对应到的,长度固定的字符串(又称消息摘要)的算法。且若输入的消息不同,它们对应到不同字符串的机率很高。
下表中的中继散列值(internal state)表示对每个数据区块压缩散列过后的中继值(internal hash sum)。
iOS代码示例
// 类似MD5,相关类文件:#include <CommonCrypto/CommonDigest.h> -(NSString *)sha1 { const char *cstr = [self cStringUsingEncoding:NSUTF8StringEncoding]; NSData *data = [NSData dataWithBytes:cstr length:self.length]; uint8_t digest[CC_SHA1_DIGEST_LENGTH]; CC_SHA1(data.bytes, (unsigned int)data.length, digest); NSMutableString *output = [NSMutableString stringWithCapacity:CC_SHA1_DIGEST_LENGTH * 2]; for(int i=0; i < CC_SHA1_DIGEST_LENGTH; i++) { [output appendFormat:@"%02x", digest[i]]; } return output; }
MAC(Message Authentication Code,消息认证码算法)结合了MD5和SHA算法的优势,并加入密钥的支持,是一种更为安全的消息摘要算法。消息认证码的算法中,通常会使用带密钥的散列函数(HMAC),或者块密码的带认证工作模式(如CBC-MAC)。信息鉴别码不能提供对信息的保密,若要同时实现保密认证,同时需要对信息进行加密。下面以HMAC为例进行分析:
原理
1.计算HMAC需要一个散列函数hash(可以是md5或者sha-1)和一个密钥key。
2.算法公式
HMAC(K,M)=H(K⊕opad∣H(K⊕ipad∣M)) H 代表所采用的HASH算法(如SHA-256) K 代表认证密码 Ko 代表HASH算法的密文 M 代表一个消息输入 B 代表H中所处理的块大小,这个大小是处理块大小,而不是输出hash的大小
3.运算步骤
First-Hash = H(Ko XOR Ipad || (data to auth)) Second-Hash = H(Ko XOR Opad || First-Hash) (1) 在密钥K后面添加0来创建一个字长为B的字符串。(例如,如果K的字长是20字节,B=64字节,则K后会加入44个零字节0x00) (2) 将上一步生成的B字长的字符串与ipad做异或运算。 (3) 将数据流text填充至第二步的结果字符串中。 (4) 用H作用于第三步生成的数据流。 (5) 将第一步生成的B字长字符串与opad做异或运算。 (6) 再将第四步的结果填充进第五步的结果中。 (7) 用H作用于第六步生成的数据流,输出最终结果
应用
HMAC主要应用在身份验证中,过程如下:
iOS代码示例
//相关类文件:#include <CommonCrypto/CommonHMAC.h> -(NSString*)hmacMD5StringWithKey:(NSString*)key{ const char* keyData = key.UTF8String; const char* strData =self.UTF8String; uint8_tbuffer[CC_MD5_DIGEST_LENGTH]; //以MD5为例 CCHmac(kCCHmacAlgMD5, keyData,strlen(keyData), strData,strlen(strData), buffer); return[self stringFromBytes:buffer length:CC_MD5_DIGEST_LENGTH]; }
在对称加密算法中,使用的密钥只有一个,发收信双方都使用这个密钥对数据进行加密和解密,这就要求解密方事先必须知道加密密钥。密码学中,分组(block)密码的工作模式(mode of operation)允许使用同一个分组密码密钥对多于一块的数据进行加密,并保证其安全性。分组密码自身只能加密长度等于密码分组长度的单块数据,若要加密变长数据,则数据必须先被划分为一些单独的密码块。通常而言,最后一块数据也需要使用合适填充方式将数据扩展到匹配密码块大小的长度。一种工作模式描述了加密每一数据块的过程,并常常使用基于一个通常称为初始化向量的附加输入值以进行随机化,以保证安全。工作模式主要用来进行加密和认证。虽然工作模式通常应用于对称加密,它亦可以应用于公钥加密,例如在原理上对RSA进行处理,但在实用中,公钥密码学通常不用于加密较长的信息,而是使用结合对称加密和公钥加密的混合加密方案。
工作模式:
enum { kCCModeECB = 1, // 电码本模式(Electronic Codebook Book (ECB)) kCCModeCBC = 2, // 密码分组链接模式(Cipher Block Chaining (CBC)) kCCModeCFB = 3, // 密码反馈模式(Cipher FeedBack (CFB)) kCCModeCTR = 4, // 计数器模式(Counter (CTR)) kCCModeF8 = 5, // Unimplemented for now (not included) kCCModeLRW = 6, // Unimplemented for now (not included) kCCModeOFB = 7, // 输出反馈模式(Output FeedBack (OFB) kCCModeXTS = 8, // XEX-based Tweaked CodeBook Mode. kCCModeRC4 = 9, // RC4 as a streaming cipher is handled internally as a mode. kCCModeCFB8 = 10, // Cipher Feedback Mode producing 8 bits per round. };
填充模式:
iOS支持的填充模式有PKCS7Padding(kCCOptionPKCS7Padding表示,缺几位就补几个几)。
enum { ccNoPadding = 0, ccPKCS7Padding = 1, };
3DES原理
3DES使用“密钥包”,其包含3个DES密钥,K1,K2和K3,均为56位(除去奇偶校验位)。加密算法为:
密文 = EK3(DK2(EK1(明文))) 即:使用K1为密钥进行DES加密,再用K2为密钥进行DES“解密”,最后以K3进行DES加密。
而解密则为其反过程:
明文 = DK1(EK2(DK3(密文))) 即:以K3解密,以K2“加密”,最后以K1解密。
每次加密操作都只处理64位数据,称为一块。无论是加密还是解密,中间一步都是前后两步的逆。这种做法提高了使用密钥选项2时的算法强度,并在使用密钥选项3时与DES兼容。
AES加密算法(Advanced Encryption Standard,AES),是美国联邦政府采用的一种区块加密标准。这个标准用来替代原先的DES。AES的基本要求是,采用对称分组密码体制,密钥的长度最少支持为128、192、256,但分组长度为128位,算法应易于各种硬件和软件实现。三种密钥长度对比如下:
iOS代码示例
//AES128密钥长度128位(16x8),通常16个字符,例如:”0123456789123456“ -(NSData *)AES128_DecryptWithKey:(NSString *)key{ char keyPtr[kCCKeySizeAES128 + 1]; bzero(keyPtr, sizeof(keyPtr)); [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding]; size_t bufferSize = self.length + kCCBlockSizeAES128; void *buffer = malloc(bufferSize); size_t numBytesEncrypted = 0; // CCCrypt 是常用简易方法,支持ECB和CBC两种工作模式,如果CCCrypt不能满足,可换用CCCryptorCreateWithMode方法 CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding | kCCOptionECBMode, // 采用ECB工作模式,PCKS7填充 keyPtr, //密钥长度128位 kCCBlockSizeAES128, NULL, //ECB模式不需要初始化向量 self.bytes, self.length, buffer, bufferSize, &numBytesEncrypted); if (cryptStatus == kCCSuccess) { return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted]; } free(buffer); return nil; }
是密码学的一种算法,它需要两个密钥,一个是公开密钥,另一个是私有密钥;一个用作加密的时候,另一个则用作解密。使用其中一个密钥把明文加密后所得的密文,只能用相对应的另一个密钥才能解密得到原本的明文;甚至连最初用来加密的密钥也不能用作解密。由于加密和解密需要两个不同的密钥,故被称为非对称加密。与对称密码相比,非对称加密密钥交换安全,安全性高,不过,公钥加密在在计算上相当复杂,性能欠佳、远远不比对称加密;因此,在一般实际情况下,往往通过公钥加密来随机创建临时的对称秘钥,然后才通过对称加密来传输大量、主体的数据。常见的公钥加密算法有:RSA、ElGamal、背包算法、Rabin(RSA的特例)、迪菲-赫尔曼密钥交换协议中的公钥加密算法、椭圆曲线加密算法(英语:Elliptic Curve Cryptography, ECC)。
RSA是目前最有影响力的公钥加密算法,对极大整数做因数分解的难度决定了RSA算法的可靠性。
原理
RSA公钥密码体制描述如下:(m为明文,c为密文,利用欧拉公式)
特点
安全性
应用