美文网首页iOS进阶+实战
iOS开发之CryptoKit

iOS开发之CryptoKit

作者: YungFan | 来源:发表于2020-07-05 12:05 被阅读0次

    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经过协商产生了共享密钥")
    }
    

    相关文章

      网友评论

        本文标题:iOS开发之CryptoKit

        本文链接:https://www.haomeiwen.com/subject/srujqktx.html