美文网首页初见
iOS 开发之网络数据安全

iOS 开发之网络数据安全

作者: DB001 | 来源:发表于2020-06-08 17:42 被阅读0次

    网络安全原则
    • 安全的原则

    1)在网络不允许传输用户隐私数据的明文
    2)在本地不允许保存用户隐私数据的明文

    • 请求方法

    1.一定要使用POST请求提交用户的隐私数据
    2.GET请求的所有参数都直接暴露在URL中
    3.请求的URL一般会记录在服务器的访问日志中。
    4.服务器的访问日志黑客攻击重点对象之一

    • 用户的隐私数据

    登录密码
    银行账号
    … …

    数据安全
    • 数据拦截(抓包工具)

    1.仅仅用POST请求提交用户的隐私数据,还是不能完全解决安全问题。
    2.可以利用软件(比如Charles)设置代理服务器,拦截查看手机的请求数据。
    3.因此:提交用户的隐私数据时,一定不要明文提交,要加密处理后提交

    • 信息安全所面临的威胁

    1.机密性(被窃听,秘密泄露)。
    2.完整性(篡改,信息被修改)。
    3.认证(伪装,伪装成通信双方)。
    4.不可否认性(否认,事后不承认是自己发送的)。

    data.png
    • 常用的加密算法加密算法的选择

    1.MD5 \ SHA \ DES \ 3DES \ RC2和RC4 \ RSA \ IDEA \ DSA \ AES
    2.一般公司都会有一套自己的加密方案,按照公司接口文档的规定去加密

    Base64编码
    • 说明

    1.HTTP将Base64编码用于基本的认证和摘要认证。
    2.其可以方便的将用户的任何输入转换成只包含特定字符的安全格式,服务于网络通信过程。

    • 命令行进行Base64编码解码

    编码base64 123.png -o 123.txt
    解码base64 123.txt -o test.png -D

    base64.png
    • 特点

    1.可以将任意的二进制数据进行Base64编码
    2.所有的数据都能被编码为并只用65个字符就能表示的文本文件
    3.编码后的65个字符包括A~Z,a~z,0~9,+,/,=
    4.对文件字符串进行Base64编码后将比原始大小增加33%
    5.能够逆运算
    6.不够安全,但却被很多加密算法作为编码方式

    • Base64编码原理:

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

    处理过程说明:

    a、转换的时候,将`3个byte的数据`,先后放入`1个24bit的缓冲区中`,先来的`byte`占高位。
    b、数据不足`3byte`的话,于缓冲区中剩下的bit用`0`补足。然后,`每次`取出`6个bit`,按照其值选择查表选择对应的字符作为编码后的输出。
    c、不断进行,直到全部输入数据转换完成。
    d、如果最后剩下两个输入数据,在编码结果后加`1`个“=”;
    e、如果最后剩下一个输入数据,编码结果后加`2`个“=”;
    f、如果没有剩下任何数据,就什么都不要加,这样才可以保证资料还原的正确性。
    
    • 实现
    a.说明:
            1)从iOS7.0 开始,苹果就提供了base64的编码和解码支持
            2)如果是老项目,则还能看到base64编码和解码的第三方框架,如果当前不再支持iOS7.0以下版本,则建议替换。
    
     b.相关代码:
        //给定一个字符串,对该字符串进行Base64编码,然后返回编码后的结果
        -(NSString *)base64EncodeString:(NSString *)string
        {
            //1.先把字符串转换为二进制数据
            NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
    
            //2.对二进制数据进行base64编码,返回编码后的字符串
            return [data base64EncodedStringWithOptions:0];
        }
    
        //对base64编码后的字符串进行解码
        -(NSString *)base64DecodeString:(NSString *)string
        {
            //1.将base64编码后的字符串『解码』为二进制数据
            NSData *data = [[NSData alloc]initWithBase64EncodedString:string options:0];
    
            //2.把二进制数据转换为字符串返回
            return [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
        }
    
      c.终端测试命令
            $ echo -n A | base64
            $ echo -n QQ== |base64 -D
    
    • 常见的安全处理机制

    单向散列函数:MD5 | SHA1 | SHA256 | SHA512等。
    消息认证码:HMAC-MD5 | HMAC-SHA1
    对称加密: DES | 3DES | AES(高级加密标准)
    非对称加密:RSA
    数字签名
    证书

    • 对消息加密解密的两种处理方式:

    1)只需要保存一个值,保证该值的机密性,而不需要知道原文。
    2)除了保证机密性外还需要对该值进行解密得到消息原文。

    • 单向散列函数
    • 性质
      1)对任意长度的消息散列得到散列值是定长的。
      2)散列计算速度快,非常高效。
      3)消息不同,则散列值一定不同。
      4)消息相同,则散列值一定相同。
      5)具备单向性,无法逆推计算。
    • 说明
      1.单向散列函数也称为消息摘要函数哈希函数者函数
      2.单向散列函数输出的散列值又称为消息摘要或者指纹
    • 经典算法
      MD4MD5SHA1SHA256SHA512等。
    singe.png
    • MD5
    • MD5简单说明:
      1.MD5是由Rivest于1991年设计的单向散列函数
      2.全称是Message Digest Algorithm 5,译为“消息摘要算法第5版”
    • MD5的特点:
      1.对输入信息生成唯一128位散列值(32个字符)
      2.明文不同,则散列值一定不同
      3.明文相同,则散列值一定相同
      4.根据输出值不能得到原始的明文,即其过程不可逆
    • MD5的应用
      1.加密
      2.搜索
      3.文件完整性验证
    • 安全性
      1)MD5解密网站:http://www.cmd5.com
      2)MD5的强抗碰撞性已经被证实攻破,即对于重要数据不应该再继续使用MD5加密
    • 提交隐私数据的安全过程注册

      register.png
    • 提交隐私数据的安全过程登录

      login.png
    • 结论:
      1.用户的隐私数据,只有在用户输入那一刻是明文,其他情况都是密文处理
      2.注册只需要将密码明文加密过后,保存到数据库中,在登录时,将加密之后的密文和数据库中的密文进行比较(不需要对密文解密),相同则返回登录成功

    • MD5改进

    • 现在的MD5已不再是绝对安全,对此,可以对MD5稍作改进,以增加解密的难度:
      1、加盐(Salt):在明文的固定位置插入随机串,然后再进行MD5。
      2、先加密,后乱序:先对明文进行MD5,然后对加密得到的MD5串的字符进行乱序。
      3、先乱序,后加密:先对明文字符串进行乱序处理,然后对得到的串进行加密。
      4、先乱序,再加盐,再MD5等。
      5、总之宗旨就是:黑客就算攻破了数据库,也无法解密出正确的明文。
    • 加密命令行
            MD5加密-字符串    $ echo -n "520it" |md5
            MD5加密-文件1     $ md5 abc.png
            SHA1加密:        $ echo -n "520it" |openssl sha -sha1
            SHA256            $ echo -n "520it" |openssl sha -sha256
            SHA512            $ echo -n "520it" |openssl sha -sha512
            hmacMD5加密       $ echo -n "520it" |openssl dgst -md5 -hmac "123"
    
    • 散列函数应用领域

      1)搜索 多个关键字,先对每个关键字进行散列,然后多个关键字进行或运算,如果值一致则搜索结果一致
      2)版权 对文件进行散列判断该文件是否是正版或原版的
      3)文件完整性验证 对整个文件进行散列,比较散列值判断文件是否完整或被篡改

    • 消息认证机制(HMAC)简单说明

      • 1、原理
        ①消息的发送者接收者有一个共享密钥
        ②发送者使用共享密钥对消息加密计算得到MAC值(消息认证码)
        消息接收者使用共享密钥对消息加密计算得到MAC值
        ④比较两个MAC值是否一致
      • 2、使用
        客户端需要在发送的时候把(消息)+(消息·HMAC)一起发送给服务器
        服务器接收到数据后,对拿到的消息用共享的KEY进行HMAC,比较是否一致,如果一致则信任
    hmac.png
    #import "ViewController.h"
    #import "NSString+Hash.h"
    @interface ViewController ()
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
    //    [self md5];
        
        [self hMac];
    }
    
    /**
    * 方法说明:消息认证码
    */
    - (void)hMac{
        
        NSString *string0 = @"520it";
        
        //认证码:先发送网络请求获取认证码
        NSString *renzhengCode = @"RENZHENGMA";
        
        //网络请求获取认证码 两次加密处理:先使用认证码来进行加密处理,接着对加密之后的密文进行一次散列计算
        NSString *hMacString0 = [string0 hmacMD5StringWithKey:renzhengCode];
        //b42299f23989da507afad6fb7ff1e96d
        NSLog(@"hMacString0:%@ - %ld",hMacString0,hMacString0.length);
        
    }
    
    /**
     * 方法说明:MD5系列加密
     */
    - (void)md5{
        
        /**
         MD5
         
         用户的输入:520it
         加密的原文:520it
         发送给服务器的数据:21bfcc4c2625469d8ec6f3d710dcb0fe
         可能被拦截的数据:21bfcc4c2625469d8ec6f3d710dcb0fe
         可能存在的破解:21bfcc4c2625469d8ec6f3d710dcb0fe -> 520it
         */
        
        NSString *string = @"520it";
        NSLog(@"MD5|string:%@",[string md5String]);
        
        /**
         MD5 * N
         
         用户的输入:520it
         加密的原文:520it
         发送给服务器的数据:3e1bc183ec3c95afe85d45483f2d107c
         可能被拦截的数据:3e1bc183ec3c95afe85d45483f2d107c
         可能存在的破解:3e1bc183ec3c95afe85d45483f2d107c  ->21bfcc4c2625469d8ec6f3d710dcb0fe -> 520it
         */
        
        NSString *string1 = @"520it";
        NSLog(@"MD5 * N|string1:%@",[[string1 md5String] md5String]);
        
        /**
         MD5 + Salt
         Salt:要足够的长,足够的复杂
         
         用户的输入:520it
         加密的原文:520it
         发送给服务器的数据:549345ff7a43d6bcb199832e8013b6df
         可能被拦截的数据:549345ff7a43d6bcb199832e8013b6df
         可能存在的破解:549345ff7a43d6bcb199832e8013b6df -> 520it123456
         
         用户的输入:kxt
         加密的原文:kxt
         发送给服务器的数据:510f38957bc2982fafc35d8bf5f712b5
         可能被拦截的数据:510f38957bc2982fafc35d8bf5f712b5
         可能存在的破解:510f38957bc2982fafc35d8bf5f712b5 -> kxt123456
         
         总结:输入不同的原文解密之后有:520it123456 | kxt123456 通过两次解密结果对比123456为加盐部分去掉:520it | kxt
         
         */
        NSString *salt = @"123456";
        NSString *string2 = @"520it";
       
        string2 = [string2 stringByAppendingString:salt];
        NSLog(@"MD5 + Salt|string2:%@",[string2 md5String]);
        
        NSString *string3 = @"kxt";
        string3 = [string3 stringByAppendingString:salt];
        NSLog(@"MD5 + Salt|string3:%@",[string3 md5String]);
           
        /**
           先乱序,在加密(安全性很高)
           
           用户的输入:520it 乱序之后得到加密原文 it520
           加密的原文:it520
           发送给服务器的数据:c1e8a4de626d2dd197cbfea2a3171250
           可能被拦截的数据:c1e8a4de626d2dd197cbfea2a3171250
           可能存在的破解:c1e8a4de626d2dd197cbfea2a3171250 -> it520
         */
        
        NSString *string4 = @"520it";
        NSString *str1 = [string4 substringFromIndex:3];
        NSString *str2 = [string4 substringToIndex:3];
        string4 = [str1 stringByAppendingString:str2];
        
        NSLog(@"%@-%@-%@",str1,str2,string4);
        NSLog(@"先乱序,在加密:%@",[string4 md5String]);
        
        /**
         直接对字符串加密,得到32位的字符串,只截取该字符的串的固定长度(一部分)作为密文
    
         用户的输入:520it
         加密的原文:520it
         加密的密文:21bfcc4c2625469d8ec6f3d710dcb0fe
         将加密之后的密文截取固定的长度,发送给服务器如:截取0~13
         发送给服务器的数据:21bfcc4c26254
         可能被拦截的数据:21bfcc4c26254
         可能存在的破解:21bfcc4c26254 -> 21bfcc4c26254(不能使用MD5的方式破解因为MD5是32位的)
         */
        
        //加密的原文
        NSString *string5 = @"520it";
        //加密之后的密文
        NSString *strMD5 = [string5 md5String];
        NSLog(@"strMD5:%@",strMD5);
        //要发送给服务器的数据:(strMD5:截取0~13)
        NSString *sendStr = [strMD5 substringToIndex:13];
        NSLog(@"要发送给服务器的数据:%@",sendStr);  
    }
    @end
    
    对称加密
      1. 对称加密的特点

      1)加密/解密使用相同的密钥
      2)加密解密的过程是可逆的(明文-》密文-》明文)

    对称加密.png
    • 2.经典算法

      1)DES 数据加密标准
      2)3DES 使用3个密钥,对消息进行(密钥1·加密)+(密钥2·解密)+(密钥3·加密)
      3)AES 高级加密标准

    • 3.分组密码简单说明

      密码算法可以分为分组密码流密码两种:
      1)分组密码:每次只能处理特定长度的一组数据的一类密码算法。一个分组的比特数量就称之为分组长度。
      ex:DES和3DES的分组长度都是64比特。即每次只能加密64比特的明文,并生成64比特的密文。AES的分组长度有128比特、192比特和256比特可以选择。
      2)流密码:对数据流进行连续处理的一类算法。流密码中一般以1比特、8比特或者是32比特等作为单位俩进行加密和解密。

    • 4.ECB分组模式

      ECB模式的全称为Electronic CodeBook模式。又成为电子密码本模式
      特点:
      1)使用ECB模式加密的时候,相同的明文分组会被转换为相同的密文分组。
      2)类似于一个巨大的明文分组-》密文分组的对照表。

    ecb.png DES-ECB.png
     终端测试命令:
       加密 $ openssl enc -des-ecb -K 616263 -nosalt -in 123.txt -out 123.bin 
       解密 $ openssl enc -des-ecb -K 616263 -nosalt -in 123.bin -out 1231.txt -d
    
    • 5.CBC分组模式

    1.CBC模式全称为Cipher Block Chainning模式(密文分组链接模式|电子密码链条)。

    1. 特点:在CBC模式中,首先将明文分组前一个密文分组进行异或(XOR)运算,然后再进行加密
    CBC.png
    c-b-c.png
    终端命令:
       加密 $ openssl enc -des-cbc -K 616263 -iv 0102030405060708 -nosalt -in a.txt -out a.bin
       解密 $ openssl enc -des-cbc -K 616263 -iv 0102030405060708 -nosalt -in a.bin -out a1.txt -d
    
    #import "ViewController.h"
    #import "EncryptionTools.h"
    
    @interface ViewController ()
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        
        [super viewDidLoad];
        
    //    [self AES_ECB];
        
    //    [self AES_CBC];
        
        [self DES_CBC];
        
    //    [self DES_ECB];
        
    }
    
    - (void)DES_CBC{
        
        NSString *string = @"haha";
        NSString *keyString = @"abc";
        
        uint8_t iv[8] = {1,2,3,4,5,6,7,8};
        NSData *data = [[NSData alloc]initWithBytes:iv length:sizeof(iv)];
        [EncryptionTools sharedEncryptionTools].algorithm = kCCAlgorithmDES;
        
        NSLog(@"DES-CBC 加密:%@",[[EncryptionTools sharedEncryptionTools] encryptString:string keyString:keyString iv:data]);
       
        NSLog(@"DES-CBC 解密:%@",[[EncryptionTools sharedEncryptionTools] decryptString:@"gmVDD4Bj4ZE=" keyString:keyString iv:data]);
        
    }
    
    - (void)DES_ECB{
        
        NSString *string = @"haha";
        NSString *keyString = @"abc";
        //DES -ECB
        [EncryptionTools sharedEncryptionTools].algorithm = kCCAlgorithmDES; //设置加密方式为DES
        //echo -n "haha" |openssl enc -des-ecb -K 616263 -nosalt |base64
        NSLog(@"DES-ECB 加密:%@",[[EncryptionTools sharedEncryptionTools] encryptString:string keyString:keyString iv:nil]);
        //echo -n "b2Z9CtPer5Y=" |base64 -D |openssl enc -des-ecb -K 616263 -nosalt -d
        NSLog(@"DES-ECB 解密:%@",[[EncryptionTools sharedEncryptionTools] decryptString:@"b2Z9CtPer5Y=" keyString:keyString iv:nil]);
        
    }
    
    
    //AES - CBC
    - (void)AES_CBC{
        
        NSString *string = @"haha";
        NSString *keyString = @"abc";
        
        //AES -CBC
        uint8_t iv[8] = {1,2,3,4,5,6,7,8};
        NSData *data = [[NSData alloc]initWithBytes:iv length:sizeof(iv)];
        // echo -n "haha" |openssl enc -aes-128-cbc -K 616263 -nosalt -iv 0102030405060708 |base64
        NSLog(@"AES-CBC 加密:%@",[[EncryptionTools sharedEncryptionTools] encryptString:string keyString:keyString iv:data]);
        // echo -n "E/wWqUTiw/E+1DThAzV39A==" |base64 -D |openssl enc -aes-128-cbc -K 616263 -nosalt -iv 0102030405060708 -d
        NSLog(@"AES-CBC 解密:%@",[[EncryptionTools sharedEncryptionTools] decryptString:@"E/wWqUTiw/E+1DThAzV39A==" keyString:keyString iv:data]);
        
        
    }
    //AES - ECB
    - (void)AES_ECB{
        
        /**
         * 参数说明
         * 该方法内部会对加密之后的密文进行base64编码
         * 第一个参数:要加密的字符串
         * 第二个参数:密钥
         * 第三个参数:初始向量(只有CBC的时候才用到)
         */
        
        NSString *encryptString = @"haha";
        NSString *keyString = @"abc";
        NSString *enString = [[EncryptionTools sharedEncryptionTools] encryptString:encryptString keyString:keyString iv:nil];
        //AES_ECB:MIoAu+xUEpQZSUmkZUW6JQ==
        /**
        终端验证:
        nanadeMacBook-Pro:~ mac2016$ echo -n "haha" | openssl enc -aes-128-ecb -K 616263 -nosalt |base64
        MIoAu+xUEpQZSUmkZUW6JQ==
        */
        NSLog(@"AES_ECB加密:%@",enString);
       
        NSString *decryptString=@"MIoAu+xUEpQZSUmkZUW6JQ==";
        NSString *deString = [[EncryptionTools sharedEncryptionTools] decryptString:decryptString keyString:keyString iv:nil];
    //  终端验证:
    //  echo -n "MIoAu+xUEpQZSUmkZUW6JQ==" |base64 -D |openssl enc -aes-128-ecb -K 616263 -nosalt -d
        
         NSLog(@"AES_ECB解密:%@",deString);
        
    }
    
    //16进制
    abc = 616263
    @end
    
    非对称加密

    (1)非对称加密算法需要两个密钥公开密钥(publickey)和私有密钥(privatekey)。
    (2)公开密钥私有密钥是一对,如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密;如果用私有密钥对数据进行加密,那么只有用对应的公开密钥才能解密
    (3)特点:
    a、非对称密码体制的特点:算法强度复杂、安全性依赖于算法与密钥但是由于其算法复杂,而使得加密解密速度没有对称加密解密的速度快
    b、对称密码体制中只有一种密钥,并且是非公开的,如果要解密就得让对方知道密钥。所以保证其安全性就是保证密钥的安全,而非对称密钥体制有两种密钥,其中一个是公开的,这样就可以不需要像对称密码那样传输对方的密钥了。

    • 1.非对称加密的特点:

      1)使用公钥加密使用私钥解密;
      2)公钥公开的,私钥保密;
      3)加密处理安全,但是性能极差

    RSA.png
    • 2.经典算法---RSA

    1)RSA 原理:
    (1)求N,准备两个质数p和q,N = p x q;
    (2)求L,Lp-1q-1最小公倍数L = lcm(p-1,q-1);
    (3)求EEL最大公约数为1E和L互质);
    (4)求DE x D mode L = 1

    2)RSA加密小实践
    (1)p = 17,q = 19 =>N = 323;
    (2)lcm(p-1,q-1)=>lcm(16,18)=>L= 144;
    (3)gcd(E,L)=1 =>E=5;
    (4)E乘以可以mode L =1? D=29可以满足;
    (5)得到公钥为E=5,N=323;
    (6)得到私钥为D=29,N=323;
    (7)加密 明文E次方 mod N = 123的5次方 mod 323 = 225(密文);
    (8)解密 密文D次方mod N = 225的29次方 mod 323 = 123(明文)

    3)openssl生成密钥命令
    (1) 生成强度是 512 的 RSA 私钥:
    $ openssl genrsa -out private.pem 512
    (2) 以明文输出私钥内容:
    $ openssl rsa -in private.pem -text -out private.txt
    (3) 校验私钥文件:
    $ openssl rsa -in private.pem -check
    (4) 从私钥中提取公钥:
    $ openssl rsa -in private.pem -out public.pem -outform PEM -pubout
    (5) 以明文输出公钥内容:
    $ openssl rsa -in public.pem -out public.txt -pubin -pubout -text
    (6) 使用公钥加密小文件:
    $ openssl rsautl -encrypt -pubin -inkey public.pem -in msg.txt -out msg.bin
    (7) 使用私钥解密小文件:
    $ openssl rsautl -decrypt -inkey private.pem -in msg.bin -out a.txt
    (8) 将私钥转换成 DER 格式:
    $ openssl rsa -in private.pem -out private.der -outform der
    (9) 将公钥转换成 DER 格式:
    $ openssl rsa -in public.pem -out public.der -pubin -outform der

    数字签名

    1.数字签名的应用场景
    答:需要严格验证发送方身份信息情况

    2.数字签名原理:
    1)客户端处理:
    ①对"消息"进行 HASH 得到"消息摘要"
    ②发送方使用自己的私钥对"消息摘要"加密(数字签名);
    ③把数字签名附着在"报文"的末尾一起发送给接收方。
    2)服务端处理
    ①对"消息"HASH 得到"报文摘要"
    ②使用公钥对"数字签名"解密;
    ③对结果进行匹配

    数字签名.png
    数字证书

    1.简单说明
    证书和驾照很相似,里面记有姓名、组织、地址等个人信息,以及属于此人的公钥,并有认证机构施加数字签名,只要看到公钥证书,我们就可以知道认证机构认证该公钥的确属于此人。

    2.数字证书的内容
    1)公钥
    2)认证机构的数字签名

    3.证书的生成步骤:
    1)生成私钥 :
    openssl genrsa -out private.pem 1024
    2)创建证书请求:
    openssl req -new -key private.pem -out rsacert.csr
    3)生成证书并签名,有效期10年 :
    openssl x509 -req -days 3650 -in rsacert.csr -signkey private.pem -out rsacert.crt
    4)将 PEM 格式文件转换成 DER 格式 :
    openssl x509 -outform der -in rsacert.crt -out rsacert.der
    5)导出P12文件 :
    openssl pkcs12 -export -out p.p12 -inkey private.pem -in rsacert.crt

    4.iOS开发中的注意点:
    1)在iOS开发中,不能直接使用 PEM 格式的证书,因为其内部进行了Base64编码,应该使用的是DER的证书,是二进制格式的
    2)OpenSSL默认生成的都是PEM格式的证书

    
    #import "ViewController.h"
    
    #import "RSACryptor.h"
    
    @interface ViewController ()
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        
        [super viewDidLoad];
    
        //使用公钥来进行加密,使用私钥来进行解密
        
        //01 加载公钥
        NSString *path = [[NSBundle mainBundle] pathForResource:@"rsacert.der" ofType:nil];
        [[RSACryptor sharedRSACryptor] loadPublicKey:path];
        
        //02 对数据加密
        NSData *data = [[RSACryptor sharedRSACryptor] encryptData:[@"520it" dataUsingEncoding:NSUTF8StringEncoding]];
        //对加密得到的密文进行base64编码
        NSString *oo = [data base64EncodedStringWithOptions:kNilOptions];
    //Q1RapLxau+1YQmGCo6/QVrTXdfQo+ky7orApyvBi+BlfPOyYylCeVYDIHtXqXPn99caNscU4v1drGDvyoyqQSxEcHi7/F59WerrQ6MgJZF+31VsbDylkew+Cl2cAB4d9I0h+Gp0f2tJEL7oTb7w2bQ/bpo7HrqOeua8hybQgJLI=
        NSLog(@"加密:%@",oo);
        
        //03 加载私钥
        NSString *path1 = [[NSBundle mainBundle] pathForResource:@"p.p12" ofType:nil];
        [[RSACryptor sharedRSACryptor] loadPrivateKey:path1 password:@"123456"];
        
        //04 对数据解密
        NSData *data1 = [[RSACryptor sharedRSACryptor] decryptData:data];
        
        NSString *oo1 = [[NSString alloc] initWithData:data1 encoding:NSUTF8StringEncoding];
        
    //    520it
        NSLog(@"解密%@",oo1);
         
    }
    
    @end
    
     混合密码系统:对称加密 + 非对称加密
     先使用非对称加密来完成密钥的交换(后面对称加密需要使用的密钥),后面所有的通信都使用对称加密来完成后面的通信
    
    HTTPS的基本使用

    1.https简单说明
    HTTPS(全称:Hyper Text Transfer Protocol over Secure Socket Layer),是以安全为目标的HTTP通道,简单讲是HTTP的安全版。
    即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL。 它是一个URI scheme(抽象标识符体系),句法类同http:体系。用于安全的HTTP数据传输。
    https:URL表明它使用了HTTP,但HTTPS存在不同于HTTP的默认端口及一个加密/身份验证层(在HTTP与TCP之间)。

    2.HTTPSHTTP的区别主要为以下四点
    一、https协议需要到ca申请证书,一般免费证书很少,需要交费。
    二、http是超文本传输协议,信息是明文传输,https 则是具有安全性的ssl加密传输协议。
    三、http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443`。
    四、http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。

    3.简单说明
    1)HTTPS的主要思想是在不安全的网络上创建一安全信道,并可在使用适当的加密包和服务器证书可被验证且可被信任时,对窃听和中间人攻击提供合理的保护。
    2)HTTPS的信任继承基于预先安装在浏览器中的证书颁发机构(如VeriSign、Microsoft等)(意即“我信任证书颁发机构告诉我应该信任的”)。
    3)因此,一个到某网站的HTTPS连接可被信任,如果服务器搭建自己的https 也就是说采用自认证的方式来建立https信道,这样一般在客户端是不被信任的。
    4)所以我们一般在浏览器访问一些https站点的时候会有一个提示,问你是否继续。

    4.对开发的影响。

    • 4.1 如果是自己使用NSURLSession来封装网络请求,涉及代码如下。
    
    #import "ViewController.h"
    
    @interface ViewController ()<NSURLSessionDataDelegate>
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        /*
        HTTPS请求的时候:
        [1] 证书是受信任的,什么都不用做
        [2] 证书是不受信任的,是自签名的
            (1) 修改配置文件,禁用ATS特性
            (2) 信任并安装(数字证书)
        */
    //
        
    //    支付宝
        /**
    
         NSURL *url = [NSURL URLWithString:@"https://www.alipay.com/"];
    
         NSURLSession *session = [NSURLSession sharedSession];
         
         NSURLSessionDataTask *dataTask = [session dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
             
             NSLog(@"%@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
             
         }];
         
         [dataTask resume];
              
         */
    
        //    12306(之前不是ca认证这里仍然使用该网站举例)
            NSURL *url = [NSURL URLWithString:@"https://kyfw.12306.cn/otn/"];
    
            NSURLSession *session = [NSURLSession sessionWithConfiguration: [NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:nil];
            
            NSURLSessionDataTask *dataTask = [session dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
                   
                   NSLog(@"%@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
                   
            }];
               
            [dataTask resume];
        
        
    }
    #pragma---------------------------------------
    #pragma MARK - NSURLSessionDataDelegate
    /*
    challenge:挑战,质询
    当我们发送的是一个HTTPS请求的时候就会调用该方法,需要在该方法中处理证书
    NSURLAuthenticationMethodServerTrust:服务器信任
    HTTP:80
    HTTPS:443
    */
    - (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler{
        
        
        NSLog(@"%@",challenge.protectionSpace);
         /*
           NSURLSessionAuthChallengeUseCredential = 0, 使用证书
           NSURLSessionAuthChallengePerformDefaultHandling = 1,  忽略证书
           NSURLSessionAuthChallengeCancelAuthenticationChallenge = 2, 请求被取消,证书被忽略
           NSURLSessionAuthChallengeRejectProtectionSpace = 3, 拒绝
            */
        
        //判断只有当时NSURLAuthenticationMethodServerTrust的时候才安装这个证书
           if (![challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
               return;
           }
        
        //根据服务器中的保护控件的服务器信任,来创建一个认证信息
        NSURLCredential *credential = [[NSURLCredential alloc]initWithTrust:challenge.protectionSpace.serverTrust];
        completionHandler(NSURLSessionAuthChallengeUseCredential,credential);
        
    }
    
    @end
    
    • 4.2 如果是自己使用AFN来网络请求,涉及代码如下。
    #import "ViewController.h"
    #import "AFNetworking.h"
    
    @interface ViewController ()
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        /**
         //证书受信任
         
        //01 创建会话管理者对象
         AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
         //修改对响应的序列化方式
         manager.responseSerializer = [AFHTTPResponseSerializer serializer];
         
         //02 发送请求
         [manager GET:@"https://www.alipay.com/" parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
             
             NSLog(@"%@",[[NSString alloc]initWithData:responseObject encoding:NSUTF8StringEncoding]);
         } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
             NSLog(@"error---%@",error);
         }];
        */
        
        
        //01 创建会话管理者对象
         AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
         //修改对响应的序列化方式
         manager.responseSerializer = [AFHTTPResponseSerializer serializer];
         
         //设置AFN中的安全配置
        //01 允许接收无效的证书
         manager.securityPolicy.allowInvalidCertificates = YES;
        //02 不做域名验证
         manager.securityPolicy.validatesDomainName = NO;
         //03 修改info.plist文件ATS
         
         //02 发送请求
         [manager GET:@"https://kyfw.12306.cn/otn/" parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
             
             NSLog(@"%@",[[NSString alloc]initWithData:responseObject encoding:NSUTF8StringEncoding]);
         } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
             NSLog(@"error---%@",error);
         }];
         
    }
    
    /**
     AFNetworking:中的类AFSecurityPolicy说明:
     
     AFSecurityPolicy,内部有三个重要的属性,如下:
    
     AFSSLPinningMode SSLPinningMode;    //该属性标明了AFSecurityPolicy是以何种方式来验证
     BOOL allowInvalidCertificates;      //是否允许不信任的证书通过验证,默认为NO
     BOOL validatesDomainName;           //是否验证主机名,默认为YES
    
     "AFSSLPinningMode"枚举类型有三个值,分别是AFSSLPinningModeNone、AFSSLPinningModePublicKey、AFSSLPinningModeCertificate。
    
     "AFSSLPinningModeNone"代表了AFSecurityPolicy不做更严格的验证,"只要是系统信任的证书"就可以通过验证,不过,它受到allowInvalidCertificates和validatesDomainName的影响;
    
     "AFSSLPinningModePublicKey"是通过"比较证书当中公钥(PublicKey)部分"来进行验证,通过SecTrustCopyPublicKey方法获取本地证书和服务器证书,然后进行比较,如果有一个相同,则通过验证,此方式主要适用于自建证书搭建的HTTPS服务器和需要较高安全要求的验证;
    
     "AFSSLPinningModeCertificate"则是直接将本地的证书设置为信任的根证书,然后来进行判断,并且比较本地证书的内容和服务器证书内容是否相同,来进行二次判断,此方式适用于较高安全要求的验证。
    
     如果HTTPS服务器满足ATS默认的条件,而且SSL证书是通过权威的CA机构认证过的,那么什么都不用做。如果上面的条件中有任何一个不成立,那么都只能修改ATS配置。
    
     
     */
    
    @end
    

    相关文章

      网友评论

        本文标题:iOS 开发之网络数据安全

        本文链接:https://www.haomeiwen.com/subject/zcqrtktx.html