? Apple CryptoKit 加密算法庫 ?
加密庫
Apple CryptoKit
CryptoSwift
EllipticCurveKit
OpenSSL
術(shù)語介紹
Hash
Hash,音譯為哈希,也叫散列函數(shù)、摘要算法。它是把任意長度的輸入,通過散列算法變換成固定長度的輸出,該輸出就是散列值。
常用的哈希算法有:
MD5
MD5 信息摘要算法(MD5 Message-Digest Algorithm),一種被廣泛使用的密碼散列函數(shù),可以產(chǎn)生出一個(gè)128位(16字節(jié))的散列值,用于確保信息傳輸完整一致。
SHA
SHA (Secure Hash Algorithm),即安全散列算法。散列算法又稱雜湊算法或哈希算法,能將一定長度的消息計(jì)算出固定長度的字符串(又稱消息摘要)。SHA包含5個(gè)算法,分別是SHA-1、SHA-224、SHA-256、SHA-384和SHA-512,后四者并稱為SHA-2。
Cyclic Redundancy Check (CRC)
循環(huán)冗余校驗(yàn)(Cyclic redundancy check,通稱“CRC”)是一種根據(jù)網(wǎng)絡(luò)數(shù)據(jù)包或電腦文件等數(shù)據(jù)產(chǎn)生簡短固定位數(shù)校驗(yàn)碼的一種散列函數(shù),主要用來檢測或校驗(yàn)數(shù)據(jù)傳輸或者保存后可能出現(xiàn)的錯(cuò)誤。生成的數(shù)字在傳輸或者存儲之前計(jì)算出來并且附加到數(shù)據(jù)后面,然后接收方進(jìn)行檢驗(yàn)確定數(shù)據(jù)是否發(fā)生變化。一般來說,循環(huán)冗余校驗(yàn)的值都是32位的整數(shù)。
Cipher
AES,高級加密標(biāo)準(zhǔn)(Advanced Encryption Standard),又稱 Rijndael 加密法,是美國聯(lián)邦政府采用的一種區(qū)塊加密標(biāo)準(zhǔn)。
Message authenticators
MAC,消息認(rèn)證碼(帶密鑰的 Hash 函數(shù)):密碼學(xué)中,通信實(shí)體雙方使用的一種驗(yàn)證機(jī)制,保證消息數(shù)據(jù)完整性的一種工具。構(gòu)造方法由 M.Bellare 提出,安全性依賴于 Hash 函數(shù),故也稱帶密鑰的 Hash 函數(shù)。消息認(rèn)證碼是基于密鑰和消息摘要所獲得的一個(gè)值,可用于數(shù)據(jù)源發(fā)認(rèn)證和完整性校驗(yàn)。
Password-Based Key Derivation Function
PBKDF2(Password-Based Key Derivation Function)是一個(gè)用來導(dǎo)出密鑰的函數(shù),常用于生成加密的密碼。它的基本原理是通過一個(gè)偽隨機(jī)函數(shù)(例如 HMAC 函數(shù)),把明文和一個(gè)鹽值作為輸入?yún)?shù),然后重復(fù)進(jìn)行運(yùn)算,并最終產(chǎn)生密鑰。如果重復(fù)的次數(shù)足夠大,破解的成本就會變得很高。而鹽值的添加也會增加“彩虹表”攻擊的難度。
CryptoSwift 使用方法
安裝
- CocoaPods
pod 'CryptoSwift', '~> 1.0'
- Carthage
github "krzyzanowskim/CryptoSwift"
在需要使用 CryptoSwift 的地方將其 import 進(jìn)來:
import CryptoSwift
數(shù)據(jù)類型轉(zhuǎn)換
// Bytes 轉(zhuǎn) Data
let data = Data([0x01, 0x02, 0x03])
print(data)
// Data 轉(zhuǎn) Bytes
let bytes = data.bytes
print(bytes)
// Hex 轉(zhuǎn) Bytes
let bytes1 = Array<UInt8>(hex: "0x010203")
print(bytes1)
// Bytes 轉(zhuǎn) Hex
let hex = bytes1.toHexString()
print(hex)
// String 轉(zhuǎn) Bytes
let bytes2 = "password".bytes
print(bytes2)
// Bytes 轉(zhuǎn) 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!)
計(jì)算 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)
計(jì)算 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)
// 拼接多組運(yùn)算
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 校驗(yàn)碼計(jì)算
// 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 消息認(rèn)證碼計(jì)算
// 計(jì)算 HMAC(Hashed Message Authentication Code)中文名叫做:散列消息身份驗(yàn)證碼。
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())
// 計(jì)算 CMAC(基于分組加密的消息認(rèn)證碼)
let cmac = try! CMAC(key: key.bytes).authenticate(string.bytes)
print(cmac.toHexString())
// 計(jì)算 Poly1305
// Poly1305 消息認(rèn)證碼的輸入為 32 字節(jié)(256bit)的密鑰和任意長度的消息比特流,經(jīng)過一系列計(jì)算生成 16 字節(jié)(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: 重復(fù)計(jì)算的次數(shù)。默認(rèn)值:4096
/// - keyLength: 期望得到的密鑰的長度。默認(rèn)值:不指定
/// - variant: 加密使用的偽隨機(jī)函數(shù)。默認(rèn)值: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 字節(jié),可以使用 zeroPadding 將其補(bǔ)齊至 blockSize 的整數(shù)倍
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 {
}
// 隨機(jī)生成密鑰偏移量
let iv = AES.randomIV(AES.blockSize)
print(iv) // 16 字節(jié)
// 增量更新
do {
let aes = try AES(key: "ABCDEFGH12345678", iv: "1234567890123456")
// 創(chuàng)建一個(gè)用于增量加密的 Cryptor 實(shí)例
var encryptor = try aes.makeEncryptor()
var ciphertext = Array<UInt8>()
// 合并每個(gè)部分的結(jié)果
ciphertext += try encryptor.update(withBytes: Array("Allen".utf8))
ciphertext += try encryptor.update(withBytes: Array("Crypto".utf8))
ciphertext += try encryptor.update(withBytes: Array("Swift".utf8))
// 結(jié)束
ciphertext += try encryptor.finish()
// 輸出完整的結(jié)果(base64 字符串形式)
print(ciphertext.toBase64()!)
// 創(chuàng)建一個(gè)用于增量解密的 Deryptor 實(shí)例
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 補(bǔ)碼方式
// 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)
}
總結(jié)
歡迎留言討論,有錯(cuò)誤請指出,謝謝!
Swift 開發(fā)學(xué)習(xí)交流,聯(lián)系我 QQ:3500229193 入群,請備注“Swift 學(xué)習(xí)”!
參考鏈接
- 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
- 填充 (密碼學(xué))
- https://blog.csdn.net/qq_18497653/article/details/84073464
- https://zh.wikipedia.org/wiki/高級加密標(biāo)準(zhǔn)
更新日志
| 日期 | 次數(shù) | 備注 |
|---|---|---|
| 2020.05.22 | 1 | |
| 2020.05.25 | 2 | |
| 2020.07.10 | 3 |