专栏首页学海无涯iOS开发之CryptoKit

iOS开发之CryptoKit

Apple 在 WWDC2019 推出了一个基于 Swift 的密码框架 CryptoKit,它让生成哈希值、加/解密数据、数字签名和密钥协商变得更加容易。

阅读本文前,需要有一定的密码学基础。请参考之前的一篇文章搞定密码学基础一文。

哈希值

  • 提供了 3 种 Hash 函数:
    • SHA256
    • SHA384
    • SHA512
  • 哈希普通的 Data 类型的数据
let str = "Hello CryptoKit"
let data = str.data(using: .utf8)!

let hash256 = SHA256.hash(data: data)
let hash384 = SHA384.hash(data: data)
let hash512 = SHA512.hash(data: data)

print(hash256.description)
  • 哈希文件
if let filePath = Bundle.main.path(forResource: "secret", ofType: "json"),
    let data = FileManager.default.contents(atPath: filePath) {
    
    let hash256 = SHA256.hash(data: data)
    let hash384 = SHA384.hash(data: data)
    let hash512 = SHA512.hash(data: data)
    
    print(hash256.description)
}

HMAC

HMAC 可以理解为一种更安全的 Hash,它需要借助于前面介绍的 Hash 函数。

// 构造一个salt
let salt = "YungFan".data(using: .utf8)!

// 密钥
let key = SymmetricKey(size: .bits256)

// HMAC with SHA256
let authenticationCode = HMAC<SHA256>.authenticationCode(for: salt, using: key)
print(authenticationCode)

// 验证
if HMAC<SHA256>.isValidAuthenticationCode(Data(authenticationCode),
                                          authenticating: salt, using: key) {
    print("未被篡改")
}

加解密数据

支持 AES-GCM 和 ChaChaPoly 算法。开发中首选 ChaChaChaPoly,因为按照官方宣称它在移动设备上的速度更快。ChaChaChaPoly 中的核心概念是ChaChaChaPoly.SealedBox,它可以理解为只有通过密钥才能访问的数据容器,加密操作时把加密后的密文放在其中,解密操作时需要从中取出密文进行解密。

  • 加密
// 明文
let str = "Hello CryptoKit"
let data = str.data(using: .utf8)!

// 密钥,有3种长度的密钥
let key128 = SymmetricKey(size: .bits128)
let key192 = SymmetricKey(size: .bits192)
let key256 = SymmetricKey(size: .bits256)

// 加密
let encryptedContent = try? ChaChaPoly.seal(data, using: key256).combined
  • 解密
// 解密
if let encryptedContent = encryptedContent {
    if let sealedBox = try? ChaChaPoly.SealedBox(combined: encryptedContent) {
        if let decryptedContent = try? ChaChaPoly.open(sealedBox, using: key256) {
            print(String(data: decryptedContent, encoding: .utf8))
        }
        
        // SealedBox的3个属性
        let nonce = sealedBox.nonce
        let ciphertext = sealedBox.ciphertext
        let tag = sealedBox.tag
        
        print(sealedBox.combined == nonce + ciphertext + tag)
    }
}

数字签名

内置了 4 种不同的椭圆曲线类型用于创建和验证加密签名,分别是 Curve25519, P521, P384 和 P256,不同的类型有不同的安全性和速度,但通常选择 Curve25519。

  • 产生公/私钥
// 私钥
let privateKey = Curve25519.Signing.PrivateKey()
// 公钥
let publicKey = privateKey.publicKey
// 发布公钥
let publicKeyData = publicKey.rawRepresentation 
  • 私钥签名
let str = "Hello CryptoKit"
let data = str.data(using: .utf8)!

let signature = try? privateKey.signature(for: data)
  • 公钥验证
if let signature = signature {
    if publicKey.isValidSignature(NSData(data: signature) , for: data) {
        print("签名有效")
    }
}

密钥协商

密钥协商是一个过程,通过这个过程,通信双方可以安全地选择一个加密密钥,然后用它来进行加解密数据。

// 构造一个salt,生成密钥时需要使用
let salt = "YungFan".data(using: .utf8)!

// 用户A和用户B都会生成一对公钥和私钥
let privateKeyA = P521.KeyAgreement.PrivateKey()
let publicKeyA = privateKeyA.publicKey

let privateKeyB = P521.KeyAgreement.PrivateKey()
let publicKeyB = privateKeyB.publicKey

// 用户A用私钥和用户B的公钥产生一个共享的密钥
let sharedSecretA = try? privateKeyA.sharedSecretFromKeyAgreement(with: publicKeyB)
let symmetricKeyA = sharedSecretA?.hkdfDerivedSymmetricKey(using: SHA256.self, salt: salt, sharedInfo: Data(), outputByteCount: 32)

// 用户B用私钥和用户A的公钥产生一个共享的密钥
let sharedSecretB = try? privateKeyB.sharedSecretFromKeyAgreement(with: publicKeyA)
let symmetricKeyB = sharedSecretB?.hkdfDerivedSymmetricKey(using: SHA256.self, salt: salt, sharedInfo: Data(), outputByteCount: 32)


if symmetricKeyA == symmetricKeyB {
    print("A和B经过协商产生了共享密钥")
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 38.Swift学习之实用知识点

    Swift 中提供了很多实用的知识点,这些知识点极大提高了开发的效率。本章节主要罗列 Swift 中那些好用但未必人人都知道的知识点。

    YungFan
  • 30.Swift学习之Codable协议

    开发中推荐使用Paste JSON as Code • quicktype软件,可以根据JSON快速生成Model文件

    YungFan
  • Swift学习之5.1和5.2新特性

    Swift 5.1 内置于 Xcode 11,新增了很多新特性,比较重要的有以下几个。

    YungFan
  • Swift基础---Integers

    用户3004328
  • ES2018

    但如果数据源是异步的,for...of循环就只能拿到一堆Promise,而不是想要的值:

    ayqy贾杰
  • swift基础1

    用户2554571
  • ES6

    ES的全称是ECMAScript,它是由ECMA国际标准化组织制定的一项脚本语言的标准化规范。

    eadela
  • swift图片颜色占比分析

    调用以上方法,终端输出: [0.3862848497311907, 0.093752754193718965, 0.088868650665413204, 0...

    用户6094182
  • 变量的解构赋值

    上面代码中,函数move的参数是一个对象,通过对这个对象进行解构,得到变量x和y的值。如果解构失败,x和y等于默认值。

    达达前端
  • 38.Swift学习之实用知识点

    Swift 中提供了很多实用的知识点,这些知识点极大提高了开发的效率。本章节主要罗列 Swift 中那些好用但未必人人都知道的知识点。

    YungFan

扫码关注云+社区

领取腾讯云代金券