用 Swift 实现的与加密相关的函数和助手,适用于 Swift。(#PureSwift)
注意:main 分支遵循最新发布的 Swift 版本。如果您需要较早版本的 Swift,请在 Podfile 中指定其版本或使用该版本的分支代码。旧分支不受支持。查看版本了解详情。
需求 | 特性 | 贡献 | 安装 | Swift 版本 | 使用方法 | 作者 | 许可证 | 更新日志
项目的财务可持续性得益于我们的 GitHub 赞助商 持续的贡献
Emerge Tools 是一套革命性产品,旨在为移动应用及其开发团队提供超级动力。
心情愉悦
MD5 | SHA1 | SHA2-224 | SHA2-256 | SHA2-384 | SHA2-512 | SHA3
AES-128, AES-192, AES-256 | ChaCha20 | XChaCha20 | Rabbit | Blowfish
Poly1305 | HMAC (MD5, SHA1, SHA256) | CMAC | CBC-MAC
你想帮忙,太好了!继续 fork 我们的仓库,做出你的修改并发送给我们一个拉取请求。
查看 CONTRIBUTING.md 了解如何帮助 CryptoSwift 的更多信息。
如果应用使用本地运行签名签名证书并启用了强化运行时,二进制 CryptoSwift.xcframework(由 Swift Package Manager 包集成使用)将无法在你的应用中正确加载。Xcode 可能会这样设置。要解决这个问题,你有两个选择:
禁用库验证 即 com.apple.security.cs.disable-library-validation 权限要安装 CryptoSwift,将其作为子模块添加到你的项目(在顶级项目目录):
git submodule add https://github.com/krzyzanowskim/CryptoSwift.git
建议启用整模块优化以获得更好的性能。未优化的构建会导致性能明显变差。
你可以使用 Swift Package Manager 并在 Package.swift 中通过添加以下内容指定依赖:
.package(url: "https://github.com/krzyzanowskim/CryptoSwift.git", from: "1.8.3")
注意:Swift Package Manager 在 Xcode 调试构建中使用调试配置,这可能会导致性能显著下降(最多 10000 倍)。发布构建中的性能特征有所不同。要解决这个问题,请考虑嵌入下面描述的 CryptoSwift.xcframework。
你可以使用 CocoaPods。
pod 'CryptoSwift', '~> 1.8.3'
请记住,CocoaPods 将在没有整模块优化的情况下构建 CryptoSwift,这可能会影响性能。你可以在安装后手动更改它,或使用 cocoapods-wholemodule 插件。
你可以使用 Carthage。 在 Cartfile 中指定:
github "krzyzanowskim/CryptoSwift"
运行 carthage 构建框架,并将构建的 CryptoSwift.framework 拖入你的 Xcode 项目。按照构建说明进行操 作。常见问题。
XCFrameworks 需要 Xcode 11 或更高版本,它们可以像我们习惯集成 .framework 格式一样进行集成。
请使用脚本 scripts/build-framework.sh 生成二进制 CryptoSwift.xcframework 存档,你可以在 Xcode 中将其用作依赖项。
CryptoSwift.xcframework 是一个发布(优化)二进制文件,提供最佳可用的 Swift 代码性能。
<img width="320" alt="Screen Shot 2020-10-27 at 00 06 32" src="https://yellow-cdn.veclightyear.com/2b54e442/1e2df743-9203-4fdb-97fd-e7ffdddc9bc1.png">嵌入式框架要求最低部署目标为 iOS 11.0 或 macOS Sierra (10.13)。将 CryptoSwift.xcodeproj 文件拖入你的 Xcode 项目,并将适当的框架作为依赖项添加到你的目标。现在选择你的应用并选择应用目标的 General 选项卡。找到 嵌入式二进制文件 并按 "+",然后选择 `CryptoSwift
import CryptoSwift
CryptoSwift使用字节数组(即Array<UInt8>)作为所有操作的基本类型。任何数据都可以转换为字节流。你会发现一些接受String或Data的便捷函数,它们会在内部转换为字节数组。
为了方便使用,CryptoSwift提供了两个函数,可以轻松地将字节数组转换为Data或将Data转换为字节数组:
从字节创建Data:
let data = Data([0x01, 0x02, 0x03])
Data转换为Array<UInt8>
let bytes = data.bytes // [1,2,3]
十六进制编码:
let bytes = Array<UInt8>(hex: "0x010203") // [1,2,3] let hex = bytes.toHexString() // "010203"
从String构建字节
let bytes: Array<UInt8> = "cipherkey".bytes // Array("cipherkey".utf8)
另外...查看使用Base64编码数据的辅助函数:
"aPf/i9th9iX+vf49eR7PYk2q7S5xmm3jkRLejgzHNJs=".decryptBase64ToString(cipher) "aPf/i9th9iX+vf49eR7PYk2q7S5xmm3jkRLejgzHNJs=".decryptBase64(cipher) bytes.toBase64()
对数据或字节数组(即Array<UInt8>)进行哈希处理
/* Hash结构体用法 */ let bytes: Array<UInt8> = [0x01, 0x02, 0x03] let digest = input.md5() let digest = Digest.md5(bytes)
let data = Data([0x01, 0x02, 0x03]) let hash = data.md5() let hash = data.sha1() let hash = data.sha224() let hash = data.sha256() let hash = data.sha384() let hash = data.sha512()
do { var digest = MD5() let partial1 = try digest.update(withBytes: [0x31, 0x32]) let partial2 = try digest.update(withBytes: [0x33]) let result = try digest.finish() } catch { }
对字符串进行哈希处理并打印结果
let hash = "123".md5() // "123".bytes.md5()
bytes.crc16() data.crc16() bytes.crc32() data.crc32()
// 为消息计算消息认证码(MAC) let key: Array<UInt8> = [1,2,3,4,5,6,7,8,9,10,...] try Poly1305(key: key).authenticate(bytes) try HMAC(key: key, variant: .sha256).authenticate(bytes) try CMAC(key: key).authenticate(bytes)
let password: Array<UInt8> = Array("s33krit".utf8) let salt: Array<UInt8> = Array("nacllcan".utf8) let key = try PKCS5.PBKDF2(password: password, salt: salt, iterations: 4096, keyLength: 32, variant: .sha256).calculate()
let password: Array<UInt8> = Array("s33krit".utf8) let salt: Array<UInt8> = Array("nacllcan".utf8) // Scrypt实现不支持并行化工作,因此`p`参数即使在多核系统中也会增加工作时间 let key = try Scrypt(password: password, salt: salt, dkLen: 64, N: 16384, r: 8, p: 1).calculate()
let password: Array<UInt8> = Array("s33krit".utf8) let salt: Array<UInt8> = Array("nacllcan".utf8) let key = try HKDF(password: password, salt: salt, variant: .sha256).calculate()
某些内容加密算法假设输入长度是k个八位字节的倍数,其中k大于1。对于这样的算法,需要对输入进行填充。
Padding.pkcs7.add(to: bytes, blockSize: AES.blockSize)
let encrypted = try ChaCha20(key: key, iv: iv).encrypt(message) let decrypted = try ChaCha20(key: key, iv: iv).decrypt(encrypted)
let encrypted = try Rabbit(key: key, iv: iv).encrypt(message) let decrypted = try Rabbit(key: key, iv: iv).decrypt(encrypted)
let encrypted = try Blowfish(key: key, blockMode: CBC(iv: iv), padding: .pkcs7).encrypt(message) let decrypted = try Blowfish(key: key, blockMode: CBC(iv: iv), padding: .pkcs7).decrypt(encrypted)
关于填充的注意事项:手动填充数据是可选的,CryptoSwift默认使用PKCS7填充。如果你需要手动禁用/启用填充,可以通过设置__AES__类的参数来实现
AES加密的变体(AES-128、AES-192、AES-256)取决于给定的密钥长度:
AES-256示例
let encryptedBytes = try AES(key: [1,2,3,...,32], blockMode: CBC(iv: [1,2,3,...,16]), padding: .pkcs7)
完整示例:
let password: [UInt8] = Array("s33krit".utf8) let salt: [UInt8] = Array("nacllcan".utf8) /* 从`密码`生成密钥。如果已经有密钥,则可选 */ let key = try PKCS5.PBKDF2( password: password, salt: salt, iterations: 4096, keyLength: 32, /* AES-256 */ variant: .sha256 ).calculate() /* 生成随机IV值。IV是公开值。需要生成或从其他地方获取 */ let iv = AES.randomIV(AES.blockSize) /* AES加密器实例 */ let aes = try AES(key: key, blockMode: CBC(iv: iv), padding: .pkcs7) /* 加密数据 */ let inputData = Data() let encryptedBytes = try aes.encrypt(inputData.bytes) let encryptedData = Data(encryptedBytes) /* 解密数据 */ let decryptedBytes = try aes.decrypt(encryptedData.bytes) let decryptedData = Data(decryptedBytes)
do { let aes = try AES(key: "keykeykeykeykeyk", iv: "drowssapdrowssap") // aes128 let ciphertext = try aes.encrypt(Array("Nullam quis risus eget urna mollis ornare vel eu leo.".utf8)) } catch { }
增量操作使用Cryptor实例,一次加密/解密一部分,这样可以为大文件节省内存。
do { var encryptor = try AES(key: "keykeykeykeykeyk", iv: "drowssapdrowssap").makeEncryptor() var ciphertext = Array<UInt8>() // 聚合部分结果 ciphertext += try encryptor.update(withBytes: Array("Nullam quis risus ".utf8)) ciphertext += try encryptor.update(withBytes: Array("eget urna mollis ".utf8)) ciphertext += try encryptor.update(withBytes: Array("ornare vel eu leo.".utf8)) // 最后完成 ciphertext += try encryptor.finish() print(ciphertext.toHexString()) } catch { print(error) }
let input: Array<UInt8> = [0,1,2,3,4,5,6,7,8,9] let key: Array<UInt8> = [0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00] let iv: Array<UInt8> = // `AES.blockSize`长度的随机字节 do { let encrypted = try AES(key: key, blockMode: CBC(iv: iv), padding: .pkcs7).encrypt(input) let decrypted = try AES(key: key, blockMode: CBC(iv: iv), padding: .pkcs7).decrypt(encrypted) } catch { print(error) }
不带数据填充的AES
let input: Array<UInt8> = [0,1,2,3,4,5,6,7,8,9] let encrypted: Array<UInt8> = try! AES(key: Array("secret0key000000".utf8), blockMode: CBC(iv: Array("0123456789012345".utf8)), padding: .noPadding).encrypt(input)
使用便捷扩展
let plain = Data([0x01, 0x02, 0x03]) let encrypted = try! plain.encrypt(ChaCha20(key: key, iv: iv)) let decrypted = try! encrypted.decrypt(ChaCha20(key: key, iv: iv))
伽罗瓦/计数器模式(GCM)加密的结果是密文和认证标签,后者用于解密。
加密
do { // 在组合模式下,认证标签直接附加到加密消息后。这通常是你想要的。 let gcm = GCM(iv: iv, mode: .combined) let aes = try AES(key: key, blockMode: gcm, padding: .noPadding) let encrypted = try aes.encrypt(plaintext) let tag = gcm.authenticationTag } catch { // 失败 }
解密
do { // 在组合模式下,认证标签附加在加密消息后。这通常是你想要的。 let gcm = GCM(iv: iv, mode: .combined) let aes = try AES(key: key, blockMode: gcm, padding: .noPadding) return try aes.decrypt(encrypted) } catch { // 失败 }
注意:GCM实例不能重复使用。所以你不能使用同一个GCM实例进行加密和解密。
带密码块链消息认证码的计数器模式(CCM)加密的结果是密文和认证标签,后者用于解密。
do { // 认证标签附加在加密消息后。 let tagLength = 8 let ccm = CCM(iv: iv, tagLength: tagLength, messageLength: ciphertext.count - tagLength, additionalAuthenticatedData: data) let aes = try AES(key: key, blockMode: ccm, padding: .noPadding) return try aes.decrypt(encrypted) } catch { // 失败 }
请查看文档或CCM规范以了解CCM的有
let encrypt = try AEADChaCha20Poly1305.encrypt(plaintext, key: key, iv: nonce, authenticationHeader: header) let decrypt = try AEADChaCha20Poly1305.decrypt(ciphertext, key: key, iv: nonce, authenticationHeader: header, authenticationTag: tagArr: tag)
从参数初始化RSA
let input: Array<UInt8> = [0,1,2,3,4,5,6,7,8,9] let n: Array<UInt8> = // RSA模数 let e: Array<UInt8> = // RSA公开指数 let d: Array<UInt8> = // RSA私有指数 let rsa = RSA(n: n, e: e, d: d) do { let encrypted = try rsa.encrypt(input) let decrypted = try rsa.decrypt(encrypted) } catch { print(error) }
RSA密钥生成
let rsa = try RSA(keySize: 2048) // 这将生成具有给定大小的模数、公开指数和私有指数
RSA加密和解密示例
// Alice生成一个私钥 let alicesPrivateKey = try RSA(keySize: 1024) // Alice与Bob分享她的**公钥** let alicesPublicKeyData = try alicesPrivateKey.publicKeyExternalRepresentation() // Bob接收Alice公钥的原始外部表示并导入它 let bobsImportOfAlicesPublicKey = try RSA(rawRepresentation: alicesPublicKeyData) // Bob现在可以使用Alice的公钥为她加密一条消息 let message = "Hi Alice! This is Bob!" let privateMessage = try bobsImportOfAlicesPublicKey.encrypt(message.bytes) // 这会产生一些加密输出,如下所示 // URcRwG6LfH63zOQf2w+HIllPri9Rb6hFlXbi/bh03zPl2MIIiSTjbAPqbVFmoF3RmDzFjIarIS7ZpT57a1F+OFOJjx50WYlng7dioKFS/rsuGHYnMn4csjCRF6TAqvRQcRnBueeINRRA8SLaLHX6sZuQkjIE5AoHJwgavmiv8PY= // Bob现在可以将这个加密消息发送给Alice,而不用担心其他人能够读取原始内容 // Alice接收加密消息并使用她的私钥解密数据,恢复原始消息 let originalDecryptedMessage = try alicesPrivateKey.decrypt(privateMessage) print(String(data: Data(originalDecryptedMessage), encoding: .utf8)) // "Hi Alice! This is Bob!"
RSA签名和验证示例
// Alice生成一个私钥 let alicesPrivateKey = try RSA(keySize: 1024) // Alice想要签署一条她同意的消息 let messageAliceSupports = "Hi my name is Alice!" let alicesSignature = try alicesPrivateKey.sign(messageAliceSupports.bytes) // Alice与Bob分享她的公钥和签名 let alicesPublicKeyData = try alicesPrivateKey.publicKeyExternalRepresentation() // Bob接收Alice公钥的原始外部表示并导入它! let bobsImportOfAlicesPublicKey = try RSA(rawRepresentation: alicesPublicKeyData) // Bob现在可以验证Alice使用与她共享的公钥相关联的私钥签署了该消息。 let verifiedSignature = try bobsImportOfAlicesPublicKey.verify(signature: alicesSignature, for: "Hi my name is Alice!".bytes) if verifiedSignature == true { // Bob知道Alice提供的签名对该消息是有效的,并且是使用与Alice共享的公钥相关联的私钥签署的。 } else { // 签名无效,所以要么 // - Alice签署的消息与我们预期的不同。 // - 或者Alice使用了与Bob拥有的共享公钥不相关联的私钥。 }
CryptoSwift RSA密钥 -> Apple的Security Framework SecKey示例
/// 从CryptoSwift RSA密钥开始 let rsaKey = try RSA(keySize: 1024) /// 定义你的密钥属性 let attributes: [String:Any] = [ kSecAttrKeyType as String: kSecAttrKeyTypeRSA, kSecAttrKeyClass as String: kSecAttrKeyClassPrivate, // 或 kSecAttrKeyClassPublic kSecAttrKeySizeInBits as String: 1024, // 适当的位数 kSecAttrIsPermanent as String: false ] var error:Unmanaged<CFError>? = nil guard let rsaSecKey = try SecKeyCreateWithData(rsaKey.externalRepresentation() as CFData, attributes as CFDictionary, &error) else { /// 从原始密钥数据构造SecKey时出错 return } /// 现在你有了一个可以在Apple的Security框架中使用的RSA SecKey
Apple的Security Framework SecKey -> CryptoSwift RSA密钥示例
/// 从SecKey RSA密钥开始 let rsaSecKey:SecKey /// 复制外部表示 var externalRepError:Unmanaged<CFError>? guard let cfdata = SecKeyCopyExternalRepresentation(rsaSecKey, &externalRepError) else { /// 无法复制RSA SecKey的外部表示 return } /// 从原始外部表示实例化RSA密钥 let rsaKey = try RSA(rawRepresentation: cfdata as Data) /// 现在你有了一个CryptoSwift RSA密钥
CryptoSwift由Marcin Krzyżanowski拥有和维护
你可以在Twitter上关注我 @krzyzanowskim 以获取项目更新和发布信息。
本发行版包含加密软件。你目前居住的国家可能对加密软件的进口、拥有、使用和/或再出口到另一个国家有限制。在使用任何加密软件之前,请检查你所在国家的法律、法规和政策,了解是否允许进口、拥有或使用加密软件,以及是否允许将其再出口。详情请参见 https://www.wassenaar.org/。
版权所有 (C) 2014-2022 Marcin Krzyżanowski marcin@krzyzanowskim.com 本软件按"原样"提供,不提供任何明示或暗示的保证。
在任何情况下,作者均不对因使用本软件而产生的任何损害承担责任。
允许任何人出于任何目的使用本软件,包括商业应用,并且可以自由更改和重新分发,但须遵守以下限制:
请参阅CHANGELOG文件。


职场AI,就用扣子
AI办公助手,复杂任务高效处理。办公效率低?扣子空间AI助手支持播客生成、PPT制作、网页开发及报告写作,覆盖科研、商业、舆情等领域的专家Agent 7x24小时响应,生活工作无缝切换,提升50%效率!


多风格AI绘画神器
堆友平台由阿里巴巴设计团队创建,作为一款AI驱动的设计工具,专为设计师提供一站式增长服务。功能覆盖海量3D素材、AI绘画、实时渲染以及专业抠图,显著提升设计品质和效率。平台不仅提供工具,还是一个促进创意交流和个人发展的空间,界面友好,适合所有级别的设计师和创意工作者。


零代码AI应用开发平台
零代码AI应用开发平台,用户只需一句话简单描述需求,AI能自动生成小程序、APP或H5网页应用,无需编写代码。


免费创建高清无水印Sora视频
Vora是一个免费创建高清无水印Sora视频的AI工具


最适合小白的AI自动化工作流平台
无需编码,轻松生成可复用、可变现的AI自动化工作流

大模型驱动的Excel数据处理工具
基于大模型交互的表格处理系统,允许用户通过对话方式完成数据整理和可视化分析。系统采用机器学习算法解析用户指令,自动执行排序、公式计算和数据透视等操作,支持多种文件格式导入导出。数据处理响应速度保持在0.8秒以内,支持超过100万行数据的即时分析。


AI辅助编程,代码自动修复
Trae是一种自适应的集成开发环境(IDE),通过自动化和多元协作改变开发流程。利用Trae,团队能够更快速、精确地编写和部署代码,从而提高编程效率和项目交付速度。Trae具备上下文感知和代码自动完成功能,是提升开发效率的理想工具。


AI论文写作指导平台
AIWritePaper论文写作是一站式AI论文写作辅助工具,简化了选题、文献检索至论文撰写的整个过程。通过简单设定,平台可快速生成高质量论文大纲和全文,配合图表、参考文献等一应俱全,同时提供开题报告和答辩PPT等增值服务,保障数据 安全,有效提升写作效率和论文质量。


AI 一键生成PPT,就用博思AIPPT!
博思AIPPT,新一代的AI生成PPT平台,支持智能生成PPT、AI美化PPT、文本&链接生成PPT、导入Word/PDF/Markdown文档生成PPT等,内置海量精美PPT模板,涵盖商务、教育、科技等不同风格,同时针对每个页面提供多种版式,一键自适应切换,完美适配各种办公场景。


AI赋能电商视觉革命,一站式智能商拍平台
潮际好麦深耕服装行业,是国内AI试衣效果最好的软件。使用先进AIGC能力为电商卖家批量提供优质的、低成本的商拍图。合作品牌有Shein、Lazada、安踏、百丽等65个国内外头部品牌,以及国内10万+淘宝、天猫、京东等主流平台的品牌商家,为卖家节省将近85%的出图成本,提升约3倍出图效率,让品牌能够快速上架。
最新AI工具、AI资讯
独家AI资源、AI项目落地

微信扫一扫关注公众号