CryptoKit简易使用教程

2021-01-05  本文已影响0人  LonnieQ

哈希数据

支持的哈希算法有

其中MD5、SHA1被认为是不安全的哈希算法。

import CryptoKit
let data = "Hello world".data(using: .utf8)!
var sha256 = SHA256()
sha256.update(data: data)
print(sha256.finalize())
// SHA256 digest: 64ec88ca00b268e5ba1a35678a1b5316d212f4f366b2477232534a8aeca37f3c

HMAC验证数据

import CryptoKit
let data = "Hello world".data(using: .utf8)!
let key = SymmetricKey(data: Array(0..<32))
// 生成数据验证码
let authenticateCode = HMAC<SHA256>.authenticationCode(for: data, using: key)
print(authenticateCode)
// HMAC with SHA256: 8d02cc6dde5f1711bef21a1ed4b2d52f0c39daa8cef255bccae53ca24ef2f180
let authenticateCodeData = Data(authenticateCode)
// 验证数据
let isValid = HMAC<SHA256>.isValidAuthenticationCode(authenticateCodeData, authenticating: data, using: key)
print(isValid)
// true

对称加密

该框架支持的对称加密算法有限:

import CryptoKit
let data = "Hello world".data(using: .utf8)!
let key = SymmetricKey(data: Array(0..<32))
// 加密数据
let encrypted = try AES.GCM.seal(data, using: key).combined!
// 解密数据
let box = try AES.GCM.SealedBox(combined: encrypted)
let decrypted = try AES.GCM.open(box, using: key)
print(String(data: decrypted, encoding: .utf8)!)
// Hello world

利用Key Agreement交换密钥

import CryptoKit
let salt = "Salt".data(using: .utf8)!
// 为Alice生成密钥对
let alicePrivateKey = P256.KeyAgreement.PrivateKey()
let alicePublicKey = alicePrivateKey.publicKey
// 为Bob生成密钥对
let bobPrivateKey = P256.KeyAgreement.PrivateKey()
let bobPublicKey = bobPrivateKey.publicKey
// 使用Alice的私钥和Bob的公钥计算出Alice的对称密钥
let aliceSharedSecret = try! alicePrivateKey.sharedSecretFromKeyAgreement(with: bobPublicKey)
let aliceSymmetricKey = aliceSharedSecret.hkdfDerivedSymmetricKey(
    using: SHA256.self,
    salt: salt,
    sharedInfo: Data(),
    outputByteCount: 32
)
// 使用Bob的私钥和Alice的公钥计算出Bob的对称密钥
let bobSharedSecret = try! bobPrivateKey.sharedSecretFromKeyAgreement(with: alicePublicKey)
let bobSymmetricKey = bobSharedSecret.hkdfDerivedSymmetricKey(
    using: SHA256.self,
    salt: salt,
    sharedInfo: Data(),
    outputByteCount: 32
)
// Alice和Bob拥有相同的对称密钥
print(aliceSymmetricKey == bobSymmetricKey)
// true

创建和验证签名

import CryptoKit
let data = "Hello world".data(using: .utf8)!
// 生成密钥对
let signingKey = Curve25519.Signing.PrivateKey()
let signingPublicKey = signingKey.publicKey
let signingPublicKeyData = signingPublicKey.rawRepresentation
let initializedSigningPublicKey = try! Curve25519.Signing.PublicKey(rawRepresentation: signingPublicKeyData)
// 使用私钥计算签名
let signautre = try! signingKey.signature(for: data)
// 使用公钥验证签名
print(initializedSigningPublicKey.isValidSignature(signautre, for: data))
// true

公钥加密

enum DecryptionErrors: Error {
    case authenticationError
}
let salt = "Salt".data(using: .utf8)!

func encrypt(_ data: Data, to theirEncryptionKey: Curve25519.KeyAgreement.PublicKey, signedBy ourSigningKey: Curve25519.Signing.PrivateKey) throws ->
    (ephemeralPublicKeyData: Data, ciphertext: Data, signature: Data) {
        // 创建临时密钥对
        let ephemeralKey = Curve25519.KeyAgreement.PrivateKey()
        let ephemeralPublicKey = ephemeralKey.publicKey.rawRepresentation
        
        // 计算对称密钥
        let sharedSecret = try ephemeralKey.sharedSecretFromKeyAgreement(
            with: theirEncryptionKey
        )
        
        let symmetricKey = sharedSecret.hkdfDerivedSymmetricKey(
            using: SHA256.self,
            salt: salt,
            sharedInfo: ephemeralPublicKey + theirEncryptionKey.rawRepresentation + ourSigningKey.publicKey.rawRepresentation,
            outputByteCount: 32
        )
        // 利用对称密钥生成秘文
        let ciphertext = try ChaChaPoly.seal(data, using: symmetricKey).combined
    
        // 计算签名
        let signature = try ourSigningKey.signature(for: ciphertext + ephemeralPublicKey + theirEncryptionKey.rawRepresentation)
        //返回随机生成的公钥、秘文及签名
        return (ephemeralPublicKey, ciphertext, signature)
}

func decrypt(_ sealedMessage: (ephemeralPublicKeyData: Data, ciphertext: Data, signature: Data),
             using ourKeyEncryptionKey: Curve25519.KeyAgreement.PrivateKey,
             from theirSigningKey: Curve25519.Signing.PublicKey) throws -> Data {
    // 验证签名
    let data = sealedMessage.ciphertext + sealedMessage.ephemeralPublicKeyData + ourKeyEncryptionKey.publicKey.rawRepresentation
    guard theirSigningKey.isValidSignature(sealedMessage.signature, for: data) else {
        throw DecryptionErrors.authenticationError
    }

    let ephemeralKey = try Curve25519.KeyAgreement.PublicKey(
        rawRepresentation: sealedMessage.ephemeralPublicKeyData
    )
    
    // 计算对称密钥
    let sharedSecret = try ourKeyEncryptionKey.sharedSecretFromKeyAgreement(
        with: ephemeralKey
    )
    
    let symmetricKey = sharedSecret.hkdfDerivedSymmetricKey(
        using: SHA256.self,
        salt: salt,
        sharedInfo: ephemeralKey.rawRepresentation + ourKeyEncryptionKey.publicKey.rawRepresentation +
                                                                theirSigningKey.rawRepresentation,
        outputByteCount: 32
    )
    
    // 利用对称密钥解密数据
    let sealedBox = try ChaChaPoly.SealedBox(combined: sealedMessage.ciphertext)
    
    return try ChaChaPoly.open(sealedBox, using: symmetricKey)
}

let data = "Hello world".data(using: .utf8)!
// 创建发送者的签名密钥
let senderSigningKey = Curve25519.Signing.PrivateKey()
let senderSigningPublicKey = senderSigningKey.publicKey
// 创建接收者的加密密钥
let receiverEncryptionKey = Curve25519.KeyAgreement.PrivateKey()
let receiverEncryptionPublicKey = receiverEncryptionKey.publicKey
// 发送者利用接收者的公钥来加密数据,并使用发送者的私钥签名
let encrypted = try encrypt(data, to: receiverEncryptionPublicKey, signedBy: senderSigningKey)

// 接受者使用私钥加密数据,并使用发送者的公钥验证签名
let decryptedMessage = try decrypt(encrypted, using: receiverEncryptionKey, from: senderSigningPublicKey)
print("\(String(data: decryptedMessage, encoding: .utf8)!)")
// Hello world
上一篇下一篇

猜你喜欢

热点阅读