春天前销销售 - 保存一切。所有视频。所有书籍。 现在50%的折扣。

建立您的移动发展技能并保存!通过终极书籍和视频订阅,继续前进。作为春季前销销售的一部分,仅为149美元/年。

首页 iOS.& Swift Tutorials

引入Cryptokit.

加密是保护用户数据的关键。本教程向您展示如何使用Apple的新Cryptokit API来验证或加密您的应用数据。

4.9/5 12个评分

版本

  • Swift 5,iOS 13,Xcode 11

苹果的新Cayptokit API为您提供了对应用程序进行身份验证和加密数据的能力,如果您的应用程序需要超过Apple的默认硬件和软件保护。

在本文中,您将使用对称密钥和公钥加密进行身份验证和加密数据。您将学习何时以及如何使用:

  • 加密散列
  • 基于哈希的消息身份验证码(HMAC.)
  • 使用关联数据进行身份验证加密(Aead.)Ciphers.
  • 具有椭圆曲线的公钥加密(ECC.)
  • 数字签名
  • 重点协议

继续阅读以解锁所有的秘密!

SPOILER ALERT.:本教程假设您熟悉J.K.的哈利波特系列。罗琳或对阅读它没有兴趣。它讨论了最后几本书中透露的秘密。

入门

通过下载本文的材料开始 - 您可以在本文的顶部或底部找到链接。打开,建立和运行 秘书长 项目在 起动机 folder.

管家应用程序

管家应用程序

这个应用程序是一个列表 Voldemort的orcrxes。只要他灵魂的一部分在其中一个项目中是安全的,伏地魔就不能被杀死。因此,他必须将他们的身份和地点的秘诀在于,特别是Albus Dumbedore和哈利波特。

保护用户数据

像Voldemort的秘密一样,您的用户数据需要保护意外或恶意损坏以及未经授权的使用。 iOS已在Foundation / NSData,Security / Keychain和CloudKit中拥有大量内置或易于使用的安全性。如果您的应用程序访问HTTPS服务器,则免费获得TLS加密和数字签名。现在有Cryptokit,如果您的应用程序需要验证数据或身份验证发件人。

您需要在这三个州中的每一个中保护数据:

  • 运动中的数据:在运输中,通常在网络上
  • 使用数据: 在记忆中
  • >休息的数据:存储在磁盘上,不使用

运动中的数据 是加密的原因原因,返回之前 凯撒密码 向Caesar的将军发送书面订单。如今,如果应用程序使用TLS 1.3与服务器通信,则通过传输层安全(TLS)处理加密。但您仍然需要使用加密散列和键控签名来验证数据和发件人。本教程中的大多数是关于这些主题。

使用数据 必须受用户身份验证的保护。要在执行操作时限制,请使用 本地身份验证 检查用户身份验证的何时以及如何进行身份验证。例如,您可以要求用户使用Biometrics - 面部ID或触摸ID进行身份验证 - 以确保用户存在。

数据休息 通过数据保护API在设备上受到保护。用户一旦为设备设置密码,就会获得自动软件数据保护。每个新文件都会获得一个新的256位加密密钥,特定于文件的保护类型。有三种文件保护类型:

  • 保护直到第一次用户身份验证:默认文件保护类型。设备启动时无法访问该文件,但是在设备重新启动之前,可以访问,即使在设备被锁定时,也可以访问。
  • 完全的:仅在设备解锁时才可访问该文件。
  • 除非开放,否则完整:如果在设备锁定时文件打开,则仍然可以访问。如果设备锁定文件未打开,则在设备解锁之前,它无法访问。

您可能希望在锁定设备以启用网络传输以继续时访问文件。

您的应用程序还可以在私有CloudKit数据库中存储加密数据,在所有用户的设备上可用。

增加对伏地魔的秘密的保护

监控器从文件中读取以创建占星圈列表。该应用程序写入此文件,没有文件保护选项:

try data.write(to: secretsURL)

这意味着秘密文件只有默认的文件保护,因此当应用程序在后台且即使设备被锁定时,它可以访问它。

Voldemort的秘密需要更高级别的文件保护。在 ContentView.swift., in writeFile(items:), replace the data.write(to:) statement with this line:

try data.write(to: secretsURL, options: .completeFileProtection)

借助此保护级别,只有在设备解锁时才可访问该文件。

钥匙串和安全的飞地

您的应用应该在本地或iCloud中存储加密密钥,身份验证令牌和密码 钥匙链。 Apple的示例应用程序 在钥匙串中存储Cryptokit键 shows how to convert CryptoKit key types P256, P384 and P521 to SecKey and other key types to generic passwords.

自2013年底以来发布的iOS设备 - iPhone 5s,iPad Air和更晚的型号 - 有 保护飞地 芯片。 Secure Candave是一个专用加密引擎,与处理器分开,设备的唯一标识符(UID)256位加密密钥在工厂融合。 Secure Candave还存储触点和面部的生物识别数据。

安全飞地中的键和数据永远不会离开它。它们永远不会被加载到内存中或写入磁盘,因此它们被完全受到保护。您的应用通过邮箱与安全的固定通信,您将要加密或解密的数据存放,然后检索结果。

Cryptokit使您的应用程序能够直接在安全的飞机中为公钥加密创建密钥。本教程末尾附近有示例代码。

使用cryptokit.

所有内置的数据保护可能与您的应用需求一样多。或者,如果您的应用程序与第三方加密的数据或验证文件转账或金融交易,则可能需要使用Cryptokit。

滚动自己的加密:别

数据安全是加密人员和攻击者之间的战场。除非您是一个密码手,否则写自己的加密算法是您的用户数据的巨大风险。不同平台有许多加密框架。现在,您拥有Apple的Cryptokit,使您的应用程序中的超级易于使用加密。

表现:别担心

表现怎么样? cryptokit建于顶部 Corecrypto.,Apple的本机加密库。 CorecryPto的手动调整汇编代码使硬件的高效使用。

加密散列

现在是为了最基本的加密形式。您可能熟悉哈希字典项目或数据库记录的想法,以便更有效地检索。许多标准类型 conform to the Hashable protocol. Hashing objects of these types into a Hasher produces integer hash values with a reasonable probability of uniqueness. A small change to the input produces a large change in the hash value.

Hasher 使用随机生成的种子值,因此每次应用程序运行时都会产生不同的哈希值。亲自看到这个。

打开 Cryptokittutorial.playground. 在初学文件夹中。第一部分, 占领议定书, has this hashItem(item:) function:

func hashItem(item: String) -> Int {
  var hasher = Hasher()
  item.hash(into: &hasher)
  return hasher.finalize()
}

通过添加以下方式尝试:

let hashValue = hashItem(item: "the quick brown fox")

运行游乐场。散列值出现在结果侧栏中,或单击 显示结果 按钮在游乐场查看它:

哈赫哈希值

哈赫哈希值

你的价值与我的价值不同。再次运行游乐场,您将获得不同的价值。

Unlike Hasher, 加密散列 produces the same hash value every time. Like the Hasher algorithm, 加密散列 algorithms produce almost-unique hash values, and a small change to the input produces a large change in the hash value. The difference is one of degree and the amount of computation required to produce a hash value — called a 消化 或者 校验和 - 可以可靠地验证数据的完整性。

加密散列算法为输入数据创建一个小,固定的长度,几乎唯一的数据值(摘要)。最常见的摘要尺寸为256和512位。 512位摘要可以截断为384位。发现两个产生相同摘要的输入非常不太可能,但并非不可能,因为只有2256 或者 2512 256位或512位摘要的可能值。

散列算法是 单程 并包括非线性操作,因此攻击者无法反转操作以从摘要中计算原始数据。输出的每个位都取决于输入的每位点,因此攻击者无法尝试从摘要一部分计算输入的一部分。更改输入中的单个位也会产生完全不同的摘要,因此攻击者无法在输入和输出之间找到关系。

加密摘要几乎是独一无二的,很难反转。

加密摘要几乎是独一无二的,很难反转。

这些特性允许您了解两个数据集是否通过计算摘要不同。例如,Git计算摘要以识别每个提交。您可以使用摘要传输或存储数据以检测数据损坏等后续更改。软件下载通常提供摘要,称为a 校验和。下载器使用相同的散列算法来计算下载数据的摘要。如果此摘要不匹配文件的校验和,则该文件已损坏或不完整。

接收器计算摘要以检查数据是完整的,而不是损坏。

接收器计算摘要以检查数据是完整的,而不是损坏。

cryptokit提供了 安全哈希算法2(SHA-2) algorithms SHA-256, SHA-384 and SHA-512. The numbers indicate the digest size. Its Insecure container provides SHA-1 (160位)和 MD5 (128位),用于与旧服务的向后兼容。 SHA-2发表于美国国家标准与技术研究所(NIST),并在某些美国政府申请中使用法律要求。

在游乐场,向下滚动到此声明:

UIImage(data: data)

在结果侧边栏中,点击 显示结果 旁边 W 714 H 900 要查看数据是一岁的哈利波特的图像:

数据是宝宝哈利波特图像。

数据是宝宝哈利波特图像。

当Voldemort未能杀死哈利时,他不小心把他转变为魂器。但Voldemort不知道这一点。 Albus Dumbledore知道,他想用哈利分享这个秘密。

首先,作为邓布利者,创建了这个数据的摘要。添加此行:

let digest = SHA256.hash(data: data)

That’s all you have to do! SHA256 produces a 256-bit digest. It’s just as easy to use one of the other two hashing algorithms — SHA384 或者 SHA512. And if Apple updates these to use SHA-3 而不是SHA-2,你不必更改你的代码。

然后Dumbledore通过网络连接发送数据并摘要到Harry。所以现在,正如Harry,添加此代码以检查摘要匹配:

let receivedDataDigest = SHA256.hash(data: data)
if digest == receivedDataDigest { 
  print("Data received == data sent.") 
}

您在数据上使用相同的散列算法,然后检查两个摘要值相等。

运行游乐场。 The message prints. Not surprising, as data had no opportunity to become corrupted.

现在点击这一点 显示结果 button next to receivedDataDigest to get a good look at the digest:

cryptokit sha256数据摘要

cryptokit sha256数据摘要

这是一个元组。不是很可读。

Type this line to show its description instead:

String(describing: digest)
笔记: Apple’s documentation discourages calling .description directly.

运行游乐场。点击 显示结果:

CryPTOKIT DIGEST的字符串描述

CryPTOKIT DIGEST的字符串描述

The digest description contains a String. This is more human-readable and looks like a Git hash value, but twice as long. It’s also much much much longer than the Hasher hash value.

最后,要查看数据的小变化如何产生完全不同的摘要,使其对两个相同的代码中的一个非常小的变化。例如:

String(describing: SHA256.hash(data: "Harry is a horcrux".data(using: .utf8)!))
String(describing: SHA256.hash(data: "Harry's a horcrux".data(using: .utf8)!))

运行游乐场。点击 显示结果 for both lines:

近似相同数据的Cryptokit摘要非常不同。

近似相同数据的Cryptokit摘要非常不同。

注意你得到了 确切地 我所做的相同哈希值。

签名摘要

散列数据无法保护您免受恶意更改,因为恶意攻击者只会为其更改的数据发送正确的摘要。

基于哈希的消息身份验证码(HMAC.)防止恶意变化 签署 摘要用一个 对称加密键。常用用例是签署文件的摘要,因此应用程序的服务器可以检查您是否授权上传文件。

“对称键”是指发件人和接收者都知道密钥。 HMAC使用秘密键来派生内部和外部键。然后它创造了一个 内部哈希 从数据和内钥。最后,它创造了 签名 来自内部哈希和外键。

散列消息认证码的图

散列消息认证码的图

这就是算法所做的。但要使用Cryptokit创建一个对称密钥,但您只需键入此行:

let key256 = SymmetricKey(size: .bits256)

比Apple的旧C加密API所做的那么多,在那里您必须转换位和字节,并记得在完成后从内存中删除密钥!

The most common attack against HMAC is brute force to uncover the secret key, so the security of HMAC depends on the size of the secret key. CryptoKit allows three key sizes: .bits128, .bits192 and .bits256.

接下来,添加这两个代码语句:

let sha512MAC = HMAC<SHA512>.authenticationCode(
  for: data, using: key256)
String(describing: sha512MAC)

You’re creating the digest for data using your symmetric key, so now the digest is called an 身份验证码 或者 签名.

运行游乐场。点击 显示结果 要查看签名的描述:

Cryptokit HMAC 512位签名的描述

Cryptokit HMAC 512位签名的描述

您已为婴儿图像制作了一个512位(64字节)签名。

To send this signature over the network, convert it to Data:

let authenticationCodeData = Data(sha512MAC)

现在邓布利多向您哈利发送签名数据。你 - 哈利已经有了 相同的 secret key key256. Type this code to authenticate what you’ve received:

if HMAC<SHA512>.isValidAuthenticationCode(authenticationCodeData,
   authenticating: data, using: key256) {
    print("The message authentication code is validating the data: \(data))")
  UIImage(data: data)
}
else { print("not valid") }

如果签名有效,则您可以查看数据,知道它真的是邓布利多发送的。

运行游乐场。点击 显示结果 旁边 the print statement and next to the UIImage:

Cryptokit认证HMAC签名和数据

Cryptokit认证HMAC签名和数据

HMAC.允许您验证发件人的身份和数据的完整性,但不会加密数据。如果您忘记使用TLS,而Voldemort拦截传输,则怀疑哈利是他的魂之一。

或者伏地魔可能决定手动加密他的魂柱列表,绝对确定邓布利多,哈利找不到并摧毁它们。

数据加密是加密是关于的,所以它来了。

加密和验证数据

即使使用TLS加密网络数据,您也可能想要向用户发送加密文件。例如,如果他们制作了一个应用内购买,则会将加密文件发送给它们(单独)解密键。

本领域的当前状态是具有关联数据的经过身份验证的加密(Aead.)密码。 AEAD密码使用不同的密钥进行加密和MAC,MAC散列密文,而不是纯文本。一切都结合在一起 密封盒子.

共同使用中有两个AEAES:高级加密标准Galois /计数器模式(AES-GCM.) 和 Chacha20- Poly1305.。两者都是Apple的加密API新的。 AES-GCM是NIST的既定标准。 Daniel J.Bernstein开发了Chacha20-Poly1305,以防攻击者设法打破AES-GCM。

2019年,几乎所有TLS流量使用AES,但Chacha20-Poly1305的流行程度越来越高,因为它比Hys-GCM更快的移动设备上没有对AES-GCM的硬件支持。但随时可以在您的应用中使用AES-GCM,因为iOS设备具有AES硬件:]。

AES和Chacha20是密码算法。 GCM和Poly1305是MAC算法。伯尔尼斯坦从他早期的Salsa密码开发了Chacha20。 ;]

要创建密封盒,AEAD Cipher将采用这些输入:

  1. 明文被加密
  2. 一个秘密的钥匙
  3. 唯一的初始化值 - IV或 omce.:这可以防止重播攻击,就像某人一样(谁 真的 需要获得一生)重新发送相同的购物车订单多次。
  4. 可选:额外的非秘密数据,经过身份验证但未加密。这是 广告Aead..

然后是 海豹 operation:

  1. 使用密钥和nonce来生成辅助密钥。
  2. Uses the key and nonce to encrypt the data into encrypted data of equal length — the ciphertext.
  3. 使用辅助密钥生成任何附加数据的键控摘要,加密数据和每个的长度。
  4. 使用密钥和随机键加密键入摘要,然后将加密的键入摘要附加到加密数据。

我遗漏了 相关数据 在 this diagram:

Cryptokit密封盒密封操作图

Cryptokit密封盒密封操作图

看起来像很多工作,不是吗?好吧,这就是全部 需要键入,创建密封盒:

let sealedBoxData = try! ChaChaPoly.seal(data, using: key256).combined

You supply the data and key to get a sealed box. Its combined property is of type Data, which you can send over the network.

To use AES-GCM instead, you’d replace ChaChaPoly with AES.GCM.

现在,邓布利大线将密封的盒子数据发送到哈利。您的AS-AS-Harry键入此代码可将其转回密封盒:

let sealedBox = try! ChaChaPoly.SealedBox(combined: sealedBoxData)

You-as-Harry already have the same secret key as Dumbledore, so you can open the sealed box and decrypt its ciphertext:

let decryptedData = try! ChaChaPoly.open(sealedBox, using: key256)

运行游乐场。

Chachapoly Seal和开放操作的Cryptokit代码

Chachapoly Seal和开放操作的Cryptokit代码

Notice the size of 海豹edBoxData is 28 bytes more than the image data. Add these lines to see what else is in the sealed box:

sealedBox.nonce  // 12 bytes
sealedBox.tag  // 16 bytes
Cryptokit密封盒Once和标签的尺寸和内容

Cryptokit密封盒Once和标签的尺寸和内容

Both algorithms select a nonce for you, then pack it into the sealed box for open to use. So easy! The 16-byte tag is the encrypted keyed digest — the signature that authenticates the data. The nonce changes each time you create the sealed box, and this changes the encrypted keyed digest too. So your actual omce. and tag values don’t match my screenshot.

最后,只要证明无法查看加密数据,添加这些行:

let encryptedData = sealedBox.ciphertext
UIImage(data: encryptedData)
UIImage(data: decryptedData)

运行游乐场。 显示结果 for both lines:

加密数据不能被视为UIImage。

加密数据不能被视为UIImage。

发送加密数据是多么容易,但发件人和接收器都需要知道密钥。如果这不可能怎么办?

公钥密码学

笔记:这是Cryptokit的一部分,但这是一个非常大的话题,所以获得自己的部分。

HMAC.和密封盒加密使用对称键,发件人和接收器都知道密钥。必须传输对称密钥“频段”。如果您无法安全地执行此操作,则使用公钥加密。事实上,互联网上的大多数例程加密都使用公钥加密,包括Xcode签署您的应用时。

公共密钥加密创建两个数学上链接的键。您可以保留私钥秘密并发布相应的公钥数据。您使用私钥签署数据或其摘要,然后发送。接收器从公钥数据创建公钥,然后使用它来检查签名的数据或摘要。

For example, your app might need to authenticate an operation with your back-end server. On the user’s device, it creates a private key, which it stores in 钥匙链 或者 SecureEnclave, then registers the corresponding public key on the server. When your user sets up the operation, your app signs the operation’s details with the user’s private key and sends the signed details to the server, which verifies it with the user’s public key.

要发送加密数据,您和收件人每个都会创建一对密钥并发布公钥。然后,你们两个都将私钥与另一个公钥合并以创建一个 共享秘密。你们两个都使用这个共享的秘密来得出 相同的对称密钥,您可以在上一节中描述的,您可以使用它用于AEAD。

创建私人和公钥

公钥密码学的关键特征是它使用 trapdoor算法:从公钥计算私钥非常困难。

1978年出版后, RSA. (RIVEST-Shamir-Adleman)成为最受欢迎的公钥算法。它依赖于确定非常非常非常大的两个素数因子的难度。其他数学家升级为挑战,开发只能通过增加钥匙的大小在海湾保持的分解算法。生成RSA键缓慢,随着键尺寸的时间增加。最终,对算法的因子算法比移动设备的功率更快地提高,以使用非常大的数字计算。注意力转向另一种技术,这令人证明是更难攻击。

ECC. (椭圆曲线加密)首次建议于1985年,自2004年以来已被广泛使用,并成为2015年底的服务器的首选技术。ECC键远小于具有相似安全性的RSA键:例如,256的安全性-bit ECC公钥可与3072位RSA公钥相媲美。

Cryptokit专门使用ECC算法。你的选择是nist的 P256 / P384 / P521 或丹尼尔J.Bernstein的 曲线25519.. P256 is by far the most widely used curve. It’s the default curve for OpenSSL, where it’s known as prime256v1. P384 requires 2-3 times as much computation as P256. The U.S. National Security Agency (NSA) requires P384 to protect top-secret information. P256 and P384 are in the NSA’s 套房B密码学但是p521不是,我找不到有关谁使用它的信息。超级幽灵,也许?

笔记:2018年,NSA更换了套房B 商业国家安全算法套件 (CNSA.)作为其过渡到的一步 量子抗性密码学, 因为 量子计算 可以轻松打破ECC算法。

伯尔尼斯坦发布了曲线25519与NSA的套房B同一年,但其普及后其受欢迎程度增加了 爱德华斯诺登 released internal memos in 2013 suggesting the NSA had inserted a cryptographic back door into the elliptic curve-based pseudo random generator Dual_EC_DRBG. Both Dual_EC_DRBG and P256 rely on 没有我的袖子 (nums)魔术号码。该加密社区怀疑NSA使用的特殊值来派生这些魔术号,使它们能够解密用P256加密的任何内容。曲线25519不依赖魔术数字。其计算复杂性低于P256的40%。和2018年的TLS 1.3标准需要支持它。

ECC.:它是如何工作的?

许多文章,喜欢 这个,使用小素数算术以易于理解的方式解释RSA。算法非常聪明。

椭圆曲线加密甚至更好!但是解释一点复杂。

An elliptic curve consists of the (x,y) points satisfying an equation of this form:

y^2 = x^3 + ax + b

For example, y^2 = x^3 - x + 1 looks like this:

椭圆曲线图

椭圆曲线图

您可以在图表中进行更详细的椭圆曲线 Desmos绘制计算器.

ECC.使用椭圆曲线的两个属性:

  1. 任何非垂直线在不超过三点之间与图相交。
  2. The graph is symmetric around the x-axis.

这些属性让您定义一个 点操作 图中的任何两点之间:

  1. 在点A和B之间画一条线。
  2. Where this line hits the graph at a third point, reflect across the x-axis to get point c =点b.
椭圆曲线A点B操作

椭圆曲线A点B操作

您也可以定义 点乘法 operation k * A, where k is a positive integer.

  1. 从点A开始以获得点B:将切线线绘制到点A的曲线上,并反射跨越该行命中图形的X轴。这是第一个圆点操作。
  2. Now do A dot B to get point C, then A dot C = D, and so on. Do a total of k dot operations, ending at point P. If you tell someone where points A and P are, it’s 真的 hard for them to calculate k.

The actual algorithm uses only integer values of x and y, modulo a prime number n. The start point is called the 发电机, so it’s usually named G. It has the property that n * G = G.

To set up an ECC cryptosystem, you pick a curve equation (the coefficient of x and the constant b), a generator point G on this curve and its corresponding prime number n. The private key is a randomly selected number k, and the public key is k * G — the endpoint on the curve after k dot operations on G.

当然, 不需要这样做。已经存在曲线25519等标准曲线,并由NIST ECC使用的曲线,这些曲线在Cryptokit的公钥方法中实现。

数字签名

数字签名就像hMAC,但具有公钥密码学。发送者使用私钥来签名而不是使用相同的秘密密钥来验证和验证,而不是使用相同的秘密密钥,而是使用私钥签名,而接收器使用发件人的公钥来验证。

公钥加密:使用私钥标志,使用公钥进行验证。

公钥加密:使用私钥标志,使用公钥进行验证。

数字签名的首字母缩略词是椭圆曲线数字签名算法(ecdsa.),使用NIST的P256 / P384 / P512曲线和Edwards-Curve数字签名算法(eddsa.),使用Bernstein的ED25519曲线。

假设你是邓布利多想向Harry发送Horcux映像。你会签署它,所以Harry可以验证你的愚蠢。首先,您为数字签名创建私有和公钥:

let albusSigningPrivateKey = Curve25519.Signing.PrivateKey()
let albusSigningPublicKeyData = 
  albusSigningPrivateKey.publicKey.rawRepresentation

The rawRepresentation of the public key is of type Data, so you can send it over the network.

接下来,您可以使用私钥签署数据:

let signatureForData = try! albusSigningPrivateKey.signature(for: data)

或者你签名 消化 数据,哪个更快:

let digest512 = SHA512.hash(data: data)
let signatureForDigest = try! albusSigningPrivateKey.signature(
  for: Data(digest512))

你是愚蠢的使用这次SHA-512。

When using a Curve25519 private key, 签名(for:) generates an elliptic curve digital signature algorithm (EdDSA) signature of the data or digest over the Ed25519 elliptic curve, using SHA-512. 作为哈希函数。该算法在每个呼叫上生成随机的签名,即使对于相同的数据和键,也可以防止定时攻击。

如果使用P256而不是曲线25519,它使用P-256椭圆曲线的数据产生椭圆曲线数字签名算法(ECDSA)签名,使用 SHA-256. 作为哈希函数。

Now you-as-Dumbledore send data, 消化512 and 签名ForData 或者 签名ForDigest to Harry.

Switching to you-as-Harry, you add this code to verify the signatures with a key created from albusSigningPublicKeyData.

let publicKey = try! Curve25519.Signing.PublicKey(
  rawRepresentation: albusSigningPublicKeyData)
if publicKey.isValidSignature(signatureForData, for: data) {
  print("Dumbledore sent this data.")
}
if publicKey.isValidSignature(signatureForDigest,
  for: Data(digest512)) {
  print("Data received == data sent.")
  UIImage(data: data)
}
笔记: P256 and its NIST siblings have a method to sign a digest without converting it to Data.

运行游乐场以查看经过身份验证的数据:

Cryptokit代码使用公钥验证私钥签名

Cryptokit代码使用公钥验证私钥签名

这就是做数字签名是多么容易。但是,数据不加密。所以继续阅读!

为加密创建对称密钥

在本辅导中早期,邓布利多和哈利都有一个秘密钥匙,他们都知道,这让他们使用Aead密封盒来加密和解密数据。但Voldemort以某种方式发现了这个秘密密钥,并且无法安全地设置一个新的对称键 - 哈利在奔跑和邓布利多的唯一精神 - 所以现在他们需要找到另一种方式。

关键协议算法使它们能够创建一个 共享秘密 从他们的公共和私人钥匙,然后加一定的 生成一个值 对称键.

公私密钥协议算法图

公私密钥协议算法图

Computing the shared secret is amazingly simple. If G is the elliptic curve’s generator point, and a is Dumbledore’s secret key, then a * G is his public key. Similarly, Harry’s secret key is h and his public key is h * G. It turns out this is true:

(a * G) * h = (h * G) * a

这是对的,Harry乘以邓布利多的私钥,这是邓布利多通过他自己的私钥乘以哈利的公钥来获得的观点。魔法!

在这里,首字母缩写是椭圆曲线Diffie Hellman(ECDH)密钥协议,使用NIST的P256 / P384 / P512曲线或伯尔斯坦X25519曲线。

First, Dumbledore and Harry create private and public keys for key agreement, and publish their public keys as Data.

let albusPrivateKey = Curve25519.KeyAgreement.PrivateKey()
let albusPublicKeyData = albusPrivateKey.publicKey.rawRepresentation
let harryPrivateKey = Curve25519.KeyAgreement.PrivateKey()
let harryPublicKeyData = harryPrivateKey.publicKey.rawRepresentation

邓布利多和哈利必须同意 盐值 用于创建对称密钥:

let protocolSalt = "Voldemort's Horcruxes".data(using: .utf8)!

在网络上发送此安全感是安全的。除非他们也知道其中一个私钥,否则它不会有助于攻击者。

Dumbledore creates Harry’s public key from its raw representation, then combines it with his private key to calculate first the sharedSecret and then the symmetricKey:

let harryPublicKey = try! Curve25519.KeyAgreement.PublicKey(
  rawRepresentation: harryPublicKeyData)
let ADsharedSecret = try! albusPrivateKey.sharedSecretFromKeyAgreement(
  with: harryPublicKey)
let ADsymmetricKey = ADsharedSecret.hkdfDerivedSymmetricKey(
  using: SHA256.self, salt: protocolSalt,
  sharedInfo: Data(), outputByteCount: 32)

Harry creates Dumbledore’s public key from its raw representation, then combines it with his private key to calculate first the sharedSecret and then the symmetricKey:

let albusPublicKey = try! Curve25519.KeyAgreement.PublicKey(
rawRepresentation: albusPublicKeyData)
let HPsharedSecret = try! harryPrivateKey.sharedSecretFromKeyAgreement(
  with: albusPublicKey)
let HPsymmetricKey = HPsharedSecret.hkdfDerivedSymmetricKey(
  using: SHA256.self, salt: protocolSalt,
  sharedInfo: Data(), outputByteCount: 32)

现在看他们是否匹配:

if ADsymmetricKey == HPsymmetricKey {
  print("Dumbledore and Harry have 相同的对称密钥.")
}

运行游乐场。

cryptokit派生对称键匹配。

cryptokit派生对称键匹配。

仿佛魔术,邓布利多和哈利产生相同的对称密钥!现在,他们可以使用这种对称密钥来anead经验验证的加密。

P256在安全的飞地中的键

笔记: SecureEnclave code only works on a device with a Secure Enclave chip: iPhone 5S, iPad Air and later models.

有关额外保护,您可以创建 P256 私钥直接在设备安全的飞机中。这是代码的一个非常小的变化:

// Check that the device has a Secure Enclave
if SecureEnclave.isAvailable {
  // Generate private key in Secure Enclave
  let privateKey = try SecureEnclave.P256.Signing.PrivateKey() 
} else {
  let privateKey = P256.Signing.PrivateKey()
}

使用安全的外壳中的私钥,创建公钥数据和签名数据或摘要工作完全相同:

// Create public key data
let publicKeyData = privateKey.publicKey.compactRepresentation!
// Produce a signature
let dataSignature = try privateKey.signature(for: data)
let digestSignature = try privateKey.signature(for: digest)
笔记:您只能在安全的飞机中创建P256键。这个 可能 是因为芯片包含P256使用的AES引擎,而不是因为美国政府要求Apple提供后门。

安全的飞地有这个很酷的功能:你可以 约束密钥使用率 使用访问控制。例如:

let accessControl = SecAccessControlCreateWithFlags(
  nil,
  kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
  [.privateKeyUsage, .userPresence], 
  nil)!
let privateKey = try SecureEnclave.P256.Signing.PrivateKey(
  accessControl: accessControl)

您正在设置访问控制,因此当设备是时,您只能访问安全的固定中的键 解锁 并且可用 仅在此设备上。此外,您的应用程序需要 用户存在 当它与私钥执行操作时。需要用户存在意味着用户必须使用触点或面部地或设备密码进行身份验证。

符合加密出口法规

最后一件事。加密是许多国家的敏感政治问题。 这张地图 显示哪些国家有许可或登记要求,进出口控制,提供商的义务,以协助当局和其他限制。

美国是出口管制的国家之一。这是法律的东西,所以我将直接从Apple的文章引用 符合加密出口法规:

将应用程序提交到TestFlight或App Store时,将您的应用程序上传到美国的服务器。如果您在美国或加拿大境外分发您的应用程序,您的应用程序将受美国出口法律的约束,无论您的法律实体所依据。如果您的应用程序使用,访问,包含,实现或包含加密,则会被视为加密软件的导出,这意味着您的应用程序受美国的导出合规性要求,以及您分发您的国家的进口合规性要求应用程序。

来自Apple的App Store Connect帮助 出口合规概述:

使用加密包括,但不限于:

  • 通过安全频道拨打电话(即https,ssl等)。
  • 使用标准加密算法。
  • 使用来自其他来源的Crypto功能,例如iOS或MacOS。
  • 使用专有或非标准加密算法。美国政府定义“非标准加密”,作为涉及纳入或使用专有或未发表的加密功能的“加密”,包括尚未通过或批准的加密算法或由正式认可的国际标准机构(例如,IEEE,IETF,ISO,ITU,ETSI,3GPP,TIA和GSMA)并没有出版。

App Store Connect提供了一组问题 为了帮助您确定是否需要出口合规性文档,并且需要哪些表单。

然后去哪儿?

恭喜!你很快就会在Cryptokit可以做的所有事情上学习并学到了一点加密方式。而不是你很高兴Cryptokit让一切都变得如此简单吗?

您可以使用使用的项目的已完成版本 下载材料 本教程顶部或底部的按钮。

一如既往,您可以在源代码中了解更多:

除了整个教程中的(大多是维基百科)链接之外,这是椭圆曲线加密的解释,真正帮助我看看发生了什么:

平均评级

4.9/5

为此内容添加评级

12 ratings

更像这样的

贡献者

注释