网络安全传输(读书笔记)

服务器验证

    
    通过创建NSURLProtectionSpace,来确认用户访问的是安全的服务器。从一个需要验证的服务器请求资源,过程如下:
    当服务器收到请求,响应发出HTTP状态码401,报头:WWW-Authenticate,NSURLConnection接收到后,告知APP调用willSendRequestForAuthenticationChallenge:;验证服务器工作就在这个函数中完成。
实现委托:
[objc] view plain copy
  1. - (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge  
通过验证全部或部分属性,保证APP只连接指定服务器。
 
1.验证服务器全部属性
 
  创建信任的服务器的protection space:
[objc] view plain copy
  1. NSURLProtectionSpace *defaultSpace = [[NSURLProtectionSpace alloc] initWithHost:@"yourbankingdomain.com"  
  2.                                                                            port:443  
  3.                                                                        protocol:NSURLProtectionSpaceHTTPS  
  4.                                                                           realm:@"mobile"  
  5.                                                            authenticationMethod:NSURLAuthenticationMethodDefault];  
    然后验证challenge.protectionSpace是否是这个信任的服务器的protection space。
 
2.验证部分指定的服务器属性
 
  获取challenge.protectionSpace的各个属性,如:challenge.protectionSpace.host,challenge.protectionSpace.port,
challenge.protectionSpace.protocol等。依次检查各个属性是否是指定值,即可。
 
 
每一个网络连接操作都是NSOperation,在后台线程执行,所以,如果这些过程中需要更新UI,需要特别注意要在主线程中完成。服务器验证很重要,但其本身不足以防范所有攻击。例如,它不能防止网络通信被偷听。
 
 
HTTP认证
 
两种认证方式:标准和加速。
 
1.标准认证模式--用户名/密码
 
标准认证模式有:
  • HTTP Basic Authentication(基本认证)
  • HTTP Digest Authentication(摘要认证)
  • NTLM Authentication (NTLM认证)
[objc] view plain copy
  1. // <span style="font-family:Helvetica;">HTTPBasic</span>  
  2. if (challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodHTTPBasic) {  
  3.     // 验证  
  4.     if (challenge.previousFailureCount == 0) {  
  5.         NSURLCredential *creds = [[NSURLCredential alloc] initWithUser:username  
  6.                                                               password:password   
  7.                                                            persistence:NSURLCredentialPersistenceForSession];  
  8.         [challenge.sender useCredential:creds forAuthenticationChallenge:challenge];  
  9.     // 之前验证失败  
  10.     } else {  
  11.         [[challenge sender] cancelAuthenticationChallenge:challenge];  
  12.     }  
  13. }  

2.客户端证书认证
 
(这一章就是个坑啊……我这种没恒心的人先跳过好了)
 
 
哈希(HASH)和加密(ENCRYPTION)保证数据完整性
 
   APP必须保证数据在传输过程中是安全的、不会被修改,利用哈希和加密算法可以保护数据。
1.哈希
    iOS CommonCrypto中包括常用的MD5、SHA-1、SHA-256和一些不常用的哈希算法。以MD5为例:
[objc] view plain copy
  1. NSString *str = @"test string";//原字符串  
  2. const charchar *ptr = [str UTF8String];  
  3. unsigned char buffer[CC_MD5_DIGEST_LENGTH];  
  4. CC_MD5(ptr, strlen(ptr), buffer);  
  5. NSMutableString *hashString = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2];//经过哈希算法后的字符串  
  6. for(int i = 0; i < CC_MD5_DIGEST_LENGTH; i++) {  
  7.     [hashString appendFormat:@"%02x",buffer[i]];  
  8. }  
     哈希算法的结果长度一定,且不可逆,无法根据结果推断原文。
    哈希算法用于检测数据完整性时,将数据及数据经过哈希算法计算出的值一起明文发送给服务器,服务器接收到后对数据进行哈希计算,将得到的值与接收到的哈希值比较,如果不等则认为数据不完整。
    哈希算法可以应用于验证登录,用户注册时,将密码应用哈希算法计算出一个杂乱无章的值存储在数据库,每一次登录时,输入密码,然后将密码利用哈希算法计算出哈希值,与存储在数据库中的密码哈希值进行比较,相等,则登录成功。
2.加密
     加密算法的结果长度随原文长度变化,可以,可以根据结果推断出原文。
    加密发送的数据不是明文的,下图是数据传输过程中加密和解密的步骤示意图。可以看到,
加密过程中,
  1. 生成iv(初始向量)。
  2. 利用iv和加密key对数据进行加密。
  3. 根据HMAC key生成MAC,将加密后的数据、iv及MAC组成request body发送至服务器。
解密过程中,
  1. 根据共享的加密key、iv,解密数据。
  2. 利用共享的HMAC key和解密后的数据生成服务器端MAC。
  3. 比较两个MAC值是否相等,如果否,则认为数据不安全。
发送和接受方共有加密和解密过程中重要的值如MAC算法、E-KEY、HMAC-KEY等。
 
MAC(Message Authentication Codes)
 
    MAC用于检测数据是否被修改。计算MAC算法类似哈希算法,但是MAC是成对的,更安全。APP会计算一个MAC随请求一起发送,服务器也会计算一个MAC,两个MAC比较,如果不一致,则数据被修改了。iOS和大多数服务器支持HMAC(Hash-Based Message Authentication Code),它的强度取决于密钥和哈希算法强度。
[objc] view plain copy
  1. const charchar *ptr = [@"test string" UTF8String];  
  2. const charchar *keyPtr = [kMACKey UTF8String];  
  3. unsigned char buffer[CC_SHA256_DIGEST_LENGTH];  
  4.   
  5. // 计算哈希值  
  6. CCHmac(kCCHmacAlgSHA256,            // 算法  
  7.        keyPtr, kCCKeySizeAES256,    // key 和 key的长度  
  8.        ptr, strlen( ptr ),          // 原字符串 和 原字符串长度  
  9.        buffer);                     // 哈希值,哈希值长度等于所采用的哈希算法摘要长度  
  10. NSMutableString *output = [NSMutableString stringWithCapacity:CC_SHA256_DIGEST_LENGTH * 2];  
  11. for(int i = 0; i < CC_SHA256_DIGEST_LENGTH; i++) {  
  12.     [output appendFormat:@"%02x",buffer[i]];  
  13. }  
MAC和上面HASH算法的区别在于多了一个key,从图6-2可以看出E-key和M-key并没有随着请求一起发送,而是在APP和服务器端被共享的,它对于保护数据不被攻击至关重要。
 
加密与解密算法
 
      已经生成了MAC,就可以对数据进行加密,然后将其发送至服务器。这里主要讨论两种加密方式:高级加密标准(Advanced Encryption Standard,AES)和数据加密标准(Data Encryption Standard,DES)。DES占用资源较大,不适合手机设备,而AES从速度、强度和资源占用方面更适合手机设备。Objective-C中,CommonCryptor库中CCCrypt函数,可以实现加密和解密操作。
以AES为例,加密过程,首先需要生成iv,这里利用SecRandomCopyBytes函数,创建一组随机字节。加密代码如下:
[objc] view plain copy
  1. NSMutableData *iv = [NSMutableData dataWithLength:kCCBlockSizeAES128];  
  2. SecRandomCopyBytes(kSecRandomDefault,kCCBlockSizeAES128,iv.mutableBytes);  
  3. NSString *str = @"test string";  
  4. NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding];  
  5. NSData *keyData = [kAESEncryptionKey dataUsingEncoding:NSUTF8StringEncoding];  
  6. size_t dataMoved;  
  7. NSMutableData *encryptedData = [NSMutableData dataWithLength:data.length + kCCBlockSizeAES128];  
  8. CCCryptorStatus status = CCCrypt(kCCEncrypt,                    // 加密  
  9.                                  kCCAlgorithmAES128,            // 加密标准  
  10.                                  kCCOptionPKCS7Padding,  
  11.                                  keyData.bytes,  
  12.                                  keyData.length,  
  13.                                  iv.bytes,  
  14.                                  data.bytes,  
  15.                                  data.length,  
  16.                                  encryptedData.mutableBytes,  
  17.                                  encryptedData.length,  
  18.                                  &dataMoved);  
  19.   
  20. if (status == kCCSuccess) {  
  21.     encryptedData.length = dataMoved;  
  22. }  
  23. NSString *encryptedString = [encryptedData base64Encoding];  
解密算法与加密类似,唯一区别在于,CCCrypt函数第一个参数指定为解密操作。
[objc] view plain copy
  1. NSMutableData *decryptedData = [NSMutableData dataWithLength:encryptedData.length + kCCBlockSizeAES128];  
  2.     CCCryptorStatus result = CCCrypt(kCCDecrypt,                    // kCCEncrypt or kCCDecrypt  
  3.                                      kCCAlgorithmAES128,  
  4.                                      kCCOptionPKCS7Padding,         // Padding option for CBC Mode  
  5.                                      keyData.bytes,  
  6.                                      keyData.length,  
  7.                                      iv.bytes,  
  8.                                      encryptedData.bytes,  
  9.                                      encryptedData.length,  
  10.                                      decryptedData.mutableBytes,    // encrypted data out  
  11.                                      decryptedData.length,  
  12.                                      &dataMoved);                   // total data moved  
  13.     if (result == kCCSuccess) {  
  14.         decryptedData.length = dataMoved;  
  15.     }  
  16.     NSString *decryptedString = [[NSString alloc] initWithData:decryptedData encoding:NSUTF8StringEncoding];  
  17.     NSLog(@"%@",decryptedString);  
 
http://blog.csdn.net/pingshw/article/details/17845735
原文地址:https://www.cnblogs.com/feng9exe/p/8064508.html