非对称加密在移动端开发中的常用场景

988 阅读9分钟

概述

非对称加密简介

公开密钥密码学(英语:Public-key cryptography)也称非对称式密码学(英语:Asymmetric cryptography)是密码学的一种算法,它需要两个密钥,一个是公开密钥,另一个是私有密钥;公钥用作加密,私钥则用作解密,反之亦可。使用公钥把明文加密后所得的密文,只能用相对应的私钥才能解密并得到原本的明文,最初用来加密的公钥不能用作解密。由于加密和解密需要两个不同的密钥,故被称为非对称加密。不同于加密和解密都使用同一个密钥的对称加密,公钥可以公开,可任意向外发布,私钥不可以公开,必须由用户自行严格秘密保管,绝不透过任何途径向任何人提供,也不会透露给被信任的要通信的另一方。

以上这段话是引用自公开密钥加密维基百科

非对称加密和对称加密的区别

  • 对称加密的加密和解密都是用同一个密钥值,非对称加密用于消息解密的密钥与用于消息加密的密钥不同。

  • 非对称加密算法比对称加密算法慢数千倍。

数字签名

数字签名(Digital Signature) 是一种相当于现实世界中的盖章签字的功能在数字信息领域中的实现。数字签名可以识别篡改和伪装。

在数字签名技术中,有两个过程,分别是签名生成和签名验证,其核心技术就是非对称加密。

签名生成由通信中的发起方进行,其过程如下所示。首先对通信内容进行哈希,然后使用发送方的私钥进行加密,最终得到签名。

image.png

签名验证由通信中的接收方进行,其过程如下所示。通常发送方会把消息、签名一起发送给接收方。接收方首先使用发送方的公钥对签名进行解密,计算得出一个摘要。然后对消息进行哈希,计算得出另一个摘要。最后判断两个摘要是否相等,如果相等则说明接收到的消息没有被第三方进行篡改。 image.png

数字证书

上面签名的接收方是如何获取到发送方的公钥的呢?接收方又是如何确定该公钥就是属于发送方的呢?这就是数字证书要做到事。

数字证书(Digital Certificate) 是一种相当于现实世界中身份证的功能在数字信息领域中的实现。数字证书包含了个人或机构的身份信息及其公钥,因此也称为公钥证书(Public-Key Certificate,PKC)。 image.png 类似于身份证是由权威的公安局颁发,公钥证书也是由权威的认证机构(Certificate Authority,CA) 颁发。认证机构向接收方提供发送方的证书,证书中包含了发送方的身份信息和公钥。为了防止证书在颁发过程中被篡改,认证机构会将身份信息和公钥作为消息,用CA 私钥 进行签名,进而将身份信息、公钥、签名 一起放入证书,如下图所示。 image.png

  • 根证书以及证书信任链 接收方得到发送方证书时,通过 CA 公钥对证书进行签名验证。很多情况下,CA 公钥则又是由另一个更加权威的机构颁发。类似于地方公安局的证书是由市级公安局颁发,市级公安局的证书又是由省级公安局颁发。证书是具有信任链(Chain of Trust)的,根证书(Root Certificate) 是信任源,即信任链的起源。

根证书的颁发者被称为 Root Certificate Authority(Root CA)。某一认证领域内的根证书是 Root CA 自行颁发给自己的证书(Self-signed Certificate),安装证书意味着对这个 CA 认证中心的信任。

根据证书在信任链中所处的位置,可以将证书分为三种:

  • 根证书(Root Certificate)
  • 中间证书(Intermediate Certificate)
  • 叶子证书(Leaf Certificate)

这里就有一个根本性的问题:如何保证根证书是可信的?

事实上,根证书都是随软件一起安装的,如:操作系统安装时会内置一份可信的根证书列表。

apple开发证书

首先明确证书的目的是证明你确实是apple开发者(毕竟开发者是要给apple爸爸钱的) 我们来看一下 MacOS 系统中关于 iOS 开发证书的信任链示例(通过“钥匙串”查看):

-- Apple Root Certificate Authority:根证书
   -- Apple Worldwide Developer Relations Certification Authority:中间证书
      -- iPhone Developer:(XXXXXXX):叶子证书

image.png

使用流程

  • 开发者在本地生成密钥对,并提供开发者的身份信息。
  • 将密钥对中的公钥、身份信息发送给 CA。
  • CA 使用 CA 私钥对开发者的公钥、身份信息进行签名。
  • CA 将开发者的公钥、身份信息、签名组装成证书以供下载。

image.png 注意:从 Apple Member Center 网站下载证书到 Mac 上双击即可安装。

手动点击 *.cer 安装证书到 macOS 时,Keychain Access 追溯其签发 CA 为 AppleWWDRCA(Apple Worldwide Developer Relations Certification Authority),利用 AppleWWDRCA 证书公钥对该开发证书数字签名进行解密和校验。校验成功会标记此证书有效。

  • 验证 & 运行 在真机上运行测试包和正式包时,系统对两者的验证有所不同。测试包在设备上进行了完整的签名验证,正式包则把验证过程交给了 App Store,App Store 验证通过后重新进行一次签名,设备下载正式包后进行的验证过程则简化很多。

  • 测试包的运行验证过程:

  1. Xcode 证书在本机 Keychain Access 匹配的 Key Pair 的私钥对应用程序 内容 进行签名(CodeSign)。

  2. iOS系统使用本地内置的 CA 公钥对 Provisioning Profile 中匹配的 certificate 进行签名验证,从而确认匹配到的证书的合法性。

  3. iOS系统使用 Provisioning Profile 中的匹配的,且经过 CA 验证过的 certificate(即打包应用程序的开发者的证书)中取出公钥,对 App 进行签名验证,否则无法启动 App。

git

目前各大公司的代码版本管理大多都是采用git,一般我们在使用的时候,会先在本机生成一对非对称秘钥即公钥和私钥,然后把公钥放入git账号设置中。如果不这样,使用https去clone仓库,会导致我们每次push代码都需要输入账号密码,很不方便。为什么使用公钥放入git账户设置中可以免去每次push代码时输入账号和密码呢,这里就要讲到SSH了,其核心还是非对称加密。其实git管理代码的验证这块有两块,一个是验证自身,一个是每次push代码时确认是本人提交。

SSH 是 Secure Shell 的缩写即安全外壳协议,SSH 为建立在应用层基础上的安全协议。SSH 为远程登录会话和其他网络服务提供安全性的协议。SSH之所以能够保证安全,原因在于它采用了非对称加密。

SSH的使用过程

  • 远程主机收到用户的登录请求,把自己的公钥发给用户。
  • 用户使用这个公钥,将登录密码加密后,发送回来。
  • 远程主机用自己的私钥,解密登录密码,如果密码正确,就同意用户登录。

以上这个过程本身是安全的,但是实施的时候存在一个风险:如果有人截获了登录请求,然后冒充远程主机,将伪造的公钥发给用户,那么用户很难辨别真伪。因为不像https协议,SSH协议的公钥是没有证书中心(CA)公证的。如果攻击者插在用户与远程主机之间,用伪造的公钥,获取用户的登录密码。再用这个密码登录远程主机,那么SSH的安全机制就荡然无存了。这种风险就是著名的"中间人攻击"(Man-in-the-middle attack)。

如果你是第一次登录对方主机,系统会出现下面的提示:

  $ ssh user@host

  The authenticity of host 'host (12.18.429.21)' can't be established.

  RSA key fingerprint is 98:2e:d7:e0:de:9f:ac:67:28:c2:42:2d:37:16:58:4d.

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

这段话的意思是,无法确认host主机的真实性,只知道它的公钥指纹,问你还想继续连接吗?

所谓"公钥指纹",是指公钥长度较长(这里采用RSA算法,长达1024位),很难比对,所以对其进行MD5计算,将它变成一个128位的指纹。上例中是98:2e:d7:e0:de:9f:ac:67:28:c2:42:2d:37:16:58:4d,再进行比较,就容易多了。

很自然的一个问题就是,用户怎么知道远程主机的公钥指纹应该是多少?回答是没有好办法,远程主机必须在自己的网站上贴出公钥指纹,以便用户自行核对。如果你实在担心有人冒充GitHub服务器,输入yes前可以对照GitHub的RSA Key的指纹信息是否与SSH连接给出的一致。

假定经过风险衡量以后,用户决定接受这个远程主机的公钥。

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

系统会出现一句提示,表示host主机已经得到认可。

  Warning: Permanently added 'host,12.18.429.21' (RSA) to the list of known hosts.

然后,会要求输入密码。

  Password: (enter password)

如果密码正确,就可以登录了。

当远程主机的公钥被接受以后,它就会被保存在文件$HOME/.ssh/known_hosts之中。下次再连接这台主机,系统就会认出它的公钥已经保存在本地了,从而跳过警告部分,直接提示输入密码。

每个SSH用户都有自己的known_hosts文件,此外系统也有一个这样的文件,通常是/etc/ssh/ssh_known_hosts,保存一些对所有用户都可信赖的远程主机的公钥。

  • 公钥登录 所谓"公钥登录",原理很简单,就是用户将自己的公钥储存在远程主机上。登录的时候,远程主机会向用户发送一段随机字符串,用户用自己的私钥加密后,再发回来。远程主机用事先储存的公钥进行解密,如果成功,就证明用户是可信的,直接允许登录shell,不再要求密码。相比使用密码登录,每次都必须输入密码,SSH提供的公钥登录,可以省去输入密码的步骤,非常方便。

公钥登录要求用户必须提供自己的公钥。如果没有现成的,可以直接用ssh-keygen生成一个:

  $ ssh-keygen

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

运行结束以后,在$HOME/.ssh/目录下,会新生成两个文件:id_rsa.pub和id_rsa。前者是你的公钥,后者是你的私钥。

这时再输入下面的命令,将公钥传送到远程主机host上面:

  $ ssh-copy-id user@host

好了,从此你再登录,就不需要输入密码了。

HTTPS

HTTPS(全称:Hyper Text Transfer Protocol over Secure Socket Layer)安全套接字层超文本传输协议,HTTPS用于安全的HTTP数据传输。HTTPS的安全基础是SSL。网络请求方式通常分为两种,分别是HTTP请求和HTTPS请求,其中HTTP的传输属于明文传输,在传输的过程中容易被人截取并且偷窥其中的内容,而HTTPS是一种在HTTP的基础上加了SSL/TLS层(安全套接层)的安全的超文本传输协议,其传输的内容都是加密过的,所以说是一种安全的传输;另外http和https使用的端口不一样,前者是80,后者是443;

HTTPS = 非对称加密交换对称密钥 + 数字证书验证身份 + 对称密钥加解密传输的数据

image.png

由上可知HTTPS涉及到非对称加密解密,数字签名,数字证书,证书链等等的知识,但核心还是非对称加密。

参考:

公开密钥加密

iOS 证书幕后原理