1. Crypto 加密算法

? 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í)”!

參考鏈接

更新日志

日期 次數(shù) 備注
2020.05.22 1
2020.05.25 2
2020.07.10 3
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容