常用加密算法:
- DES:Data Encryption Standard,即数据加密算法,它是IBM公司于1975年研究成功并公开发表的。
- DES(数据加密标准)原理:
DES是一个分组加密算法,它以64位为分组对数据加密。64位一组的明文从算法的一端输入,64位的密文从另一段输出。它是一个对称算法:加密和解密用的是同一个算法。
密钥通常表示为64位的数,但每个第8位都用作奇偶校验,可以忽略,所以密钥长度为56位。密钥可以是任意的56位的数,且可在任意的时候改变。
DES算法只不过是加密的两个基本技术——混乱和扩散的组合,即先代替后置换,它基于密钥作用于明文,这是一轮(round),DES在明文分组上实施16轮相同的组合技术。
DES现在用的比较少,因为它的加密强度不够,能够暴力破解!!还有一个3DES,原理和DES几乎是一样的,只是使用3个密钥,对相同的数据执行三次加密,增强加密强度,但是要维护3个密钥,大大增加了维护成本!
- AES:高级加密标准,这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用。高级加密标准已然成为对称密钥加密中最流行的算法之一。
- AES:高级加密原理:
- AES 是一个新的可以用于保护电子数据的加密算法。明确地说,AES 是一个迭代的、对称密钥分组的密码,它可以使用128、192 和 256 位密钥,并且用 128 位(16字节)分组加密和解密数据。与公共密钥密码使用密钥对不同,对称密钥密码使用相同的密钥加密和解密数据。通过分组密码返回的加密数据 的位数与输入数据相同。迭代加密使用一个循环结构,在该循环中重复置换(permutations )和替换(substitutions)输入数据。Figure 1 显示了 AES 用192位密钥对一个16位字节数据块进行加密和解密的情形。
- MD5:Message-Digest Algorithm 5(信息-摘要算法5),用于确保信息传输完整一致。是计算机广泛使用的杂凑算法之一(又译摘要算法、哈希算法),主流编程语言普遍已有MD5实现。这个应该是听到最多的算法,据说是已经被破解了。但是我觉得破解这个应该也要很久吧!
- MD5加密原理:
- 对MD5算法简要的叙述可以为:MD5以512位分组来处理输入的信息,且每一分组又被划分为16个32位子分组,经过了一系列的处理后,算法的输出由四个32位分组组成,将这四个32位分组级联后将生成一个128位散列值
- Base64:Base64是网络上最常见的用于传输8Bit字节代码的编码方式之一。Base64编码可用于在HTTP环境下传递较长的标识信息。例如,在Java Persistence系统Hibernate中,就采用了Base64来将一个较长的唯一 标识符(一般为128-bit的UUID)编码为一个字符串,用作HTTP表单和HTTP GET URL中的参数。在其应用程序中,也常常需要把二进制数据编码为适合放在URL(包括隐藏表单域)中的形式。此时,采用Base64编码具有不可读性,即所编码的数据不会被人用肉眼所直接看到。
- RSA 加密方式:
RSA 加密方式相信每一个对接过支付宝SDK的同学都听过这个RSA加密,因为支付宝SDK的加密方式采用的就是这种。
它的一个大致额历程是这样:
1、生成你的公钥给支付宝,注册支付宝SDK之后你也可以拿到支付宝公钥。
2、上传你的公钥到支付宝,用你的私钥加密你的信息,支付包用你上传的公钥解密你传给支付宝的信息。
3、用你拿到的支付宝的公钥解密支付宝回调给你的信息。
注意:不要把这新秘钥信息存放在客户端,存放在服务端也建议不要使用明文的形式存储,安全问题!有些说把秘钥制作成.a文件的形式存放的客户端,问题反编译之后直接拿到你这份.a文件是不是也可以用用呢?
RSA是目前最有影响力的公钥加密算法,该算法基于一个十分简单的数论事实:将两个大素数相乘十分容易,但那时想要对其乘积进行因式分解却极其困难,
因此可以将乘积公开作为加密密钥,即公钥,而两个大素数组合成私钥。公钥是可发布的供任何人使用,私钥则为自己所有,供解密之用。
加密模式
我们通过下面的两张图解释一下这俩种加密模式,因为在后面的代码解读中我们会涉及到这一点,要是不了解后面代码中有些点可能会犯迷糊:
ECB:电子密码本,就是每个块都是独立加密的。
CBC:密码块链,使用一个密钥和一个初始化向量(IV)对数据执行加密转换。
重点说说它们的代码部分
(首先说明DES由于自身的缺陷,就不再去研究看它的代码了,我们这里研究的也不会特别深,主要是为了在项目中的使用)
先说说这个类: CCCryptorStatus
关于CCCryptorStatus,构造它可以使用CCCrypt、
CCCryptorCreateWithMode
、CCCryptorCreate
等好多类构造,在使用这些类构造时对参数是比较多,我们看着它们的头文件,解读一下参数的含义,我们就用CCCrypt为例说明一下,下面是CCCrypt的结构代码:
CCCryptorStatus CCCrypt( CCOperation op, /* kCCEncrypt, etc. */ CCAlgorithm alg, /* kCCAlgorithmAES128, etc. */ CCOptions options, /* kCCOptionPKCS7Padding, etc. */ const void *key, size_t keyLength, const void *iv, /* optional initialization vector */ const void *dataIn, /* optional per op and alg */ size_t dataInLength, void *dataOut, /* data RETURNED here */ size_t dataOutAvailable, size_t *dataOutMoved) __OSX_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_2_0);
理解了它的参数在我们写AES加密代码的时候是有很大的帮助的,下面是它的头文件中Apple给的参数解释,我们解释一下:
// 设置加密参数 /*! @function CCCrypt @abstract Stateless, one-shot encrypt or decrypt operation. This basically performs a sequence of CCCrytorCreate(), CCCryptorUpdate(), CCCryptorFinal(), and CCCryptorRelease(). @param alg Defines the encryption algorithm.定义加密的算法 alg: enum { kCCAlgorithmAES128 = 0, kCCAlgorithmAES = 0, kCCAlgorithmDES, kCCAlgorithm3DES, kCCAlgorithmCAST, kCCAlgorithmRC4, kCCAlgorithmRC2, kCCAlgorithmBlowfish }; @param op Defines the basic operation: kCCEncrypt or kCCDecrypt. 定义加密还是解密 下面是补码方式 enum { kCCOptionPKCS7Padding = 0x0001, kCCOptionECBMode = 0x0002}; @param options A word of flags defining options. See discussion for the CCOptions type. // 加密的key @param key Raw key material, length keyLength bytes. // 加密的key的长度 @param keyLength Length of key material. Must be appropriate for the select algorithm. Some algorithms may provide for varying key lengths. // IV 向量 @param iv Initialization vector, optional. Used for Cipher Block Chaining (CBC) mode. If present, must be the same length as the selected algorithm's block size. If CBC mode is selected (by the absence of any mode bits in the options flags) and no IV is present, a NULL (all zeroes) IV will be used. This is ignored if ECB mode is used or if a stream cipher algorithm is selected. For sound encryption, always initialize IV with random data. IV向量:大概意思说,此属性可选,但只能用于CBC模式。 如果出现那么他的长度必须和算法的block size保持一致。 如果是因为默认选择的CBC模式而且向量没有定义,那么向量会被定义为NULL。 如果选择了ECB模式或是其他的流密码算法,之前所说的逻辑都不成立。 NOTE**** 如果你想使用密钥偏移量IV 那你的加密模式必须为CBC,不能使用别的模式 // 需要加密或者解密处理的data以及data的长度 @param dataIn Data to encrypt or decrypt, length dataInLength bytes. @param dataInLength Length of data to encrypt or decrypt. // 加密或者解密后的数据会写在这个data中 以及它的长度 @param dataOut Result is written here. Allocated by caller. Encryption and decryption can be performed "in-place", with the same buffer used for input and output. @param dataOutAvailable The size of the dataOut buffer in bytes. // @param dataOutMoved On successful return, the number of bytes written to dataOut. If kCCBufferTooSmall is returned as a result of insufficient buffer space being provided, the required buffer space is returned here. //几种错误情况的说明 @result kCCBufferTooSmall indicates insufficent space in the dataOut buffer.(表明dataOut的空间不足) In this case, the *dataOutMoved parameter will indicate the size of the buffer needed to complete the operation. The operation can be retried with minimal runtime penalty. kCCAlignmentError indicates that dataInLength was not properly aligned. This can only be returned for block ciphers, and then only when decrypting or when encrypting with block with padding disabled. kCCDecodeError Indicates improperly formatted ciphertext or a "wrong key" error; occurs only during decrypt operations. 我们可以通过下面的解释解读一下这个result、具体的结果可以看下面的解释 @enum CCCryptorStatus @abstract Return values from CommonCryptor operations. enum { kCCSuccess Operation completed normally. kCCParamError Illegal parameter value. kCCBufferTooSmall Insufficent buffer provided for specified operation. kCCMemoryFailure Memory allocation failure. kCCAlignmentError Input size was not aligned properly. kCCDecodeError Input data did not decode or decrypt properly. kCCUnimplemented Function not implemented for the current algorithm. } */
AES加密代码
我们给出的就是具体的AES加密方式的代码,涉及到的其他的Base64编码方式等等这些我们就不在专门去写代码,这个在Demo中都有,需要的建议去翻翻Demo:
- (NSData *)aes256_encrypt:(NSString *)key //加密 { // kCCKeySizeAES256是加密位数 /* enum { kCCKeySizeAES128 = 16, kCCKeySizeAES192 = 24, kCCKeySizeAES256 = 32, kCCKeySizeDES = 8, kCCKeySize3DES = 24, kCCKeySizeMinCAST = 5, kCCKeySizeMaxCAST = 16, kCCKeySizeMinRC4 = 1, kCCKeySizeMaxRC4 = 512, kCCKeySizeMinRC2 = 1, kCCKeySizeMaxRC2 = 128, kCCKeySizeMinBlowfish = 8, kCCKeySizeMaxBlowfish = 56, }; */ char keyPtr[kCCKeySizeAES256+1]; bzero(keyPtr, sizeof(keyPtr)); [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding]; //IV NSUInteger dataLength = [self length]; size_t bufferSize = dataLength + kCCBlockSizeAES128; void * buffer = malloc(bufferSize); size_t numBytesEncrypted = 0; CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding | kCCOptionECBMode, keyPtr, kCCBlockSizeAES128, NULL, [self bytes], dataLength, buffer, bufferSize, &numBytesEncrypted); if (cryptStatus == kCCSuccess) { return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted]; } free(buffer); return nil; } -(NSData *)aes256_decrypt:(NSString *)key //解密 { //key 处理 char keyPtr[kCCKeySizeAES256+1]; bzero(keyPtr, sizeof(keyPtr)); [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding]; /*IV char ivPtr[kCCBlockSizeAES128 + 1]; bzero(ivPtr, sizeof(ivPtr)); [iv getCString:ivPtr maxLength:sizeof(ivPtr) encoding:NSUTF8StringEncoding]; */ // 输出对象 NSUInteger dataLength = [self length]; size_t bufferSize = dataLength + kCCBlockSizeAES128; void *buffer = malloc(bufferSize); size_t numBytesDecrypted = 0; //kCCDecrypt 解密 CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding | kCCOptionECBMode, keyPtr, kCCBlockSizeAES128, NULL, [self bytes], dataLength, buffer, bufferSize, &numBytesDecrypted); if (cryptStatus == kCCSuccess) { return [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted]; } free(buffer); return nil; }
最后:
针对Base64位的编码方式有的第三方比如:GTMBase64
或者是针对DES的第三方比如:SSkeychain
这些网上文章的确比较多了,我们再总结也就没有了什么意义。下面是我参考也是收集的一下关于加密算法的总结,提供给大家。