iOS学习-数据加密

2019-11-13  本文已影响0人  快乐的tomato

网络传输数据需要进行加密。

一、对称算法

1、什么是对称算法

加密和解密都使用相同的密钥
特性:
速度快,适合对大数据加密。
常见的有DES、3DES、AES。最常用的是AES。

2、什么是AES加密

高级加密标准,Advanced Encryption Standard的缩写。AES 是一个分组密码算法,旨在取代 DES 成为广泛使用的标准

3、AES加密原理

image.png

4、在iOS中的实现

#pragma mark - 2、对称加密:加密、解密
-(void)aesTest{
    
    NSString *str = @"我是中国人";
    NSLog(@"原字符=%@",str);
    
    NSString *str1 = [self aesEncrypt:str] ;
    NSLog(@"aes加密后-%@",str1);
    
    NSString *str2 = [self aesDecrypt:str1];
    NSLog(@"aes解密后-%@",str2);
}

/*
 需要导入头文件
 #import <CommonCrypto/CommonDigest.h>
 #import <CommonCrypto/CommonCrypto.h>
*/
// 秘钥key
const NSString *AESKey = @"chsiahGHBh";

-(NSString *)aesEncrypt:(NSString *)sourceStr{
    
    if (!sourceStr){
        return nil;
    }
    
    char keyPtr[kCCKeySizeAES256];
    bzero(keyPtr, sizeof(keyPtr));
    [AESKey getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
     
    NSData *sourceData = [sourceStr dataUsingEncoding:NSUTF8StringEncoding];
    NSUInteger dataLength = [sourceData length];
    size_t buffersize = dataLength+kCCBlockSizeAES128;
    void *buffer = malloc(buffersize);
    size_t numBytesEncrypted = 0;
    CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding | kCCOptionECBMode, keyPtr, kCCBlockSizeAES128, NULL, [sourceData bytes], dataLength, buffer, buffersize, &numBytesEncrypted);
     
    if (cryptStatus == kCCSuccess) {
        NSData *encryptData = [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
        //对加密后的二进制数据进行base64转码
        return [encryptData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];
    } else {
        free(buffer);
        return nil;
    }
    
}

-(NSString *)aesDecrypt:(NSString *)secretStr{
    
   if (!secretStr) {
        return nil;
    }
    //先对加密的字符串进行base64解码
    NSData *decodeData = [[NSData alloc] initWithBase64EncodedString:secretStr options:NSDataBase64DecodingIgnoreUnknownCharacters];
     
    char keyPtr[kCCKeySizeAES256 + 1];
    bzero(keyPtr, sizeof(keyPtr));
    [AESKey getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
     
    NSUInteger dataLength = [decodeData length];
    size_t bufferSize = dataLength + kCCBlockSizeAES128;
    void *buffer = malloc(bufferSize);
    size_t numBytesDecrypted = 0;
    CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding | kCCOptionECBMode, keyPtr, kCCBlockSizeAES128, NULL, [decodeData bytes], dataLength, buffer, bufferSize, &numBytesDecrypted);
    if (cryptStatus == kCCSuccess) {
        NSData *data = [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted];
        NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
        
        return result;
    } else {
        free(buffer);
        return nil;
    }
}


AES加密的细节还要和和后台商量。

二、非对称算法

算法公开,可逆的加密数据。一般服务器存私钥,客户端存公钥,且公钥是公开的。用公钥加密,就用私钥解密。用私钥加密,就用公钥解密。
特性:
速度慢,适合对小数据加密。
非对称算法比对称算法安全。
最常用的是RSA。

1、什么是RSA?

三个人一起发明了非对称算法,三个人名字的首字母分别是R、S、A,所以非对称算法加密就叫RSA加密。

2、RSA加密原理

1、找出两个‘很大’的质数:P & Q,一般长度是上百位。然后通过下面计算得到N和 M;
N = P * Q
M = (P - 1) * (Q - 1)
2、找出整数E,E与M互质,即除了1之外,没有其他公约数
3、找出整数D,使用ED除以M余1,即(ED) % M = 1
4、经过上述准备工作之后,可以得到:
E是公钥,负责加密
D是私钥,,负责解密
N负责公钥和私钥之间的联系
5、加密算法,假定对X进行加密
(X^E)%N = Y
6、解密算法,根据‘费马小定理',可以使用以下公式完成解密
(Y^D)%N = X

画外音:看懂的就看,看不懂的略过,反正我是看不懂~~

3、应用场景

由于 对称算法和非对称算法的特性,一般

1、用RSA算法加密并传输对称算法所需的密钥
2、数据本身的加密和解密使用对称加密算法(AES)

4、在iOS中的应用

1、需求:

SDK开发,使用RSA加密和后台进行数据交互,后台是PHP,公钥、私钥是后台高度,把公钥发给了我。
要求:
1、post请求,客户端放公钥,私钥放后台
2、先将上传的参数进行排序,再进行MD5加盐加密。
3、再将数据进行RSA加密。
4、使用的密钥是1024位,要和后台统一,解密长度128,加密长度117
5、rsa_public_key.pem文件后台给的

至于没有用对称算法传输数据,这个是后台决定的,每个公司的加密方法和顺序都不一样,具体问题具体分析。

4、遇到的问题
1、'openssl/asn1.h' file not found‘

解决方法:
Header Search Paths 添加这种格式的路径
"$(SRCROOT)/XSFH_game/Lib"

image.png
2、base编码发给后台,后台接收少+的问题

我这边发给后台加密后的base64编码,后台接收后,base64编码中的+变成了空格,导致后台解码错误,这是后台的问题
解决方法:
PHP学习 base64_encode +号变空格

3、后台数据接收到问题

可能是php接收数据的问题,我放在HTTPBody里的传给它的是一字符串,后台说没法解析,要那种类似于json的格式,最后给它传了个如下格式的代码stringWithFormat:@"baseKey=%@",encryptedString]; ,baseKey可以随便写,就类似于json的key值

NSString *encryptedString = [[XSFHRSATool shareInstance] encryptStr:paramStr WithRSAKeyType:KeyTypePublic];
NSString *keyAndValue = [NSString  stringWithFormat:@"baseKey=%@",encryptedString];
request.HTTPBody = [keyAndValue  dataUsingEncoding:NSUTF8StringEncoding];

三、散列算法

1、什么是散列算法

散列算法是不可逆的,MD5是其代表,又称作指纹算法,摘要算法。

2、MD5在iOS的应用

#pragma mark - 3、散列加密
-(void)MD5Test{
    
    NSString *str = @"我是中国人";
    NSString *str1 = [self md5EncryptWithString:str];
    NSLog(@"MD5加密=%@",str1);

}
//秘钥
static NSString *encryptionKey = @"nha735n197nxn(N′568GGS%d~~9naei';45vhhafdjkv]32rpks;lg,];:vjo(&**&^)";

- (NSString *)md5EncryptWithString:(NSString *)string{
    return [self md5:[NSString stringWithFormat:@"%@%@", encryptionKey, string]];
}

- (NSString *)md5:(NSString *)string{
    
    const char *cStr = [string UTF8String];
    unsigned char digest[CC_MD5_DIGEST_LENGTH];
    CC_MD5(cStr, (CC_LONG)strlen(cStr), digest);
    NSMutableString *result = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
    for (int i = 0; i < CC_MD5_DIGEST_LENGTH; i++) {
        [result appendFormat:@"%02X", digest[i]];
    }
    
    return result;
}

3、MD5更加安全的加密方式

怎么说呢,上面2种方式都是重复利用MD5加密
还可以更复杂,不过要和后台商量好就行了。

四、钥匙串

通过系统提供的钥匙串功能,可以在本地对用户的信息进行保存。系统使用AES方式对密码加密。
相对于NSUserDefaults、plist文件保存等一般方式,keychain保存更为安全。所以我们会用keyChain保存一些私密信息,比如密码、证书、设备唯一码(把获取到用户设备的唯一ID 存到keychain 里面这样卸载或重装之后还可以获取到id,保证了一个设备一个ID)等等。

一般使用第三方框架SSKeychain

#pragma mark - 4、SSKeychain
-(void)SSKeychainTest{
    
   [SSKeychain setPassword:@"admin123" forService:[NSBundle mainBundle].bundleIdentifier account:@"张三"];
   
   NSString *mima = [SSKeychain passwordForService:[NSBundle mainBundle].bundleIdentifier account:@"张三"];
    
   NSLog(@"输出密码=%@",mima);
}

参考:
iOS AES加密
1、RSA加密、解密、签名、验签的原理及方法
2、一篇文章彻底弄懂Base64编码原理
3、iOS中使用基于RSA使用公钥加密和公钥解密
4、iOS RSA加签和验签(SHA1WithRSA)
5、iOS MD5加密

上一篇下一篇

猜你喜欢

热点阅读