彻底搞懂IOS签名机制

目录

 

一、加密/解密

1、对称加密:

2、非对称加密:

3、秘钥配送问题解答

4、中间人攻击

二、数字签名

1、单向散列函数

2、数字签名

三、数字证书

四、IOS签名机制

1、IOS简单签名

2、IOS签名机制优化1

3、IOS签名机制优化2

4、IOS签名机制最终流程


一、加密/解密

          常见的加密解密算法分为“对称加密”和“非对称加密”两种。

1、对称加密:

          通信双方共享同一个秘钥,发收信双方要想进行加密通信,都使用这个密钥对数据进行加密和解密。常见的基于“对称密钥”的加密算法主要有DES、3DES(TripleDES)、AES、RC2、RC4、RC5和Blowfish等等。

 优缺点:

     优点:算法公开、计算量小、加密速度快、加密效率高。

     缺点: 

1、通信双方都使用同样钥匙,安全性得不到保证,存在秘钥配送问题

2、每对用户每次使用对称加密算法时,都需要使用其他人不知道的惟一钥匙,这会使得发收信双方所拥有的钥匙数量呈几何级数增长,密钥管理成为用户的负担。对称加密算法在分布式网络系统上使用较为困难,主要是因为密钥管理困难,使用成本较高。

具体使用如下图:

                                    

从左向右为发送方A向接收方B发送信息:发送方利用秘钥Key进行加密成为密文,接收方收到密文后,利用秘钥Key进行解密还原为原来的内容。但这就引发出一个问题,如果发送方A和接收方B距离很远,那A如何把这个秘钥Key发送给B呢?才能在发送的过程中不被别人窃取呢?这就使得,对称加密算法遇到了秘钥配送问题,带着这个问题,下面来研究下非对称加密的方式。

2、非对称加密:

顾名思义,非对称加密算法就是加密和解密使用的是不对称的秘钥,这两个秘钥我们分别称之为公钥和私钥。公钥:就是公开的,大家都可以拿到这个秘钥来进行加密;私钥,就是私有的,这个不能被别人使用,只能自己使用。

通常,发送方使用公钥来加密,接收方使用私钥来解密,反过来如果使用私钥加密,那么就只能使用公钥来解密,它来出来就是一对的而且唯一的,只能是一个加,一个解。

常见的非对称加密算法有RSA算法、DSA算法、ECC算法等等,有兴趣的可以研究下这篇文章----加解密篇 - 非对称加密算法 (RSA、DSA、ECC、DH) 

具体使用如下图:

从左向右为发送方A向接收方B发送信息:与对称加密不同,接收方B在此之前,先把自己的公钥发送给发送方A,发送方拿到公钥以后,对数据进行加密。因为非对称加密的特殊性,加密后的密文只能由私钥进行解密,所以,只有接收方B才可以解密,这样就保证了数据的安全性。

总结下非对称加密的特点:

  • 加密密钥,一般是公开的,因此该密钥称为公钥(public key)
  • 由私钥加密的密文,必须使用与该私钥对应的公钥才能解密
  • 由公钥加密的密文,必须使用与该公钥对应的私钥才能解密
  • 公钥和私钥是一 一对应的,是不能单独生成的,一对公钥和密钥统称为密钥对(key pair)
  • 解密密钥,由消息接收者自己保管的,不能公开,因此也称为私钥(private key)

生成RSA对称秘钥:https://www.cnblogs.com/hxwj/archive/2016/01/27/5163635.html

IOS开发中非对称加密:https://www.jianshu.com/p/8c48ed5f2700

 

3、秘钥配送问题解答

针对上面提到的秘钥配送问题,现在可以进行解答了。 

                                        

如上图,我们把A作为发送方,把B作为接收方。当A和B要进行通信的时候,因为在B端,已经生成了一对公钥和私钥。这个时候公钥是公开的,所以,通信前,接收方B先把公钥发送给发送方A;

当A拿到公钥以后,它在本地利用DES或者AES对称算法生成了一个秘钥key,然后利用拿到的公钥对这个Key进行加密生成密文回传给接收放B(如上图第2、3步)。

当B拿到这个密文以后,使用私钥进行解密(如上图第4步),解密以后就拿到了这个秘钥key了。

经过以上步骤以后,A和B双方的通信就都可以使用这个秘钥key对数据进行加解密了(如上图第5步),这样就解决了秘钥配送问题。

这个时候可能有人会问,那为什么要配送这个秘钥?直接利用公私钥在双方加解密不就可以了吗?

这里只做一个总结,就不详细展开了:

  1. 公钥私钥加解密速度很慢,特别是对大文件
  2. 秘钥key是随机生成的,保证每次会话使用的秘钥key都不相同,增加安全性
  3. 对称秘钥加密速度很快

 

4、中间人攻击

经过以上的加密步骤难道就真的能保证数据安全吗?我们考虑这么一种场景,如下图: 

              

假设发送方和接收方使用了上面的那种方式进行通信,但是,有一个人C(因为在他俩中间,所以称之为中间人),他是一个黑客,想要获取A和B他们交换的信息。因为接收方B的公钥是公开的,所以C也是可以拿到的,那么A和B之间的通信流程就变成了这样:

1、C截取了B发送给A的公钥,并且存储了起来,同时,他自己本地也生成了一对公钥和私钥,并且把自己的公钥C发送给了A;

2、 A自己生成了一个秘钥A,同时用收到的公钥C加密,然后发送给了C;

3、C用自己的私钥将其解密,并将秘钥A存储在了本地;同时他自己生成了一个秘钥C,并且用从第一步获取到的B的公钥加密,并且发送给了B;

4、B用自己的私钥解密,并且把秘钥C存储在了本地,以后就用这个秘钥C来加密信息然后进行通信。

这样,整个通信就建立了,只不过在A和B通信的所有信息都会受到中间人C的监听,所以,还能说上面这种方式很安全吗?

其实仔细想想,出现这种问题的原因是什么?不就是因为A和B他们俩接收到的信息并不能百分之百确定这个信息就是由对方发来的吗?如果说A收到的数据有B的亲笔签名,不就能说明这个信息就是B的么,所以,接下来就引出了“数字签名”这种技术,来证明这个信息就是来自真实的对方的。

 

二、数字签名

在讲解数字签名之前,先让我们了解下什么是单向散列函数。

1、单向散列函数

单向散列函数,又称单向Hash函数、杂凑函数,就是把任意长的输入消息串变化成固定长的输出串且由输出串难以得到输入串的一种函数。这个输出串称为该消息的散列值。常见的单向散列函数有这么几种:

  • MD5(Message Digest Algorithm 5):是RSA数据安全公司开发的一种单向散列算法,MD5被广泛使用,可以用来把不同长度的数据块进行暗码运算成一个128位的数值。
  • SHA(Secure Hash Algorithm)这是一种较新的散列算法,可以对任意长度的数据运算生成一个160位的数值。

看下他如何工作的,如下图: 

给定任意大小的数据,利用单项散列函数进行计算,总是会得到一个固定长度的散列值,如上图右,散列的大小和数据的大小没有一毛钱关系。可以上这个网站上进行验证:http://tool.chinaz.com/tools/md5.aspx?qq-pf-to=pcqq.c2c

值得一提的是,因为对原数据进行散列计算后,无法将计算的结果利用反推的方式还原为原数据,所以将其称为单项散列函数。标准的MD5已经被证实已经不安全了,所以一般在使用的时候都给它加了点盐。在我们的钥匙串中一般使用SHA-256,如下图。如果有不理解的,可以看我写的这篇文章:IOS开发之对MD5算法的理解。 

                                        

 

有了他我们就能保证我们的数据是有效的,就没有被人串改的吗?要想搞清楚能不能,还得继续看下图,看看他是如何确定数据有效性的。 

 

首先,A有一条消息要发往B,在发送之前,A利用单向散列函数对消息进行了一次计算,得到了一串散列值,专业点,请叫他信息摘要。

然后,A将原数据和信息摘要一起发往了B,此时,B同时拥有了A的消息摘要以及原数据,那么B会对消息再进行一次散列计算得到一个信息摘要,对比A传过来的消息摘要和B生成的消息摘要,如果一致,那么消息就没有被篡改,如果不一致,那么肯定是被改过了。

2、数字签名

搞懂了单向散列函数,下面我们看看什么是数字签名

先看看百度百科是怎么定义的:

数字签名(又称公钥数字签名)是只有信息的发送者才能产生的别人无法伪造的一段数字串,这段数字串同时也是对信息的发送者发送信息真实性的一个有效证明。它是一种类似写在纸上的普通的物理签名,但是使用了公钥加密领域的技术来实现的,用于鉴别数字信息的方法。一套数字签名通常定义两种互补的运算,一个用于签名,另一个用于验证。数字签名是非对称密钥加密技术数字摘要技术的应用。

对数字签名不了解的,可以继续看这篇文章https://www.jianshu.com/p/64803f36d1f3我们继续看下图: 

                           

  1. 首先利用MD5算法,算出原始数据的摘要。需满足 a.若原始数据有任何变化,计算出来的摘要值都会变化。 b.摘要要够短。这里最常用的算法是 MD5。
  2. 生成一份非对称加密的公钥和私钥,私钥我自己拿着,公钥公布出去。
  3. 对一份数据,算出摘要后,用私钥对这个摘要进行加密,我们将其称之为原始数据的签名,然后把它跟原始数据一起发送给用户。 
  4. 用户收到数据和签名后,用公钥解密得到摘要。同时用户用同样的算法计算原始数据的摘要,对比这里计算出来的摘要和用公钥解密签名得到的摘要是否相等,若相等则表示这份数据中途没有被篡改过,因为如果篡改过,摘要会变化。

                              

原理就是这样,但我知道你看完以后还是会有很多疑问,这怎么能安全?如果消息被中间人替换了,摘要也被中间人替换了,那B得到的还是一致的啊!因为我知道你们还是有很多疑问,所以我也没打算就写到这里停笔,接下来听我继续说。

先对数字签名做一个总结:

  • 数字签名的作用不是为了保证机密性,仅仅是为了能够识别内容有没有被篡改
  • 数字签名的作用
  • 防止消息发送人否认
  • 识别消息是否被篡改
  • 确认消息的完整性

很明显,光有数字签名,当我们面对的中间人攻击依然无法被避免。即使有签名,那么收到的签名仍然可能是中间人发来的,为了解决这个问题,那么“数字证书”这个玩意就应然而生。其实我们停下来仔细想想,在A和B通信的过程中,A被中间人攻击/欺骗的主要原因是什么?是不是因为A本来想获得B发来的公钥,但实际收到的确实中间人C的公钥,如果A能够确切的获得B的公钥,再配合数字签名,那么C只要是篡改了我们的数据,那么数字签名立马就会变得不一致(因为数字签名是B用私钥签的,而私钥只有B自己知道,C签出来的肯定会不一样)。下面我们看看“数字证书”是个什么玩意。

三、数字证书

先看看定义:

数字证书从本质上来说是一种电子文档,是由电子商务认证中心(以下简称为CA中心)所颁发的一种较为权威与公正的证书,对电子商务活动有重要影响,例如我们在各种电子商务平台进行购物消费时,必须要在电脑上安装数字证书来确保资金的安全性。

CA中心采用的是以数字加密技术为核心的数字证书认证技术,通过数字证书,CA中心可以对互联网上所传输的各种信息进行加密、解密、数字签名签名认证等各种处理,同时也能保障在数字传输的过程中不被不法分子所侵入,或者即使受到侵入也无法查看其中的内容。

你们看懂了吗?反正我没看懂,真抽象,其实数字证书就是证书,只不过是电子版的证书,可以这么理解,我们都有大学毕业证、驾驶证、以及四六级证,这些证书就是由对应的权威机构颁发给我们的。而数字证书也是由这样的权威机构颁发给我们的,正如定义中说的CA—商务认证中心。在这些证书中,就有我们的公钥,姓名、邮箱以及认证机构(Certificate Authority,CA)施加数字签名等信息。这个公钥是我们传给CA机构的,所以,在互联网上,只要是靠谱的CA机构,那这个公钥大家就是认的,没毛病。

有了数字证书这个东西,就能保证A能获取到B的公钥,而且能够确定一定是B的公钥。那么数据传输就成了如下流程图:

                               

 

B通过注册,将自己的公钥上传到认证机构CA,发送方A通过认证机构来获取到接收方B的公钥,这里在A出有认证机构CA的公钥(内置了),然后利用公钥对数据进行加密再发送,就能保证数据的安全性,即使中间人获取到了这个加密的密文,他也解不了,私钥在接收方B,只有B能解,一切完美。

说了这么多,终于把前期的知识补齐了,但苹果的签名机制可比这个复杂多了。不过掌握了原理,其他都是换汤不换药的,接下来我们是时候来看看苹果的签名机制是怎么搞的了。

四、IOS签名机制

IOS开发为什么会有签名机制?好像我么平时做其他APP开发的时候,开发一个软件出来,并不需要什么签名,直接就可以运行,苹果为啥要搞一大堆证书出来呢,而且各种奇怪的符号名字,比如:Provisioning Profile、entitlements、CertificateSigningRequest等等,这都是做什么的了?下面先解释下苹果为什么要搞这么多证书出来。

在 iOS 出来之前,在主流操作系统(Mac/Windows/Linux)上开发和运行软件是不需要签名的,软件随便从哪里下载都能运行。这就导致平台对第三方软件难以控制,盗版流行。苹果希望解决这样的问题,在 iOS 平台对第三方 APP 有绝对的控制权,一定要保证每一个安装到 iOS 上的 APP 都是经过苹果官方允许的,怎样保证呢?就是通过签名机制。

好家伙,要控制每一个第三方开发的APP必须是苹果允许的,你们懂得。这其实就无意中给我们加了很多门槛,要知道注册成为一个IOS开发者价格可是不菲的,看下价格表,注意是美金: 

这些门槛就使得为什么IOS开发者和Android对比那么少的原因了。别的不是这篇文章的内容,就不说了。为了让大家能看得懂,我这里先从最简单的签名说起:

1、IOS简单签名

在搞懂IOS签名之前,我们得先搞懂什么是签名对吧,如果不懂的话,可以翻看我写的这篇文章:彻底搞懂IOS签名机制(上篇)。其实我们可以想一下,苹果既然只想让IOS系统安装自己允许的三方APP,那他只需要对这个APP进行签名,然后让IOS系统去验证这个签名不就可以了吗?我们看下面这个图:

                               

苹果公司利用RSA算法生成了非对称的公钥和私钥,私钥是在自己的Apple后台,公钥会内置到出厂的每一台IOS设备上。

我们传 App 上 AppStore 时,苹果后台用私钥对 APP 数据进行签名,iOS 系统下载这个 APP 后,用公钥验证这个签名,若签名正确,这个 APP 肯定是由苹果后台认证的,并且没有被修改过,也就达到了苹果的需求:保证安装的每一个 APP 都是经过苹果官方允许的。

如果我们 iOS 设备安装 APP 只有从 AppStore 下载这一种方式的话,那这件事就结束了,没有任何复杂的东西,只有一个数字签名,非常简单地解决问题。但更多时候,作为开发者,我们不可能把每一个编译后的app上传到APPStore来进行签名,这是不现实的。但是,苹果还是想控制我们,那么这个时候,签名就变复杂了。

2、IOS签名机制优化1

苹果这里给出的方案是使用了双层签名,如下图:

                                     

那么这个时候,整个签名的流程就变成了这样:

  1. 在你的 Mac 开发机器生成一对公私钥,这里称为公钥L,私钥L。L:Local
  2. 苹果自己有固定的一对公私钥,私钥在苹果后台,公钥在每个 iOS 设备上。这里称为公钥A,私钥A。A:Apple
  3. 开发者把公钥 L 传到苹果后台,用苹果后台里的私钥 A 去签名公钥 L,得到一份数据包含了公钥 L 以及其签名,权限,等等信息,把这份数据称为证书。
  4. 在开发时,编译完一个 APP 后,用本地的私钥 L 对这个 APP 进行签名,同时把第三步得到的证书一起打包进 ipa包里,安装到手机上。
  5. 在安装时,iOS 系统取得证书,通过系统内置的公钥 A,去验证证书的数字签名是否正确。
  6. 验证证书后确保了公钥 L 是苹果认证过的,再用公钥 L 去验证 APP 的签名,这里就间接验证了这个 APP 安装行为是否经过苹果官方允许。(这里只验证安装行为,不验证APP 是否被改动,因为开发阶段 APP 内容总是不断变化的,苹果不需要管。)

3、IOS签名机制优化2

上述流程只解决了上面第一个需求,也就是需要经过苹果允许才可以安装,还未解决第二个避免被滥用的问题。怎么解决呢?

苹果再加了两个限制,一是限制只有在苹果后台注册过的设备才可以安装,二是限制签名只能针对某一个具体的 APP。(可还记得bundleId)

在上述第三步,苹果用私钥 A 签名我们本地公钥 L 时,实际上除了签名公钥 L,还可以加上无限多数据,这些数据都可以保证是经过苹果官方认证的,不会有被篡改的可能。如下图:

                                         

可以想到, 允许安装的设备 ID 列表 和 App对应的 AppID 等数据,都在第三步这里跟公钥L一起组成证书,再用苹果私钥 A 对这个证书签名。在最后第 5 步验证时就可以拿到设备 ID 列表,判断当前设备是否符合要求。根据数字签名的原理,只要数字签名通过验证,第 5 步这里的设备 IDs / AppID / 公钥 L 就都是经过苹果认证的,无法被修改,苹果就可以限制可安装的设备和 APP,避免滥用。

4、IOS签名机制最终流程

到这里这个证书已经变得很复杂了,有很多额外信息,实际上除了 设备 ID / AppID,还有其他信息也需要在这里用苹果签名,像这个 APP 里 iCloud / push / 后台运行 等权限苹果都想控制,苹果把这些权限开关统一称为 Entitlements,它也需要通过签名去授权。

实际上一个“证书”本来就有规定的格式规范,上面我们把各种额外信息塞入证书里是不合适的,于是苹果另外搞了个东西,叫 Provisioning Profile,一个 Provisioning Profile 里就包含了证书以及上述提到的所有额外信息,以及所有信息的签名。

所以整个流程稍微变一下,就变成这样了:

以上便是IOS签名机制的核心原理,可以看到,这个时候Apple就是扮演者一个CA的角色,用来给我们颁发了这么一个embedded.mobileprovision 文件,但在我们平时申请证书的时候,会遇到很多复杂的符号概念,具体的操作和概念是这样的:

  1. 第 1 步对应的是 keychain 里的 “从证书颁发机构请求证书”,这里就本地生成了一对公私钥,保存的 CertificateSigningRequest 就是公钥,私钥保存在本地电脑里。
  2. 第 2 步苹果处理,不用管。
  3. 第 3 步对应把 CertificateSigningRequest 传到苹果后台生成证书,并下载到本地。这时本地有两个证书,一个是第 1 步生成的,一个是这里下载回来的,keychain 会把这两个证书关联起来,因为他们公私钥是对应的,在XCode选择下载回来的证书时,实际上会找到 keychain 里对应的私钥去签名。这里私钥只有生成它的这台 Mac 有,如果别的 Mac 也要编译签名这个 App 怎么办?答案是把私钥导出给其他 Mac 用,在 keychain 里导出私钥,就会存成 .p12 文件,其他 Mac 打开后就导入了这个私钥。
  4. 第 4 步都是在苹果网站上操作,配置 AppID / 权限 / 设备等,最后下载 Provisioning Profile 文件。
  5. 第 5 步 XCode 会通过第 3 步下载回来的证书(存着公钥),在本地找到对应的私钥(第一步生成的),用本地私钥去签名 App,并把 Provisioning Profile 文件命名为 embedded.mobileprovision 一起打包进去。这里对 App 的签名数据保存分两部分,Mach-O 可执行文件会把签名直接写入这个文件里,其他资源文件则会保存在 _CodeSignature 目录下。
  6. 第 6 – 7 步的打包和验证都是 Xcode 和 iOS 系统自动做的事。

这里再总结一下这些概念:

  1. 证书:内容是公钥或私钥,由其他机构对其签名组成的数据包。
  2. Entitlements:包含了 App 权限开关列表。
  3. CertificateSigningRequest:本地公钥。
  4. p12:本地私钥,可以导入到其他电脑。
  5. Provisioning Profile:包含了 证书 / Entitlements 等数据,并由苹果后台私钥签名的数据包。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值