1. 对称加密:

需要对加密和解密使用相同密钥的加密算法。由于其速度快,对称性加密通常在消息发送方需要加密大量数据时使用。对称性加密也称为密钥加密。
所谓对称,就是采用这种加密方法的双方使用方式用同样的密钥进行加密和解密。密钥是控制加密及解密过程的指令。算法是一组规则,规定如何进行加密和解密。
因此 [1] 加密的安全性不仅取决于加密算法本身,密钥管理的安全性更是重要。因为加密和解密都使用同一个密钥,如何把密钥安全地传递到解密者手上就成了必须要解决的问题。

DES

DES(全程Data Encryption Standard)即数据加密标准,是一种使用密钥加密的块算法,1977年被美国联邦政府的国家标准局确定为联邦资料处理标准(FIPS),并授权在非密级政府通信中使用,随后该算法在国际上广泛流传开来。需要注意的是,在某些文献中,作为算法的DES称为数据加密算法(Data Encryption Algorithm,DEA),已与作为标准的DES区分开来。

DES代码

.h文件// 加密方法
+ (NSString*)encrypt:(NSString*)plainText;
// 解密方法
+ (NSString*)decrypt:(NSString*)encryptText;.m文件// 加密方法
+ (NSString*)encrypt:(NSString*)plainText {NSData* data = [plainText dataUsingEncoding:NSUTF8StringEncoding];size_t plainTextBufferSize = [data length];const void *vplainText = (const void *)[data bytes];CCCryptorStatus ccStatus;uint8_t *bufferPtr = NULL;size_t bufferPtrSize = 0;size_t movedBytes = 0;bufferPtrSize = (plainTextBufferSize + kCCBlockSize3DES) & ~(kCCBlockSize3DES - 1);bufferPtr = malloc( bufferPtrSize * sizeof(uint8_t));memset((void *)bufferPtr, 0x0, bufferPtrSize);const void *vkey = (const void *) [gkey UTF8String];const void *vinitVec = (const void *) [gIv UTF8String];ccStatus = CCCrypt(kCCEncrypt,kCCAlgorithm3DES,kCCOptionPKCS7Padding,vkey,kCCKeySize3DES,vinitVec,vplainText,plainTextBufferSize,(void *)bufferPtr,bufferPtrSize,&movedBytes);NSData *myData = [NSData dataWithBytes:(const void *)bufferPtr length:(NSUInteger)movedBytes];NSString *result = [GTMBase64 stringByEncodingData:myData];return result;
}// 解密方法
+ (NSString*)decrypt:(NSString*)encryptText {NSData *encryptData = [GTMBase64 decodeData:[encryptText dataUsingEncoding:NSUTF8StringEncoding]];size_t plainTextBufferSize = [encryptData length];const void *vplainText = [encryptData bytes];CCCryptorStatus ccStatus;uint8_t *bufferPtr = NULL;size_t bufferPtrSize = 0;size_t movedBytes = 0;bufferPtrSize = (plainTextBufferSize + kCCBlockSize3DES) & ~(kCCBlockSize3DES - 1);bufferPtr = malloc( bufferPtrSize * sizeof(uint8_t));memset((void *)bufferPtr, 0x0, bufferPtrSize);const void *vkey = (const void *) [gkey UTF8String];const void *vinitVec = (const void *) [gIv UTF8String];ccStatus = CCCrypt(kCCDecrypt,kCCAlgorithm3DES,kCCOptionPKCS7Padding,vkey,kCCKeySize3DES,vinitVec,vplainText,plainTextBufferSize,(void *)bufferPtr,bufferPtrSize,&movedBytes);NSString *result = [[NSString alloc] initWithData:[NSData dataWithBytes:(const void *)bufferPtrlength:(NSUInteger)movedBytes] encoding:NSUTF8StringEncoding];return result;
}.m文件需要导入的头文件及宏定义
#import "DESUtil.h"
#import <CommonCrypto/CommonCryptor.h>
#import "GTMBase64.h"
#define gkey            @"0123456789ABCDEFGHI"
#define gIv             @"01234567"
//使用的话 只需更改gkey及gIv。

重点:

  • 如果密码位数少于等于64位,加密结果与DES相同;
  • 秘钥长度128位,192位,即16或24个字符组成的字符串;
  • 常用ECB 和 BCB 模式加密计算。

AES

AES(全称Advance Encryption Standard)高级加密标准,在密码学中又成Rijndael加密法,是美国联邦政府采用的一种区块加密标准。这个标准用来替代原先的DES。AES属于块加密(Block Cipher),块加密中有CBC、ECB、CTR、OFB、CFB等几种工作模式。常用的为CBC和ECB模式,

ECB模式

这种模式是将整个明文分成若干段相同的小段,然后对每一小段进行加密。

CBC模式

这种模式是先将明文切分成若干小段,然后每一小段与初始块或者上一段的密文段进行异或运算后,再与密钥进行加密。
需要注意的是CBC模式需要传一个16位的向量值,不传的话,默认为空,空的话就属于ECB模式。

AES代码(CBC模式)

.h文件NSString * aesEncryptString(NSString *content, NSString *key);
NSString * aesDecryptString(NSString *content, NSString *key);
NSData * aesEncryptData(NSData *data, NSData *key);
NSData * aesDecryptData(NSData *data, NSData *key);.m文件NSData * cipherOperation(NSData *contentData, NSData *keyData, CCOperation operation) {NSUInteger dataLength = contentData.length;void const *initVectorBytes = [kInitVector dataUsingEncoding:NSUTF8StringEncoding].bytes;void const *contentBytes = contentData.bytes;void const *keyBytes = keyData.bytes;size_t operationSize = dataLength + kCCBlockSizeAES128;void *operationBytes = malloc(operationSize);size_t actualOutSize = 0;CCCryptorStatus cryptStatus = CCCrypt(operation,kCCAlgorithmAES,kCCOptionPKCS7Padding,keyBytes,kKeySize,initVectorBytes,contentBytes,dataLength,operationBytes,operationSize,&actualOutSize);if (cryptStatus == kCCSuccess) {return [NSData dataWithBytesNoCopy:operationBytes length:actualOutSize];}free(operationBytes);return nil;
}NSString * aesEncryptString(NSString *content, NSString *key) {NSData *contentData = [content dataUsingEncoding:NSUTF8StringEncoding];NSData *keyData = [key dataUsingEncoding:NSUTF8StringEncoding];NSData *encrptedData = aesEncryptData(contentData, keyData);return [encrptedData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];
}NSString * aesDecryptString(NSString *content, NSString *key) {NSData *contentData = [[NSData alloc] initWithBase64EncodedString:content options:NSDataBase64DecodingIgnoreUnknownCharacters];NSData *keyData = [key dataUsingEncoding:NSUTF8StringEncoding];NSData *decryptedData = aesDecryptData(contentData, keyData);return [[NSString alloc] initWithData:decryptedData encoding:NSUTF8StringEncoding];
}NSData * aesEncryptData(NSData *contentData, NSData *keyData) {return cipherOperation(contentData, keyData, kCCEncrypt);
}NSData * aesDecryptData(NSData *contentData, NSData *keyData) {return cipherOperation(contentData, keyData, kCCDecrypt);
}
.m文件中需要定义两个常量NSString const *kInitVector = @"16-Bytes--String";
size_t const kKeySize = kCCKeySizeAES128;
第一个为向量值,如果直接传空字符串,则为ECB模式,否则为CBC。本例中为CBC模式。
+ (NSData *)aes256Encryption:(NSData *)originDataencryptKey:(NSString *)key
{if (!originData || !key) {return nil;}char keyPtr[kCCKeySizeAES256 + 1];bzero(keyPtr, sizeof(keyPtr));[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];NSUInteger dataLength = [originData length];size_t bufferSize = dataLength + kCCBlockSizeAES128;void *buffer = malloc(bufferSize);size_t numBytesEncrypted = 0;CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding | kCCOptionECBMode, keyPtr, kCCBlockSizeAES128, NULL, [originData bytes], dataLength, buffer, bufferSize, &numBytesEncrypted);if (cryptStatus == kCCSuccess) {return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];}free(buffer);return nil;
}+ (NSData *)aes256Decryption:(NSData *)originDatadecryptKey:(NSString *)key
{if (!originData || !key) {return nil;}char keyPtr[kCCKeySizeAES256+1];bzero(keyPtr, sizeof(keyPtr));[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];NSUInteger dataLength = [originData length];size_t bufferSize = dataLength + kCCBlockSizeAES128;void *buffer = malloc(bufferSize);size_t numBytesDecrypted = 0;CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128,kCCOptionPKCS7Padding | kCCOptionECBMode,keyPtr, kCCBlockSizeAES128,NULL,[originData bytes], dataLength,buffer, bufferSize,&numBytesDecrypted);if (cryptStatus == kCCSuccess) {return [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted];}free(buffer);return nil;
}
  1. 非对称加密

加密和解密秘钥不同,一个是公钥一个是私钥

优点

  • 加密强度小,加密时间长,常用于数字签名和加密秘钥
  • 非对称加密算法有两种密钥,其中一个是公开的,所以在密钥传输上不存在安全性问题,使得其在传输加密数据的安全性上又高于对称加密算法。

缺点

加密解密的速度远远低于对称加密算法,因此不适用于数据量较大的情况

RSA加密算法
RSA简介

RSA加密算法是一种非对称加密算法,密钥为一对公钥和私钥组成。通常把公钥发送给使用方,私钥由接收方自己保存

RSA优点

解决了对称加密算法如何保存密钥的问题

RSA缺点

由于RSA算法的原理都是大数计算,使得RSA最快的情况也比对称加密算法慢上好几倍。速度一直是RSA的缺陷,一般来说RSA只用于小数据的加密.RSA的速度是对应同样安全级别的对称加密算法的1/1000左右。

RSA的长度

**秘钥长度:**秘钥长度一般是96bits~1024bits
**明文长度:**明文的长度(bytes) <= 秘钥长度(bytes) - 1(bytes)这样 128字节(1024bits)-减去11字节正好是117字节 。所以明文长度的最大值决定了RSA的最大瓶颈也就是一次加密的数量有限,可以用分片来解决,但分片的方法某些情况下给服务器解密带来一定的问题。
最佳解决方案: AES+RSA混合加密
密文长度:
不分片:密文长度 = 明文长度
分片: 密文长度 = 秘钥长度 * 片数

RSA特点

公钥加密,私钥解密。加密的系统和解密系统分开部署。加密的系统不应该同时具备解密的功能

注意

RSA加密的明文最大长度117字节,如果超过117字节则程序会报错

使用openssl 生成所需要的密钥文件

代码示例

#import "ZMMSecurityUtil.h"
#import "ZMMBase64.h"#define RSAPublicFileName @"公钥文件名"
#define RSAPublicFileType @"公钥文件类型"static NSString *RSAEncryptString(NSString *str)
{SecKeyRef key = securityUtil.SecKeyRefCopyPublicKey();NSError *error = nil;NSString *result = nil;if (key!=NULL) {NSData *data = securityUtil.encryptString(str,key,&error);result = [ZMMBase64 encodeStringWithData:data];CFRelease(key);}if (!result) {return nil;}return result;
}static NSData *RSAEncryptStringResultsData(NSString *str)
{SecKeyRef key = securityUtil.SecKeyRefCopyPublicKey();NSError *error = nil;NSData *reslut = nil;if (key!=NULL) {reslut = securityUtil.encryptString(str,key,&error);CFRelease(key);}if (!reslut) {return nil;}return reslut;
}static SecKeyRef SecKeyRefCopyPublicKey()
{NSString *certPath = [[NSBundle mainBundle] pathForResource:RSAPublicFileName ofType:RSAPublicFileType];NSData *certData = [[NSData alloc] initWithContentsOfFile:certPath];if (!certData) {return nil;}SecCertificateRef cert = SecCertificateCreateWithData(kCFAllocatorDefault, (__bridge CFDataRef)certData);CFArrayRef certs = CFArrayCreate(kCFAllocatorDefault, (const void **)&cert, 1, NULL);SecTrustRef trust = NULL;SecKeyRef pub_key_leaf = NULL;SecPolicyRef policy = NULL;if (certs != NULL) {policy = SecPolicyCreateBasicX509();SecTrustCreateWithCertificates(certs, policy, &trust);CFErrorRef *trustResult = NULL;if (SecTrustEvaluateWithError(trust, trustResult) == noErr) {pub_key_leaf = SecTrustCopyPublicKey(trust);}}if (cert != NULL) {CFRelease(cert);}if (certs != NULL) {CFRelease(certs);}if (trust != NULL) {CFRelease(trust);}if (policy != NULL) {CFRelease(policy);}return pub_key_leaf;
}static NSData *encryptString(NSString *inString,SecKeyRef keyRef,NSError **err)
{size_t cipherBufferSize = SecKeyGetBlockSize(keyRef);uint8_t *cipherBuffer = malloc(cipherBufferSize * sizeof(uint8_t));NSData *stringBytes = [inString dataUsingEncoding:NSUTF8StringEncoding];NSInteger blockSize = cipherBufferSize - 11;NSInteger blockCount = (NSInteger)ceil([stringBytes length] / (double)blockSize);NSMutableData *encryptedData = [[NSMutableData alloc] init];for (NSInteger i=0; i<blockCount; i++) {NSInteger bufferSize = MIN(blockSize,[stringBytes length]-i * blockSize);NSData *buffer = [stringBytes subdataWithRange:NSMakeRange(i * blockSize, bufferSize)];OSStatus status = SecKeyEncrypt(keyRef,kSecPaddingPKCS1,(const uint8_t *)[buffer bytes],[buffer length],cipherBuffer,&cipherBufferSize);if (status == noErr){NSData *encryptedBytes = [[NSData alloc]initWithBytes:(const void *)cipherBufferlength:cipherBufferSize];[encryptedData appendData:encryptedBytes];}else{if (err) {*err = [NSError errorWithDomain:@"fail" code:status userInfo:nil];}(void)(free(cipherBuffer));if (keyRef) {CFRelease(keyRef);}return nil;}}(void)(free(cipherBuffer));if (keyRef) {CFRelease(keyRef);}return encryptedData;
}const struct ZMMSecurityUtil securityUtil = {.SecKeyRefCopyPublicKey = SecKeyRefCopyPublicKey,.RSAEncryptString = RSAEncryptString,.encryptString = encryptString,.RSAEncryptStringResultsData = RSAEncryptStringResultsData,};

3.AES+RSA混合加密
场景

打开应用的第一次登陆大概需要发送1000个字节,用RSA全部加密,由于RSA加密的特性,秘钥长度最大128字节,也就是一次加密的明文是117字节,超出的部分使用分片多次加密,那我们需要分9次,服务端在解密的时候也是耗时的,对性能造成了很大的影响。如果使用AES加密,可以做到一次性加密,但是秘钥的传输成了最大的问题,接收方独自拥有秘钥才安全。

方案

RSA先对AES的秘钥加密,在接收方对RSA解密得到秘钥,用该秘钥对AES进行解密得到所有明文。

流程

  • 1.服务器端(server)分别生成自己的RSA密钥对,并提供接口给客户端获取RSA公钥(RSAPublicKey)
  • 2.客户端拿到RSA公钥,随机生成AES的秘钥(AESKey),
  • 3.用RSA公钥(RSAPublicKey)使用RSA加密方式对AES的秘钥(AESKey)加密得到= RSA加密过后的AES秘钥(AESKeyAfertRSA)
  • 4.传输数据(Data)用RSA加密过后的AES秘钥(AESKeyAfertRSA) 使用AES加密的方式进行加密得到数据(AESData)
  • 5.将 RSA加密过后的AES秘钥(AESKeyAfertRSA) 和 使用AES加密的方式进行加密得到数据(AESData) 拼接起来传输给服务端(server)
  • 6.服务端用之前RSA生成的私钥解密 将 RSA加密过后的AES秘钥(AESKeyAfertRSA)拿到AES的秘钥(AESKey)在通过AES的秘钥拿到明文数据

代码示例

 //1.获取AES的秘钥NSString *AESKeyString = [ZMMEncryptionModel getAES256EncryptKey];//2.把AES的秘钥使用RSA加密NSData *encrptionData = securityUtil.RSAEncryptStringResultsData(AESKeyString);//3.把RSA加密过的AES的秘钥转化16进制字符串NSString *encryptKey = [NSData convertStringFromData:encrptionData];//4.需要加密的数据NSData *needEncrptionData = [ZMMEncryptionModel getNeedAES256Data];//5.AES加密过的数据NSData *AESPhEnAfterData = [NSData aes256Encryption:needEncrptionData encryptKey:encryptKey];//6.把AES加密过的数据 和秘钥 拼接字符串传给服务端NSString *reslut = [NSString stringWithFormat:@"%@,%@",AESPhEnAfterData,encryptKey];NSLog(@"传给服务端的数据%@",reslut);

base64加密
定义

Base64编码,是我们程序开发中经常使用到的编码方法。它是一种基于用64个可打印字符来表示二进制数据的表示方法

Base64简单说明

特点:可以将任意的二进制数据进行Base64编码
结果:所有的数据都能被编码为并只用65个字符就能表示的文本文件。
65字符:A~Z a~z 0~9 + / =
对文件进行base64编码后文件数据的变化:编码后的数据~=编码前数据的4/3,会大1/3左右。

Base64编码原理

1)将所有字符转化为ASCII码;
2)将ASCII码转化为8位二进制;
3)将二进制3个归成一组(不足3个在后边补0)共24位,再拆分成4组,每组6位;
4)统一在6位二进制前补两个0凑足8位;
5)将补0后的二进制转为十进制;
6)从Base64编码表获取十进制对应的Base64编码;

处理过程说明

a.转换的时候,将三个byte的数据,先后放入一个24bit的缓冲区中,先来的byte占高位。
b.数据不足3byte的话,于缓冲区中剩下的bit用0补足。然后,每次取出6个bit,按照其值选择查表选择对应的字符作为编码后的输出。
c.不断进行,直到全部输入数据转换完成。
d.如果最后剩下两个输入数据,在编码结果后加1个“=”;
e.如果最后剩下一个输入数据,编码结果后加2个“=”;
f.如果没有剩下任何数据,就什么都不要加,这样才可以保证资料还原的正确性。

代码示例

//base64解码
+ (nullable NSString *)decodeString:(NSString *)string {if (!string) {return nil;}NSData *data=[[NSData alloc]initWithBase64EncodedString:string options:0];if (data) {return [[NSString alloc]initWithData:dataencoding:NSUTF8StringEncoding];;}return nil;
}
//base64编码
+ (nullable NSString *)encodeString:(NSString *)string
{if (!string) {return nil;}NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];if (data) {return [data base64EncodedStringWithOptions:0];}return nil;
}

4.信息摘要(Hash)
MD5
定义

MD5即Message-Digest Algorithm 5(消息-摘要算法5),为计算机安全领域广泛使用的一种散列函数,用以提供消息的完整性保护(又译摘要算法、哈希算法),主流编程语言普遍已有MD5实现。将数据运算为另一固定长度值,是杂凑算法的基础原理,MD5的前身有MD2、MD3和MD4

MD5特点

1、压缩性:任意长度的数据,算出的MD5值长度都是固定的。
2、容易计算:从原数据计算出MD5值很容易。
3、抗修改性:对原数据进行任何改动,哪怕只修改1个字节,所得到的MD5值都有很大区别。
4、弱抗碰撞:已知原数据和其MD5值,想找到一个具有相同MD5值的数据(即伪造数据)是非常困难的。
5、强抗碰撞:想找到两个不同的数据,使它们具有相同的MD5值,是非常困难的。
6、MD5加密是不可解密的,但是网上有一些解析MD5的,那个相当于一个大型的数据库,通过匹配MD5去找到原密码。所以,只要在要加密的字符串前面加上一些字母数字符号或者多次MD5加密,这样出来的结果一般是解析不出来的。

MD5好处

1、压缩到固定长度128bit,长度小适合互联网传输;
2、相同文件多次压缩的值不变,常用于对文件的是否被篡改的校验;
3、不同文件压缩后出现值冲突的几率很小;
4、md5算法比同类的sha-1计算速度快;

MD5应用

1、一致性验证:MD5的典型应用是对一段信息(Message)产生信息摘要(Message-Digest),以防止被篡改。MD5就可以为任何文件(不管其大小、格式、数量)产生一个同样独一无二的“数字指纹”,如果任何人对文件做了任何改动,其MD5值也就是对应的“数字指纹”都会发生变化。
2、数字签名:MD5的典型应用是对一段Message(字节串)产生fingerprint(指纹),以防止被“篡改”。举个例子,你将一段话写在一个叫 readme.txt文件中,并对这个readme.txt产生一个MD5的值并记录在案,然后你可以传播这个文件给别人,别人如果修改了文件中的任何内容,你对这个文件重新计算MD5时就会发现(两个MD5值不相同)。如果再有一个第三方的认证机构,用MD5还可以防止文件作者的“抵赖”,这就是所谓的数字签名应用。
3、安全访问认证:MD5还广泛用于操作系统的登陆认证上,如Unix、各类BSD系统登录密码、数字签名等诸多方面。如在Unix系统中用户的密码是以MD5(或其它类似的算法)经Hash运算后存储在文件系统中。当用户登录的时候,系统把用户输入的密码进行MD5 Hash运算,然后再去和保存在文件系统中的MD5值进行比较,进而确定输入的密码是否正确。通过这样的步骤,系统在并不知道用户密码的明码的情况下就可以确定用户登录系统的合法性。这可以避免用户的密码被具有系统管理员权限的用户知道。

客户端应用

1、本地数据加密:对NSUserDefaults,qlite,存储文件数据加密,保护帐号和关键信息。
2、URL编码加密:对程序中出现的URL进行编码加密,防止URL被静态分析
3、网络传输数据加密:对客户端传输数据提供加密方案,有效防止通过网络接口的拦截获取
4、方法体,方法名高级混淆:对应用程序的方法名和方法体进行混淆,保证源码被逆向后无法解析代码
5、程序结构混排加密:对应用程序逻辑结构进行打乱混排,保证源码可读性降到最低

MD5虽然说是不可逆的,但是由于有网站的存在,专门用来查询MD5码,所以有的简单的MD5码是可以在这里搜到源码的。为了让MD5码更加安全 涌现了很多其他方法,如加盐。盐要足够长足够乱得到的MD5码就很难查到。

MD5字符串加密

- (NSString *)md5_32bit
{//MD5是基于C语言的,先转化为C字符串const char * str = [self UTF8String];//创建一个数组,接受MD5加密的值uint8_t outputBuffer[CC_MD5_DIGEST_LENGTH];//把str字符串转换成了32位的16进制数列(这个过程不可逆转) 存储到了result这个空间中CC_MD5(str, (CC_LONG)strlen(str), outputBuffer);NSMutableString *outputString = [[NSMutableString alloc] initWithCapacity:CC_MD5_DIGEST_LENGTH * 2];//把C字符串取出来,转化成NSString类型for(NSInteger count = 0; count < CC_MD5_DIGEST_LENGTH; count++){[outputString appendFormat:@"%02x",outputBuffer[count]];}NSString *result = [outputString copy];return result;}

注意!!!!!

“CC_MD5”被弃用:第一次弃用是在iOS 13.0中。客户机应该迁移到SHA256(或更强)。

5.SHA

定义

哈希算法主要适用于数字签名标准里面定义的数字签名算法

特性

不可以从消息摘要中复原信息;两个不同的消息不会产生同样的消息摘要。

SHA 校验大文件完整性

  • 在文件超过1G的时候,不能一次性放入内存之中,但是我们还是需要将这个文件进行SHA256加密
  • 一个系统的api——update系列的方法

一般大文件下载下来,为了确定这个文件是否下载有误,或者检查此文件在下载过程中有没有损坏,我们需要进行的一步安全性操作就是大文件的SHA256加密,用你加密的字符串,和源文件的md5字符串进行校验,看是否一样

  • 客户端上传文件

上传文件,在请求的body
里面添加该文件的SHA256值来告诉服务器,服务器接收文件完毕后通过检验文件的SHA256值与请求body里面的SHA256值来最终确定本次上否成功。

  • 客户端下载文件

下载文件,在响应头里收到了服务器附带的该文件的MD5值,文件下载结束后,通过获取下载后文件的SHA256值与本次请求服务器返回的响应头中的SHA256值做一个比较来最终判断本次下载是否成功。

代码

#define FileHashDefaultChunkSizeForReadingData 1024*8+ (NSString *)getFileSHA256WithPath:(NSString* )path
{return (__bridge_transfer NSString *)FileSHA256HashCreateWithPath((__bridge CFStringRef)path, FileHashDefaultChunkSizeForReadingData);
}CFStringRef FileSHA256HashCreateWithPath(CFStringRef filePath,size_t chunkSizeForReadingData) {// Declare needed variablesCFStringRef result = NULL;CFReadStreamRef readStream = NULL;// Get the file URLCFURLRef fileURL =CFURLCreateWithFileSystemPath(kCFAllocatorDefault,(CFStringRef)filePath,kCFURLPOSIXPathStyle,(Boolean)false);if (!fileURL) goto done;// Create and open the read streamreadStream = CFReadStreamCreateWithFile(kCFAllocatorDefault,(CFURLRef)fileURL);if (!readStream) goto done;bool didSucceed = (bool)CFReadStreamOpen(readStream);if (!didSucceed) goto done;// Initialize the hash objectCC_SHA256_CTX hashObject;CC_SHA256_Init(&hashObject);// Make sure chunkSizeForReadingData is validif (!chunkSizeForReadingData) {chunkSizeForReadingData = FileHashDefaultChunkSizeForReadingData;}// Feed the data to the hash objectbool hasMoreData = true;while (hasMoreData) {uint8_t buffer[chunkSizeForReadingData];CFIndex readBytesCount = CFReadStreamRead(readStream,(UInt8 *)buffer,(CFIndex)sizeof(buffer));if (readBytesCount == -1) break;if (readBytesCount == 0) {hasMoreData = false;continue;}CC_SHA256_Update(&hashObject,(const void *)buffer,(CC_LONG)readBytesCount);}// Check if the read operation succeededdidSucceed = !hasMoreData;// Compute the hash digestunsigned char digest[CC_SHA224_DIGEST_LENGTH];CC_SHA256_Final(digest, &hashObject);// Abort if the read operation failedif (!didSucceed) goto done;// Compute the string resultchar hash[2 * sizeof(digest) + 1];for (size_t i = 0; i < sizeof(digest); ++i) {snprintf(hash + (2 * i), 3, "%02x", (int)(digest[i]));}result = CFStringCreateWithCString(kCFAllocatorDefault,(const char *)hash,kCFStringEncodingUTF8);
done:if (readStream) {CFReadStreamClose(readStream);CFRelease(readStream);}if (fileURL) {CFRelease(fileURL);}return result;

AES、DES、RSA、base64、MD5、SHA加密相关推荐

  1. 常见加密工具类Base64、DES、AES、RSA、MD5汇总

    文章目录 引言 1.Base64加密 2.DES加密 3.AES加密 4.RSA加密 5.MD5加密 引言 项目中经常会用到Base64.DES.AES.RSA.MD5几种加解密方式,每次都要去网上搜 ...

  2. Qt写的超级方便的编码转换器、加解密AES、RSA、MD5、SHA、网页编码

    Qt彻底解决乱码问题,各种编码转换工具 Qt写的超级方便的编码转换器.加解密AES.RSA.MD5.SHA.网页编码 一键把内容转换成GBK.UTF-8.UTF-16FE.UTF-16BE.GB231 ...

  3. C++ 使用Poco库进行MD5,SHA加密

    C++ 使用Poco库进行MD5,SHA加密 flyfish 头文件 #include <iostream> #include <Poco/MD5Engine.h> #incl ...

  4. Java实现Base64、DES、AES、RSA加解密以及加密方式之间的区别

    Base64 加密, 这个其实不可以算作加密方法,它可以看作是一种编码方式,它的用途只是二进制数字和字符串进行相互转化. Base64是网络上最常见的用于传输 8Bit字节码的编码方式之一,是一种基于 ...

  5. JS逆向加密-Cryptojs库AES/DES/RSA等代码

    目录 一.crypto-js 二.nodejs之md5.sha1.sha256.base64 三.crypto-js之AES 四.crypto-js之DES 五.crypto-js之3DES 六.Py ...

  6. APP安全--网络传输安全 AES/RSA/ECC/MD5/SHA

    移动端App安全如果按CS结构来划分的话,主要涉及客户端本身数据安全,Client到Server网络传输的安全,客户端本身安全又包括代码安全和数据存储安全.所以当我们谈论App安全问题的时候一般来说在 ...

  7. aes加密算法python语言实现_python实现AES/DES/RSA/MD5/SM2/SM4/3DES加密算法模板汇总

    都是作者累积的,且看其珍惜,大家可以尽量可以保存一下,如果转载请写好出处https://www.cnblogs.com/pythonywy 一.md5加密 1.简介 这是一种使用非常广泛的加密方式,不 ...

  8. golang中base64 md5 sha256的编解码及摘要算法、aes、des、sha1

    golang中base64 md5 sha256的编解码及摘要算法.aes.rsa.des.sha1 golang中base64 md5 sha256的编解码及摘要算法 关于加密解密 AES DES ...

  9. java js aes 简书_nodejs中aes-128-cbc加密和解密

    和java程序进行交互的时候,java那边使用AES 128位填充模式:AES/CBC/PKCS5Padding加密方法,在nodejs中采用对应的aes-128-cbc加密方法就能对应上,因为有使用 ...

最新文章

  1. usaco Arithmetic Progressions(看了题解)
  2. Swagger增强神器:Knife4j!用它轻松实现接口搜索、Word下载、接口过滤...
  3. springcloud(三):服务提供与调用
  4. linux文本处理工具之grep与正则表达式语法
  5. SpringMVC底层数据传输校验的方案(修改版)
  6. YII框架开发一个项目的通用目录结构:
  7. centos8 kernel source 安装_什么?你在物理机上安装Oracle总失败?那就试试Docker吧
  8. hihocoder 1032 最长回文子串(Manacher)
  9. 无需用户输入,Adobe提出自动高质量图像合成新方法
  10. 如何写标题摘要关键字
  11. 官方demo修改后的webuploader上传预览图片(兼容IE8) github下载回来的有问题
  12. 华为总是在用自己独特的方式诠释成功
  13. 99%的游戏建模师不知道的ZBrush的15个建模技巧
  14. 大数据开发工程师到底是干嘛的?日常做什么呢?
  15. sharding-jdbc系列之按月动态分表(十二)
  16. 移动页面input手机键盘中的“搜索”按键
  17. tensorflw视频
  18. cesium实现晴,雨,雾,雪等效果
  19. 哈工大c语言第四版pdf,哈工大C语言讲义 指针.pdf
  20. CVPR 2022 | 刷新low-level视觉多项第一!Restormer:图像复原又一力作!

热门文章

  1. 2018年终总结——凡是过往,皆为序章
  2. chrome 由某组织管理_Chrome为什么说它是“由您的组织管理”?
  3. CSDN日报20170304——《令人比较失落的IT圈子-关于华为裁员》
  4. JVM(java 虚拟机)
  5. matlab实现主成分回归
  6. NodeJS v0 10 8升级安装
  7. 安卓productFlavors多渠道打包简单使用
  8. centos 使用nslookup命令问题
  9. 房价预测,梯度下降法
  10. LTE:RA-RNTI、T-CRNTI、C-RNTI