CryptoKit简易使用教程
2021-01-05 本文已影响0人
LonnieQ
哈希数据
支持的哈希算法有
- MD5
- SHA1
- SHA256
- SHA384
- SHA512
其中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
对称加密
该框架支持的对称加密算法有限:
- GCM模式的AES算法
- ChaChaPoly
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