当前位置:   article > 正文

iOS之http和https解释/加密的方式RAS/AES/has散列算法/ssh加密/MD5、数字证书_app首先生成了一个随机数作为对称密钥

app首先生成了一个随机数作为对称密钥

 

HTTP协议的工作原理(http是在tcp的基础上的)

通常情况下,HTTP协议的工作原理很好理解,用户通过客户端向服务端发起一个请求,创建一个TCP连接,指定端口号,默认是80,然后连接到服务器工作。在那个端口监听浏览器请求。一旦监听到客户端请求,分析请求类型后,服务器会向客户端返回一个响应状态,比如"HTTP/1.0 404 OK",同时会返回特定的数据内容,如请求的资源,错误代码,其它状态信息等等。

http工作流程:

 

域名解析 --> 发起TCP的3次握手 --> 建立TCP连接后发起http请求 --> 服务器响应http请求,浏览器得到html代码 --> 浏览器解析html代码,并请求html代码中的资源(如js、css、图片等) --> 浏览器对页面进行渲染呈现给用户

 

 

 

 

 

HTTPS协议的工作原理

 

Https是一种基于SSL/TLS的Http协议,所有的http数据都是在SSL/TLS协议封装之上传输的。

Https协议在Http协议的基础上,添加了SSL/TLS握手以及数据加密传输,也属于应用层协议。

——>HTTP协议运行在TCP之上,所有传输的内容都是明文,客户端和服务器端都无法验证对方的身份。

——>HTTPS是运行在SSL/TLS之上的HTTP协议,SSL/TLS运行在TCP之上。所有传输的内容都经过加密,加密采用对称加密,但对称加密的密钥用服务器方的证书进行了非对称加密。

TLS/SSL中使用了非对称加密,对称加密以及HASH算法

(1)对称加密和非对称加密

对称加密是指加密和解密使用的密钥是同一个密钥,或者可以相互推算。
对称加密的优点是算法简单,加解密效率高,系统开销小,适合对大数据量加密。
缺点是解密加密使用同一个密钥,需要考虑远程通信的情况下如何安全的交换密钥,如果密钥丢失,
所谓的加密解密就失效了。

非对称加密和解密使用的密钥不是同一密钥,其中一个对外界公开,被称为公钥,另一个只有所有者知道,
称作私钥。
用公钥加密的信息必须用私钥才能解开,反之,用私钥加密的信息只有用公钥才能解开。

(2)握手过程的简单描述

1.浏览器将自己支持的一套加密规则(是对称加密或者非对称加密)发送给网站。

2.网站从中选出一组加密算法(非对称加密)与HASH算法(散列算法,不可逆算法,只有加密过程,没有解秘过程),并将自己的身份信息以证书的形式发回给浏览器。证书里面包含了网站地址,加密公钥,以及证书的颁发机构等信息。

3.获得网站证书之后浏览器要做以下工作:

a) 验证证书的合法性(颁发证书的机构是否合法,证书中包含的网站地址是否与正在访问的地址一致等),如果证书受信任,则浏览器栏里面会显示一个小锁头,否则会给出证书不受信的提示。

b) 如果证书受信任,或者是用户接受了不受信的证书,浏览器会生成一串随机数密码,并用证书中提供的公钥加密。(这里是非对称加密)

c) 使用约定好的HASH算法计算握手消息,并使用生成的随机数对消息进行加密(这里是对称加密),最后将之前生成的所有信息发送给网站。

4.网站接收浏览器发来的数据之后要做以下的操作:

a) 网站使用自己的私钥将信息解密取出密码(秘密就是浏览器会生成一串随机数密码),使用密码解密浏览器发来的握手消息,并验证HASH(网站用约定好的hash算法计算握手的消息)是否与浏览器发来的一致。

b) 网站使用密码(私钥加密)加密一段握手消息,发送给浏览器。

5.浏览器解密(公钥解秘)并计算握手消息的HASH,如果与服务端发来的HASH一致,

此时握手过程结束,之后所有的通信数据将由之前浏览器生成的随机密码并利用对称加密算法进行加密。

这里浏览器与网站互相发送加密的握手消息并验证,目的是为了保证双方都获得了一致的密码,并且可以正常的加密解密数据,为后续真正数据的传输做一次测试。

 

HTTPS一般使用的加密与HASH算法如下:

非对称加密算法:RSA,DSA/DSS-----非对称密钥也叫公开密钥加密,它是用两个数学相关的密钥对信息进行编码。

 

asymmetric encoding algorithm对称加密算法需要两个密钥:公开密钥(publickey)和私有密钥(privatekey)。公开密钥与私有密钥是一对,如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密;如果用私有密钥对数据进行加密,那么只有用对应的公开密钥才能解密。因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法

对称加密算法实现机密信息交换的基本过程是:甲方生成一对密钥并将其中的一把作为公用密钥向其它方公开;得到该公用密钥的乙方使用该密钥对机密信息进行加密后再发送给甲方;甲方再用自己保存的另一把专用密钥对加密后的信息进行解密。

 

 

 

对称加密算法:AES,RC4,3DES

HASH算法:MD5,SHA1,SHA256--------散列算法,不可逆算法,只有加密过程,没有解秘过程

 

Md5加密原理:

MD5以512位分组来处理输入的信息,且每一分组又被划分为16个32位子分组,经过了一系列的处理后,算法的输出由四个32位分组组成,将这四个32位分组级联后将生成一个128位散列值。

在MD5算法中,首先需要对信息进行填充,使其字节长度对512求余数的结果等于448。因此,信息的字节长度(Bits Length)将被扩展至N*512+448,即N*64+56个字节(Bytes),N为一个正整数。填充的方法如下,在信息的后面填充一个1和无数个0,直到满足上面的条件时才停止用0对信息的填充。然后再在这个结果后面附加一个以64位二进制表示的填充前的信息长度。经过这两步的处理,现在的信息字节长度=N*512+448+64=(N+1)*512,即长度恰好是512的整数倍数。这样做的原因是为满足后面处理中对信息长度的要求。MD5中有四个32位被称作链接变量(Chaining Variable)的整数参数,他们分别为:A=0x01234567,B=0x89abcdef,C=0xfedcba98,D=0x76543210。 当设置好这四个链接变量后,就开始进入算法的四轮循环运算,循环的次数是信息中512位信息分组的数目。

将上面四个链接变量复制到另外四个变量中:A到a,B到b,C到c,D到d。 主循环有四轮(MD4只有三轮),每轮循环都很相似。第一轮进行16次操作。每次操作对a、b、c和d中的其中三个作一次非线性函数运算,然后将所得结果加上第四个变量(文本中的一个子分组和一个常数)。

再将所得结果向右环移一个不定的数,并加上a、b、c或d中之一。最后用该结果取代a、b、c或d中之一。 以一下是每次操作中用到的四个非线性函数(每轮一个)。

其中,?是异或,∧是与,∨是或, 是反符号。 

如果X、Y和Z的对应位是独立和均匀的,那么结果的每一位也应是独立和均匀的。F是一个逐位运算的函数。即,如果X,那么Y,否则Z。函数H是逐位奇偶操作符。所有这些完成之后,将A,B,C,D分别加上a,b,c,d。然后用下一分组数据继续运行算法,最后的输出是A,B,C和D的级联。最后得到的A,B,C,D就是输出结果,A是低位,D为高位,DCBA组成128位输出结果。

 

 

SSH加密:

 

 

大多数人知道SSH是用来替代R命令集,是用于加密的远程登录,文件传输,甚至加密的FTP(SSH2内置), 因此SSH成为使用极广的服务之一,不仅如此,SSH还有另一项非常有用的功能,就是它的端口转发隧道功能,利用此功能,让一些不安全的服务象POP3,SMTP,FTP,LDAP等等通过SSH的加密隧道传输,然后,既然这些服务本身是不安全的,密码和内容是明文传送的,现在其它中间媒介也没无监听了。

SSH的加密隧道保护的只是中间传输的安全性,使得任何通常的嗅探工具软件无法获取发送内容

 

SSH:Secure Shell,是一种网络安全协议,主要用于登录远程计算机的加密过程。

登录方式主要有两种:

1、基于用户密码的登录方式:

加密原理:

 当服务器知道用户请求登录时,服务器会把自己的公钥发给用户,ssh会将服务器的公钥存放在客户端的~/.ssh/known_hosts文件下,用户会根据服务器给它发的公钥进行加密,加密好好之后返回给服务器,服务器用自己的私钥解密,如果密码正确,则用户会成功登录到服务器上。

如果服务器改变了自己的公钥,客户端想要登录时必须删除自己~/.ssh/known_hosts文件下的旧内容,重新获取服务器新的公钥。只要你知道服务器上的用户和密码,就可以成功登录到远程服务器上。

 

           命令格式: # ssh user@ip

           在你第一次登录时,界面上会出现如下图的情形:

 Are you sure you want to continue connecting (yes/no)?

它会给你提示:你确定你要继续链接吗?,这时,你输入yes就好。接下来会让你输入密码,只要正确输入就可成功登录。

 

2、基于密钥的登录方式:

加密原理:

你自己事先得创建一对密钥,把自己的公钥放在你需要登录的服务器上。当客户端需要请求密钥验证登录服务器时,服务器收到请求后,服务器就用公用密匙加密一段随机字符串并把它发送给客户端。客户端收到加密后的随机字符串之后就可以用客户端的的私钥加密再把它发送给服务器,如果服务器上你事先存放的公钥解密成功则证明用户是可信的,直接允许登录,不再要求密码。

 

获取自己密钥对的命令格式:$ ssh-keygen

运行上面的命令以后,系统会出现一系列提示,可以一路回车。其中有一个问题是,要不要对私钥设置口令(passphrase),如果担心私钥的安全,这里可以设置一个。

命令完成后,在~/.ssh/目录下会生成两个新文件:id_rsa.pub和id_rsa。前者存放你自己的公钥,后者存放你自己的私钥。

然后将自己的公钥传到服务器上,该命令格式为:$ ssh-copy-id user@ip

成功登录后,重启服务器ssh服务:   $ systemctl  restart  ssh.service

接下来就可以远程操控服务器了。

 

其中非对称加密算法用于在握手过程中加密生成的密码,对称加密算法用于对真正传输的数据进行加密,而HASH算法用于验证数据的完整性。

由于浏览器生成的密码是整个数据加密的关键,因此在传输的时候使用了非对称加密算法对其加密。

非对称加密算法会生成公钥和私钥,公钥只能用于加密数据,因此可以随意传输,而网站的私钥用于对数据进行解密,所以网站都会非常小心的保管自己的私钥,防止泄漏。

TLS握手过程中如果有任何错误,都会使加密连接断开,从而阻止了隐私信息的传输。

 

 

二、私钥的作用

握手阶段有三点需要注意。

(1)生成对话密钥一共需要三个随机数。

(2)握手之后的对话使用"对话密钥"加密(对称加密),服务器的公钥和私钥只用于加密和解密"对话密钥"(非对称加密),无其他作用。

(3)服务器公钥放在服务器的数字证书之中。

从上面第二点可知,整个对话过程中(握手阶段和其后的对话),服务器的公钥和私钥只需要用到一次。

 

 

苹果包装了MD5加密的方法,使用起来十分的方便。

 

1、导入头文件:

 

 

#import<CommonCrypto/CommonDigest.h>

 

2、MD5加密方法:

 

 

- (NSString *) md5:(NSString *) input {

    constchar *cStr = [input UTF8String];

    unsignedchar digest[CC_MD5_DIGEST_LENGTH];

    CC_MD5( cStr, strlen(cStr), digest ); // This is the md5 call

    

    NSMutableString *output = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2];

    

    for(int i = 0; i <CC_MD5_DIGEST_LENGTH; i++)

        [output appendFormat:@"%02x", digest[i]];

    

    return  output;

}

 

3、调用MD5方法:

[objc] view plain copy

NSString *str = @"123456";

 

NSString *result = [self md5:str];

 

NSLog(@"%@",result);

 

---------RSA原理--------

http://www.ruanyifeng.com/blog/2013/06/rsa_algorithm_part_one.html

http://www.ruanyifeng.com/blog/2013/07/rsa_algorithm_part_two.html

https://blog.csdn.net/dfskhgalshgkajghljgh/article/details/51557446

------------对称加密和非对称加密结合使用-----

参考结合RSA,AES128,MD5---移动端与服务端在通信层的加密处理(讲的庸俗易懂)
https://www.jianshu.com/p/b092b4fac27c

虽然非对称加密很安全,但是和对称加密比起来,它非常的慢,所以我们还是要用对称加密来传送消息,但对称加密所使用的密钥我们可以通过非对称加密的方式发送出去。过程:

 (1)、APP客户端需要和服务器进行数据交互,它的APP首先生成了一个随机数作为对称密钥(比如AES加密的密钥)。

 (2)、APP客户端向服务器请求公钥

 (3)、服务器将公钥发送给APP客户端

 (4)、APP客户端使用服务器的公钥将自己的对称密钥(比如AES加密的密钥)加密

 (5)、APP客户端将加密后的对称密钥发送给服务器

 (6)、服务器使用私钥解密得到APP客户端的对称密钥

 (7)、APP客户端与服务器可以使用对称密钥来对沟通的内容进行加密与解密了

服务器使用一个明文的服务地址来让大家获得“RSA公钥”,那么任何客户端就可以使用服务器公钥来RSA加密一个信息,这样就只有掌握了此公钥对应的RSA私钥的程序才能解密,而所有其它掌握了RSA公钥的客户端都不能揭密。
HTTPS可确保您的数据不会被拦截,因为拦截了也没法解密,因为其传输使用了RSA非对称加密。
您也可以使用自定义的RSA加解密,APP用公钥加密,服务器端用私钥解密,或者相反。
服务器端如果没法解密传来的数据,说明是非法数据,直接扔掉!这样确保只能通过app和服务器通讯。

 

 

.假设app端拥有公钥PublicKey,服务器端拥有公钥PublicKey和私钥PrivateKey。

.app发送请求到服务器端:app随机生成Byte[]随机密码,假设RandomKey=“123456”,通过AES算法,对Json数据利用进行加密。

.但是此刻服务器并不知道客户端的RandomKey是什么,因此需要同时将Randomkey传给服务器,否则服务器无法通过AES对Json数据进行解密。但是如果直接发送请求,Randomkey就会暴露,所以要对RandomKey进行不可逆的RSA加密。

.app将使用Randomkey进行AES加密的Json数据,和使用PublicKey进行RSA加密的RandomKey通过HTTP传送到服务器端。数据请求工作完成。

.服务器端接收到AES加密的Json数据和Rsa加密的RandomKey数据。

.服务器通过私钥PrivateKey对加密后的RandomKey进行Rsa解密。得到app生成的原始Randomkey。

.利用原始的RandomKey对加密后的Json数据进行AES对称解密。至此已经得到app端发过来的原始Json数据。进行常规的服务器业务操作,然后将返回数据通过app端的RandomKey进行AES加密gouhou后,Response返回。

.app端接收到Response的数据后,利用之前本地生成的RandomKey直接进行AES解密即可。

 

 

 

数字证书

数字证书原理:https://blog.csdn.net/preyta/article/details/57101236

公钥传输问题

在密文传输过程中,客户端(Client C)向服务器(Server S)发送数据,C使用S的公钥加密,这样只有S使用自己的私钥解密才能拿到信息,其他人即使得到了数据,没有S的私钥也没用。

但是如果有一个黑客H告诉C自己是S,并将自己的假公钥发送给C,那么C用假公钥加密数据并将数据发送给了H,那么H就顺利得到了信息,无法起到数据加密的作用。

这就需要一个中间人来颁发一个身份证明来证明S是真的S。

数字证书认证中心

这个中间人就是数字证书认证机构。

数字证书认证中心(Certificate Authority)(也被称为证书认证机构或CA)是指颁发证书、废除证书、更新证书、验证证书、管理密钥的机构。它能在认证某组织或个人后分发证书的机构,它验证的信息包括已签约的证书,当然它也负责吊销有危害的证书。

数字证书

中间人颁发的身份证明就是数字证书。

数字证书是一个包含 证书拥有者公钥、证书拥有者信息、证书认证中心数字签名的文件。 拿到数字证书后,我们解析证书的证书认证机构数字签名确保证书是真的,且没有被篡改过后,取得其中的公钥,然后就可以使用此公钥与浏览器进行交互了。

根证书

CA 这么重要,可是怎么能证明 CA 是真的呢?这个不用担心,许多 CA 都有嵌入在浏览器中的根证书,所以浏览器能自动识别它们。在一些API交互中,如请求支付宝的接口时,我们已经在本地存储了支付宝的证书了。

不用担心本地的根证书安全问题,如果本地存储的根证书都被修改了,那么加解密也就没有什么意义了。

证书链

由于世界上需要证书的组织众多,任何一家 CA 也不能处理全部的认证请求。于是大大小小的 CA 出现了,可是每个客户端不可能把他们的证书作为根证书全存储起来。

于是CA建立自上而下的信任链,下级 CA 信任上级 CA,下级 CA 由上级 CA 颁发证书并认证。因为下级 CA 的证书是用上级 CA 的密钥加密的,而上级 CA 的密钥只有自己知道,因此别人无法冒充上级 CA 给别人发证书。

在进行证书认证时,服务器会发给客户端一个包含着“证书机构证书”的证书,会层层链接到最上层的 CA,我们本地拥有最上级的 CA 的证书,如果能证明此 CA 的真实性,那么也便能证明服务器证书的可靠。

证书标准

X.509是目前最能用的证书标准, 证书由用户公共密钥和用户标识符组成。此外还包括版本号、证书序列号、CA标识符、签名算法标识、签发者名称、证书有效期等信息。这一标准的最新版本是X.509 v3,它定义了包含扩展信息的数字证书。该版数字证书提供了一个扩展信息字段,用来提供更多的灵活性及特殊应用环境下所需的信息传送。

 

 

 

 


证书预置和申请

1:客户端浏览器会预置根证书, 里面包含CA公钥
2:服务器去CA申请一个证书
3: CA用自己的签名去签一个证书,指纹信息保存在证书的数字摘要里面, 然后发送给服务器

一次访问流程(简化)

1: 客户端 sayHello
2: 服务器返回证书
3-1: 客户端验证证书内容有效性(过期时间, 域名是否相同等)
3-2: 验证证书的有效性 (是否被串改), 通过本地根证书的CA公钥解密数字摘要,看是否匹配。
3-3:如果数字签名验证通过, 就可以使用服务器证书里面提供的公钥进行下一步通信。

********

CA下发给网站的证书都是一个证书链,也就是一层一层的证书,从根证书开始,到下级CA,一层一层,最后一层就是网站证书。

浏览器收到服务器发送的证书后,需要验证其真实性。而证书的签名是通过签名算法上级CA的私钥生成的,并非很多文章里简单说的靠CA私钥生成。浏览器需要用上级CA的公钥才能解密签名,并与生成的指纹对比,那么问题来了,这个上级CA的公钥从哪来呢?

答案是此公钥来自于证书链该层的上级CA的证书明文内。单个X509v3证书由以下部分组成:

X.509v3证书由三部分组成:

  • tbsCertificate (to be signed certificate),待签名证书。
  • SignatureAlgorithm,签名算法。
  • SignatureValue,签名值。

tbsCertificate又包含10项内容,在HTTPS握手过程中以明文方式传输:

  • Version Number,版本号。
  • Serial Number,序列号。
  • Signature Algorithm ID,签名算法ID。
  • Issuer Name,发行者。
  • Validity period,有效时间。
  • Subject name ,证书主体名称。
  • Subject Public Key Info ,证书主体公钥信息,包含公钥算法和公钥值。
  • Issuer Unique Identifier (optional),发行商唯一ID。
  • Subject Unique Identifier (optional),主体唯一ID。
  • Extensions (optional),扩展。

证书链由多个证书一层一层组成的,除了最底层的网站证书的公钥是给用户加密报文外,其他层证书中的公钥均用于解密底层的证书指纹签名。最高层的根证书是自签名的,也就是自己颁发给自己,所以它的公钥不仅用来解密下层的签名,也用来给自己的签名解密。

验证证书是否真实的任务完成了,那么证书是否可靠如何验证呢?一句话,只要根证书可靠,整个证书链就可靠,而根证书是否可靠要看这个根证书是否在操作系统或浏览器内置的可信根证书内,在的话就可信

 

RSA加密标准

 

公钥加密标准

公钥加密标准(Public Key Cryptography Standards, PKCS),此系列标准的设计与发布皆由RSA信息安全公司所制定。包括证书申请、证书更新、证书作废表发布、扩展证书内容以及数字签名、数字信封的格式等方面的一系列相关协议。

目前在使用的最高版本为 PKCS#12,这版本也是我工作中使用最多的版本,此外我还接触过 PKCS#7 版本,java多用 PKCS#8 版本,下面分别说一下。

PKCS#7:

定义一种通用的消息语法,包括数字签名和加密等用于增强的加密机制,PKCS#7与PEM兼容,所以不需其他密码操作,就可以将加密的消息转换成PEM消息。规范了以公开密钥基础设施(PKI)所产生之签名/密文之格式。其拓展数字证书在 S/MIME与CMS 的应用,PKCS#7一般主要用来做数字信封。

PKCS#8

描述私有密钥信息格式,该信息包括公开密钥算法的私有密钥以及可选的属性集等,Apache读取证书私钥的标准,在JAVA平台中使用。(接入一些支付公司中经常会提供此格式的密钥,有些印象)

PKCS#12:

描述个人信息交换语法标准。描述了将用户公钥、私钥、证书和其他相关信息打包的语法。 含有私钥,同时可以有公钥,有口令保护 格式一般为 .pfx。 由于它可以加密码保护,打开时需要一串特殊密码,所以相对安全些。

证书和密钥文件格式

需要注意:证书文件格式与加密标准并没有严格的对应关系,证书文件格式是存储证书的方式不同,可能存储的内容也略有不同。而加密标准是使用证书文件进行加解密的方式不同。

pem格式

最普通的证书格式,以-----BEGIN CERTIFICATE----- 开头,以-----END CERTIFICATE-----结尾;有些pem证书把私钥也放在了一个文件中,但是很多平台还是需求证书和私钥分开放在不同的文件中。 pem证书有以下特点:

  • base64编码;
  • 有.pem, .crt, .cer, .key文件后缀;
  • Apache等类似服务器使用pem格式证书;

der格式

der格式是pem格式证书的二进制格式,证书和私钥都可以以der格式存储。 其特点为:

  • 二进制格式;
  • 以.cer或.der格式为后缀;
  • 常被用于java平台;

PKCS#7格式

它是一种PKCS#7格式以-----BEGIN PKCS-----开头,以-----END PKCS7-----结尾,它只能保存证书或证书链,不能保存私钥。 其特点为:

  • base64编码;
  • 文件后缀为 .p7p, .p7c;
  • window或java tomcat等平台支持此类型;

PKCS#12(pfx)格式

它能把服务器证书(包括公钥),中间证书和私钥存储在一起。特点为:

  • 二进制文档;
  • 以 .pfx 或.p12为后缀;
  • 经常在windows系统内被用于导入导出证书和私钥;
  • 打开可能需要额外密码;

密钥的保存

对于密钥(单指公私钥)的保存,并不需要特殊的格式,直接将base64编码后的密钥作为字符串存入文档即可。

 

 

--------RSA加密操作------------

 

  1. 密钥生成和使用
  2. openssl genrsa -out rsa_private_key.pem 1024 // 生产一个1024位的私钥, 保存在 rsa_private_key.pem 文件里
  3. openssl rsa -in rsa_private_key.pem -pubout -out pub.pem // 通过私钥生产公钥
  4. 此外,介绍一下openssl提供的一个测试加密速度的小工具,可以查看一定时间内某算法计算的次数,让我们对各种加密算法的速度有一个大概的认识。
  5. openssl speed algciper
  6. eg: openssl speed rsa1024
  7. openssl speed des-ede3
  8. 格式转换
  9. 从pfx文件中提取公私钥
  10. openssl pkcs12 -in source.pfx -nocerts -nodes -out key.key // 从pfx文件中获取到密匙对文件,有时会需要密码
  11. opensll rsa -in key.key -out pri.key // 从密匙对文件中获取到私匙。
  12. opensll rsa -in key.key -pubout -out pub.key // 从密匙对文件中获取到公匙;
  13. openssl pkcs8 -in pri.key -out repri.key -outform der -nocrypt -topk8 //java语言用
  14. 各种证书之间的互相转换
  15. PEM to DER
  16. openssl x509 -outform der -in certificate.pem -out certificate.der
  17. —————————————————————————————————–
  18. PEM to P7B
  19. openssl crl2pkcs7 -nocrl -certfile certificate.cer -out certificate.p7b -certfile CAcert.cer
  20. ———————————————————————————————————————————-
  21. PEM to PFX
  22. openssl pkcs12 -export -out certificate.pfx -inkey privateKey.key -in certificate.crt -certfile CAcert.crt
  23. ——————————————————————————————————————————————————
  24. DER to PEM
  25. openssl x509 -inform der -in certificate.cer -out certificate.pem
  26. ————————————————————————————————
  27. P7B to PEM
  28. openssl pkcs7 -print_certs -in certificate.p7b -out certificate.cer
  29. ————————————————————————————————-
  30. P7B to PFX
  31. openssl pkcs7 -print_certs -in certificate.p7b -out certificate.cer
  32. openssl pkcs12 -export -in certificate.cer -inkey privateKey.key -out certificate.pfx -certfile CAcert.cer
  33. ——————————————————————————————————————————————————-
  34. PFX to PEM
  35. openssl pkcs12 -in certificate.pfx -out certificate.cer -nodes
  36. PHP中使用RSA
  37. 作为一个PHPer,当然还要提一下在 PHP 中如何使用 RSA 加密,所用工具依然是强大的openssl扩展:
  38. # 从pfx文件中提取私钥和证书(需要传入密码 $password):
  39. openssl_pkcs12_read($file_content, $key, $password);
  40. $key['pkey'] => 私钥
  41. $key['cert'] => 证书
  42. # 解析x.509证书
  43. openssl_x509_read($cert);
  44. # 以pkcs7加密标准加解密/签名验签数据:需要注意pkcs7操作都需要使用一个临时文件,多进程时要考虑一下文件冲突问题,还有别忘了最后释放临时文件。
  45. openssl_pkcs7_encrypt()/openssl_pkcs7_decrypt()
  46. openssl_pkcs7_sign()/openssl_pkcs7_verify()
  47. # 从字符串中获取公私钥:
  48. openssl_pkey_get_private()/openssl_pkey_get_public()
  49. # RSA以pkcs#12标准加解密/签名验签数据:
  50. openssl_private(public)_encrypt()/openssl_private(public)_decrypt()

 

证书预置和申请

1:客户端浏览器会预置根证书, 里面包含CA公钥
2:服务器去CA申请一个证书
3: CA用自己的签名去签一个证书,指纹信息保存在证书的数字摘要里面, 然后发送给服务器

一次访问流程(简化)

1: 客户端 sayHello
2: 服务器返回证书
3-1: 客户端验证证书内容有效性(过期时间, 域名是否相同等)
3-2: 验证证书的有效性 (是否被串改), 通过本地根证书的CA公钥解密数字摘要,看是否匹配。
3-3:如果数字签名验证通过, 就可以使用服务器证书里面提供的公钥进行下一步通信。

 

项目中的一种加密方式:

  1. #import "WofuCommanManager.h"
  2. #import "AppDelegate.h"
  3. #import <CommonCrypto/CommonDigest.h>
  4. #import "AFNetworking.h"
  5. @implementation WofuCommanManager
  6. +(instancetype)sharedManager{
  7. static WofuCommanManager *wofucommanger;
  8. static dispatch_once_t onceToken;
  9. dispatch_once(&onceToken, ^{
  10. wofucommanger =[[WofuCommanManager alloc]init];
  11. });
  12. return wofucommanger;
  13. }
  14. //初始化sdk
  15. +(void)initSDKWithagent:(NSString *)agent seckey:(NSString *)seckey brand:(NSString *)brand{
  16. [WofuCommanManager sharedManager].agent=agent;//代 商UUID,由平台统 下发
  17. // NSLog(@"agent --%@",[WofuCommanManager sharedManager].agent);
  18. [WofuCommanManager sharedManager].seckey=seckey;//安全密钥
  19. [WofuCommanManager sharedManager].brand=brand;
  20. }
  21. //注册SDK
  22. +(NSDictionary *)registerSDKWithmobile:(NSString *)mobile{
  23. NSMutableDictionary *params=[[self class] publicDict];
  24. [params setObject:@"enroll" forKey:@"service"];
  25. [params setObject:mobile forKey:@"mobile"];
  26. [WofuCommanManager sharedManager].sdkmobile=mobile;//
  27. [params setObject:[WofuCommanManager sharedManager].brand forKey:@"brand"];
  28. [params setObject:[WofuCommanManager sharedManager].agent forKey:@"token"];
  29. return [[self class] publicSignParamsWithDict:params];
  30. }
  31. //签到
  32. +(NSDictionary *)signSDKWithmobile:(NSString *)mobile{
  33. NSMutableDictionary *params=[[self class] publicDict];
  34. [params setObject:@"signin" forKey:@"service"];
  35. [params setObject:mobile forKey:@"mobile"];
  36. [params setObject:[WofuCommanManager sharedManager].agent forKey:@"token"];
  37. return [[self class] publicSignParamsWithDict:params];
  38. }
  39. //用户信息查询
  40. +(NSDictionary *)userInfoSearchSDKWith{
  41. NSMutableDictionary *params=[[self class] publicDict];
  42. [params setObject:@"info" forKey:@"service"];
  43. [params setObject:[WofuCommanManager sharedManager].sdkToken forKey:@"token"];
  44. return [[self class] publicSignParamsWithDict:params];
  45. }
  46. //借记卡绑定
  47. +(NSDictionary *)bankcardBindWithname:(NSString *)name idno:(NSString *)idno card_no:(NSString *)card_no bank_name:(NSString *)bank_name city_name:(NSString *)city_name{
  48. NSMutableDictionary *params=[[self class] publicDict];
  49. [params setObject:@"debit.bind" forKey:@"service"];
  50. [params setObject:name forKey:@"name"];
  51. [params setObject:idno forKey:@"idno"];
  52. [params setObject:card_no forKey:@"card_no"];
  53. [params setObject:bank_name forKey:@"bank_name"];
  54. [params setObject:city_name forKey:@"city_name"];
  55. [params setObject:[WofuCommanManager sharedManager].sdkToken forKey:@"token"];
  56. return [[self class] publicSignParamsWithDict:params];
  57. }
  58. //借记卡解绑
  59. +(NSDictionary *)bankcardUnBindWithcard_no:(NSString *)card_no{
  60. NSMutableDictionary *params=[[self class] publicDict];
  61. [params setObject:@"debit.unbind" forKey:@"service"];
  62. [params setObject:card_no forKey:@"card_no"];
  63. [params setObject:[WofuCommanManager sharedManager].sdkToken forKey:@"token"];
  64. return [[self class] publicSignParamsWithDict:params];
  65. }
  66. //借记卡变更
  67. +(NSDictionary *)upDateBankcardWithold_card_no:(NSString *)old_card_no new_card_no:(NSString *)new_card_no{
  68. NSMutableDictionary *params=[[self class] publicDict];
  69. [params setObject:@"debit.alter" forKey:@"service"];
  70. [params setObject:old_card_no forKey:@"old_card_no"];
  71. [params setObject:new_card_no forKey:@"new_card_no"];
  72. [params setObject:[WofuCommanManager sharedManager].sdkToken forKey:@"token"];
  73. return [[self class] publicSignParamsWithDict:params];
  74. }
  75. //贷记卡绑定
  76. +(NSDictionary *)creditBindWithcard_no:(NSString *)card_no cvn:(NSString *)cvn expiry:(NSString *)expiry{
  77. NSMutableDictionary *params=[[self class] publicDict];
  78. [params setObject:@"credit.bind" forKey:@"service"];
  79. [params setObject:card_no forKey:@"card_no"];
  80. [params setObject:cvn forKey:@"cvn"];
  81. [params setObject:expiry forKey:@"expiry"];
  82. [params setObject:[WofuCommanManager sharedManager].sdkToken forKey:@"token"];
  83. return [[self class] publicSignParamsWithDict:params];
  84. }
  85. //贷记卡解绑
  86. +(NSDictionary *)creditUnBindWithcard_no:(NSString *)card_no{
  87. NSMutableDictionary *params=[[self class] publicDict];
  88. [params setObject:@"credit.unbind" forKey:@"service"];
  89. [params setObject:card_no forKey:@"card_no"];
  90. [params setObject:[WofuCommanManager sharedManager].sdkToken forKey:@"token"];
  91. return [[self class] publicSignParamsWithDict:params];
  92. }
  93. //贷记卡列表
  94. +(NSDictionary *)creditListSearch{
  95. NSMutableDictionary *params=[[self class] publicDict];
  96. [params setObject:@"credit.list" forKey:@"service"];
  97. [params setObject:[WofuCommanManager sharedManager].sdkToken forKey:@"token"];
  98. return [[self class] publicSignParamsWithDict:params];
  99. }
  100. //消费
  101. +(NSDictionary *)consumeWithcard_no:(NSString *)card_no cvn:(NSString *)cvn expiry:(NSString *)expiry amount:(NSString *)amount{
  102. NSMutableDictionary *params=[[self class] publicDict];
  103. [params setObject:@"order.new" forKey:@"service"];
  104. [params setObject:card_no forKey:@"card_no"];
  105. [params setObject:cvn forKey:@"cvn"];
  106. [params setObject:amount forKey:@"amount"];
  107. [params setObject:expiry forKey:@"expiry"];
  108. [params setObject:[WofuCommanManager sharedManager].sdkToken forKey:@"token"];
  109. return [[self class] publicSignParamsWithDict:params];
  110. }
  111. //交易查询
  112. +(NSDictionary *)orderQueryWithorder_id:(NSString *)order_id{
  113. NSMutableDictionary *params=[[self class] publicDict];
  114. [params setObject:@"order.query" forKey:@"service"];
  115. [params setObject:order_id forKey:@"order_id"];
  116. [params setObject:[WofuCommanManager sharedManager].sdkToken forKey:@"token"];
  117. return [[self class] publicSignParamsWithDict:params];
  118. }
  119. //交易列表
  120. +(NSDictionary *)orderListWithserial:(NSString *)serial limit:(NSString *)limit{
  121. NSMutableDictionary *params=[[self class] publicDict];
  122. [params setObject:@"order.list" forKey:@"service"];
  123. [params setObject:serial forKey:@"serial"];
  124. [params setObject:limit forKey:@"limit"];
  125. [params setObject:[WofuCommanManager sharedManager].sdkToken forKey:@"token"];
  126. return [[self class] publicSignParamsWithDict:params];
  127. }
  128. //SHA1加密方式
  129. +(NSString*)sha1WithStr:(NSString *)str
  130. {
  131. const char *cstr = [str cStringUsingEncoding:NSUTF8StringEncoding];
  132. NSData *data = [NSData dataWithBytes:cstr length: strlen(cstr)];
  133. uint8_t digest[CC_SHA1_DIGEST_LENGTH];
  134. CC_SHA1(data.bytes, data.length, digest);
  135. NSMutableString* output = [NSMutableString stringWithCapacity:CC_SHA1_DIGEST_LENGTH * 2];
  136. for(int i = 0; i < CC_SHA1_DIGEST_LENGTH; i++)
  137. [output appendFormat:@"%02x", digest[i]];
  138. return output;
  139. }
  140. +(NSMutableDictionary *)publicDict{
  141. NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary];
  142. CFShow(CFBridgingRetain(infoDictionary));//打印出infoDictionary的详细信息
  143. //bundelID
  144. NSString *bundelID= [[NSBundle mainBundle] bundleIdentifier];
  145. // NSLog(@"bundelID---%@",bundelID);
  146. // app名称displayName
  147. NSString *app_Name = [infoDictionary objectForKey:@"CFBundleDisplayName"];
  148. // NSLog(@"app名称displayname---%@",app_Name);
  149. // app名称name,当displayname存在时,name显示为override,displayname不存在时,name正常显示
  150. NSString *name = [infoDictionary objectForKey:@"CFBundleName"];
  151. // NSLog(@"app名称name---%@",name);
  152. //手机序列号(唯一标识)
  153. NSString* identifierNumber =[[[UIDevice currentDevice] identifierForVendor]UUIDString];
  154. // NSLog(@"手机序列号: %@",identifierNumber);
  155. //设备名称
  156. NSString* deviceName = [[UIDevice currentDevice] systemName];
  157. // NSLog(@"设备名称: %@",deviceName );
  158. //手机系统版本
  159. NSString* phoneVersion = [[UIDevice currentDevice] systemVersion];
  160. // NSLog(@"手机系统版本: %@", phoneVersion);
  161. //手机型号
  162. NSString* phoneModel = [[UIDevice currentDevice] model];
  163. // NSLog(@"手机型号: %@",phoneModel );
  164. NSMutableString *model=[NSMutableString stringWithString:[deviceName stringByAppendingString:[NSString stringWithFormat:@" %@",phoneVersion]]];
  165. [model appendString:[NSString stringWithFormat:@"/%@",phoneModel]];
  166. // NSLog(@"model---%@",model);
  167. NSString *agentStr=[[WofuCommanManager sharedManager].agent stringByReplacingOccurrencesOfString:@"-" withString:@""];
  168. // NSLog(@"agentStr---%@",agentStr);
  169. int randNum=19+arc4random()%10;
  170. NSString *noiseStr=[agentStr substringToIndex:randNum];
  171. NSMutableDictionary *params=[NSMutableDictionary dictionaryWithDictionary:@{
  172. @"version":@"1.1",
  173. @"agent":[WofuCommanManager sharedManager].agent,
  174. @"device":identifierNumber,
  175. @"model":model,
  176. @"package":bundelID,
  177. @"appname":app_Name?app_Name:name,
  178. @"noise":noiseStr
  179. }];
  180. return params;
  181. }
  182. +(NSMutableDictionary *)publicSignParamsWithDict:(NSMutableDictionary *)params{
  183. NSArray *keyArr=[params allKeys];
  184. keyArr = [keyArr sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2){
  185. NSComparisonResult result = [obj1 compare:obj2];
  186. return result;
  187. }];
  188. // NSLog(@"key数组002%@",keyArr);
  189. NSMutableString *signStr=[[NSMutableString alloc]initWithCapacity:10];
  190. for (int i=0; i<keyArr.count; i++) {
  191. NSString *key=keyArr[i];
  192. [signStr appendString:[NSString stringWithFormat:@"%@=",key]];
  193. [signStr
  194. appendString:params[key]];
  195. [signStr appendString:@"&"];
  196. }
  197. [signStr appendString:[NSString stringWithFormat:@"key=%@",SECKEY]];
  198. // NSLog(@"拼接参数---%@",signStr);
  199. //SHA1计算上面拼接的字符串
  200. NSString *sha1str=[self sha1WithStr:signStr];
  201. NSLog(@"sha1--%@",sha1str);
  202. [params setObject:sha1str forKey:@"sign"];
  203. return params;
  204. }
  205. @end

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/732641
推荐阅读
相关标签
  

闽ICP备14008679号