❀ Apple CryptoKit 加密算法库 ❀
加密库
Apple CryptoKit
CryptoSwift
EllipticCurveKit
OpenSSL
术语介绍
Hash
Hash,音译为哈希,也叫散列函数、摘要算法。它是把任意长度的输入,通过散列算法变换成固定长度的输出,该输出就是散列值。
常用的哈希算法有:
MD5
MD5 信息摘要算法(MD5 Message-Digest Algorithm),一种被广泛使用的密码散列函数,可以产生出一个128位(16字节)的散列值,用于确保信息传输完整一致。
SHA
SHA (Secure Hash Algorithm),即安全散列算法。散列算法又称杂凑算法或哈希算法,能将一定长度的消息计算出固定长度的字符串(又称消息摘要)。SHA包含5个算法,分别是SHA-1、SHA-224、SHA-256、SHA-384和SHA-512,后四者并称为SHA-2。
Cyclic Redundancy Check (CRC)
循环冗余校验(Cyclic redundancy check,通称“CRC”)是一种根据网络数据包或电脑文件等数据产生简短固定位数校验码的一种散列函数,主要用来检测或校验数据传输或者保存后可能出现的错误。生成的数字在传输或者存储之前计算出来并且附加到数据后面,然后接收方进行检验确定数据是否发生变化。一般来说,循环冗余校验的值都是32位的整数。
Cipher
AES,高级加密标准(Advanced Encryption Standard),又称 Rijndael 加密法,是美国联邦政府采用的一种区块加密标准。
Message authenticators
MAC,消息认证码(带密钥的 Hash 函数):密码学中,通信实体双方使用的一种验证机制,保证消息数据完整性的一种工具。构造方法由 M.Bellare 提出,安全性依赖于 Hash 函数,故也称带密钥的 Hash 函数。消息认证码是基于密钥和消息摘要所获得的一个值,可用于数据源发认证和完整性校验。
Password-Based Key Derivation Function
PBKDF2(Password-Based Key Derivation Function)是一个用来导出密钥的函数,常用于生成加密的密码。它的基本原理是通过一个伪随机函数(例如 HMAC 函数),把明文和一个盐值作为输入参数,然后重复进行运算,并最终产生密钥。如果重复的次数足够大,破解的成本就会变得很高。而盐值的添加也会增加“彩虹表”攻击的难度。
CryptoSwift 使用方法
安装
- CocoaPods
pod 'CryptoSwift', '~> 1.0'
- Carthage
github "krzyzanowskim/CryptoSwift"
在需要使用 CryptoSwift 的地方将其 import 进来:
import CryptoSwift
数据类型转换
// Bytes 转 Data
let data = Data([0x01, 0x02, 0x03])
print(data)
// Data 转 Bytes
let bytes = data.bytes
print(bytes)
// Hex 转 Bytes
let bytes1 = Array<UInt8>(hex: "0x010203")
print(bytes1)
// Bytes 转 Hex
let hex = bytes1.toHexString()
print(hex)
// String 转 Bytes
let bytes2 = "password".bytes
print(bytes2)
// Bytes 转 Base64
let bytes3: [UInt8] = [1, 2, 3]
let base64String = bytes3.toBase64()
print(base64String!)
// String 的 Base64 编码
let string = "Allen"
let base64String1 = string.bytes.toBase64()
print(base64String1!)
计算 MD5 值
// Bytes 的 MD5 值
let bytes:Array<UInt8> = [0x01, 0x02, 0x03]
let digest = bytes.md5().toHexString()
print(digest)
let digest1 = Digest.md5(bytes).toHexString()
print(digest1)
// Data 的 MD5 值
let data = Data([0x01, 0x02, 0x03])
let digest2 = data.md5().toHexString()
print(digest2)
// String 的 MD5 值
let string = "Allen"
let digest3 = string.md5()
print(digest3)
计算 SHA 值
// Bytes 的 SHA 值
let bytes:Array<UInt8> = [0x01, 0x02, 0x03]
let digest = bytes.sha1().toHexString()
//let digest = Digest.sha1(bytes)
print(digest)
let digest1 = bytes.sha224().toHexString()
//let digest1 = Digest.sha224(bytes)
print(digest1)
let digest2 = bytes.sha256().toHexString()
//let digest2 = Digest.sha256(bytes)
print(digest2)
let digest3 = bytes.sha384().toHexString()
//let digest3 = Digest.sha384(bytes)
print(digest3)
let digest4 = bytes.sha512().toHexString()
//let digest4 = Digest.sha512(bytes)
print(digest4)
// Data 的 SHA 值
let data = Data([0x01, 0x02, 0x03])
let digest5 = data.sha1()
//let digest5 = Digest.sha1(data.bytes)
print(digest5)
let digest6 = data.sha224()
//let digest6 = Digest.sha224(data.bytes)
print(digest6)
let digest7 = data.sha256()
//let digest7 = Digest.sha256(data.bytes)
print(digest7)
let digest8 = data.sha384()
//let digest8 = Digest.sha384(data.bytes)
print(digest8)
let digest9 = data.sha512()
//let digest9 = Digest.sha512(data.bytes)
print(digest9)
// String 的 SHA 值
let string = "Allen"
let digest10 = string.sha1()
print(digest10)
let digest11 = string.sha224()
print(digest11)
let digest12 = string.sha256()
print(digest12)
let digest13 = string.sha384()
print(digest13)
let digest14 = string.sha512()
print(digest14)
// 拼接多组运算
do {
var digest = MD5()
let partial1 = try digest.update(withBytes: "All".bytes)
print(partial1)
let partial2 = try digest.update(withBytes: "en".bytes)
print(partial2)
let result = try digest.finish()
print(result)
print(result.toHexString() == "Allen".md5()
} catch {
}
CRC 校验码计算
// Bytes 的 CRC 值
let bytes:Array<UInt8> = [0x01, 0x02, 0x03]
let crc = bytes.crc16()
print(crc)
let crc1 = bytes.crc32()
print(crc1)
// Data 的 CRC 值
let data = Data([0x01, 0x02, 0x03])
let crc2 = data.crc16()
print(crc2)
let crc3 = data.crc32()
print(crc3)
// String 的 CRC 值
let string = "Allen"
let crc4 = string.crc16()
print(crc4)
let crc5 = string.crc32()
print(crc5)
MAC 消息认证码计算
// 计算 HMAC(Hashed Message Authentication Code)中文名叫做:散列消息身份验证码。
let string = "Allen"
let key = "123"
let hmac = try! HMAC(key: key.bytes, variant: HMAC.Variant.md5).authenticate(string.bytes)
print(hmac.toHexString())
let hmac1 = try! HMAC(key: key.bytes, variant: HMAC.Variant.sha1).authenticate(string.bytes)
print(hmac1.toHexString())
let hmac2 = try! HMAC(key: key.bytes, variant: HMAC.Variant.sha256).authenticate(string.bytes)
print(hmac2.toHexString())
let hmac3 = try! HMAC(key: key.bytes, variant: HMAC.Variant.sha384).authenticate(string.bytes)
print(hmac3.toHexString())
let hmac4 = try! HMAC(key: key.bytes, variant: HMAC.Variant.sha512).authenticate(string.bytes)
print(hmac4.toHexString())
// 计算 CMAC(基于分组加密的消息认证码)
let cmac = try! CMAC(key: key.bytes).authenticate(string.bytes)
print(cmac.toHexString())
// 计算 Poly1305
// Poly1305 消息认证码的输入为 32 字节(256bit)的密钥和任意长度的消息比特流,经过一系列计算生成 16 字节(128bit)的摘要。
let key32 = "AA012345678901234567890123456789"
let poly1305 = try! Poly1305(key: key32.bytes).authenticate(string.bytes)
print(poly1305.toHexString())
PBKDF 加密
// PBKDF2
let password = "Allen"
let salt = "ABCDEFGH12345678"
let pbkdf2 = try! PKCS5.PBKDF2(password: password.bytes, salt: salt.bytes).calculate()
print(pbkdf2.toHexString())
// 指定生成密钥的长度
/// - parameters:
/// - password: 用来生成密钥的原始密码
/// - salt: 加密用的盐值
/// - iterations: 重复计算的次数。默认值:4096
/// - keyLength: 期望得到的密钥的长度。默认值:不指定
/// - variant: 加密使用的伪随机函数。默认值:sha256
let pbkdf2New = try! PKCS5.PBKDF2(password: password.bytes, salt: salt.bytes, iterations: 1024, keyLength: 4, variant: HMAC.Variant.sha256).calculate()
print(pbkdf2New.toHexString())
AES 加密
// ECB 模式
do {
let string = "Allen"
let key = "ABCDEFGH12345678"
// 使用 AES-128-ECB 加密模式
let aes = try AES(key: key.bytes, blockMode: ECB())
// 加密
let encrypted = try aes.encrypt(string.bytes)
print(encrypted.toHexString())
// 解密
let decrypted = try aes.decrypt(encrypted)
print(String(data: Data(decrypted), encoding: .utf8)!)
} catch {
}
// ECB 模式
do {
let string = "Allen"
let key = "12345678"
// 使用 AES-128-ECB 加密模式
// 如果密钥长度不够 16、24 或 32 字节,可以使用 zeroPadding 将其补齐至 blockSize 的整数倍
let aes = try AES(key: Padding.zeroPadding.add(to: key.bytes, blockSize: AES.blockSize), blockMode: ECB())
// 加密
let encrypted = try aes.encrypt(string.bytes)
print(encrypted.toHexString())
// 解密
let decrypted = try aes.decrypt(encrypted)
print(String(data: Data(decrypted), encoding: .utf8)!)
} catch {
}
// CBC 模式
do {
let string = "Allen"
let key = "ABCDEFGH12345678"
let iv = "1234567890123456"
// 使用 AES-128-ECB 加密模式
let aes = try AES(key: key.bytes, blockMode: CBC(iv: iv.bytes))
//let aes = try AES(key: key, iv: iv)
// 加密
let encrypted = try aes.encrypt(string.bytes)
print(encrypted.toHexString())
// 解密
let decrypted = try aes.decrypt(encrypted)
print(String(data: Data(decrypted), encoding: .utf8)!)
} catch {
}
// 随机生成密钥偏移量
let iv = AES.randomIV(AES.blockSize)
print(iv) // 16 字节
// 增量更新
do {
let aes = try AES(key: "ABCDEFGH12345678", iv: "1234567890123456")
// 创建一个用于增量加密的 Cryptor 实例
var encryptor = try aes.makeEncryptor()
var ciphertext = Array<UInt8>()
// 合并每个部分的结果
ciphertext += try encryptor.update(withBytes: Array("Allen".utf8))
ciphertext += try encryptor.update(withBytes: Array("Crypto".utf8))
ciphertext += try encryptor.update(withBytes: Array("Swift".utf8))
// 结束
ciphertext += try encryptor.finish()
// 输出完整的结果(base64 字符串形式)
print(ciphertext.toBase64()!)
// 创建一个用于增量解密的 Deryptor 实例
var decryptor = try aes.makeDecryptor()
var result = Array<UInt8>()
result += try decryptor.update(withBytes: ciphertext)
result += try decryptor.finish()
print(String(data: Data(result), encoding: .utf8)!)
} catch {
print(error)
}
// Padding 补码方式
// pkcs5、pkcs7、zeroPadding、noPadding
ChaCha20
do {
let string = "Allen"
let key = "ABCDEFGH12345678ABCDEFGH12345678"
let iv = "12345678"
let chiper = try ChaCha20(key: key, iv: iv)
let encrypted = try chiper.encrypt(string.bytes)
let decrypted = try chiper.decrypt(encrypted)
print(String(data: Data(decrypted), encoding: .utf8)!)
} catch {
print(error)
}
Rabbit
do {
let string = "Allen"
let key = "ABCDEFGH12345678"
let iv = "12345678"
let chiper = try Rabbit(key: key, iv: iv)
let encrypted = try chiper.encrypt(string.bytes)
let decrypted = try chiper.decrypt(encrypted)
print(String(data: Data(decrypted), encoding: .utf8)!)
} catch {
print(error)
}
Blowfish
do {
let string = "Allen"
let key = "ABCDEFGH12345678"
let iv = "12345678"
let chiper = try Blowfish(key: key.bytes, blockMode: CBC(iv: iv.bytes), padding: .pkcs7)
let encrypted = try chiper.encrypt(string.bytes)
let decrypted = try chiper.decrypt(encrypted)
print(String(data: Data(decrypted), encoding: .utf8)!)
} catch {
print(error)
}
总结
欢迎留言讨论,有错误请指出,谢谢!
Swift 开发学习交流,联系我 QQ:3500229193 入群,请备注“Swift 学习”!
参考链接
- https://developer.apple.com/documentation/cryptokit
- https://www.oschina.net/p/swift-crypto
- http://www.carymic.com/2020/02/08/
- https://github.com/krzyzanowskim/CryptoSwift
- https://www.hangge.com/blog/cache/detail_1865.html
- https://www.hangge.com/blog/cache/detail_1867.html
- https://www.hangge.com/blog/cache/detail_1869.html
- https://www.hangge.com/blog/cache/detail_1870.html
- 填充 (密码学)
- https://blog.csdn.net/qq_18497653/article/details/84073464
- https://zh.wikipedia.org/wiki/高级加密标准
更新日志
日期 | 次数 | 备注 |
---|---|---|
2020.05.22 | 1 | |
2020.05.25 | 2 | |
2020.07.10 | 3 |