当前位置: 首页 > news >正文

使用iOS安全API进行数据加密、解密、签名与验证完整指南

按下回车或点击查看完整尺寸图片

1. 加密与解密的基础知识

进行加密和解密操作,需要公钥和私钥。这些密钥通常通过安全隔离区、随机字符串、密码生成,或者从证书中获取。

2. 什么是签名和验证?

通过对数据进行签名,可以创建出一个数字签名。通过提供原始数据和签名,可以验证数据的完整性。

数字签名是接收方验证发送方身份真实性、数据完整性的保证。简单来说,它相当于手写签名。数字签名使用的是与加密/解密不同的另一套密钥对。

数字签名广泛应用于许多电子领域,例如当你要将应用提交测试或上传至App Store时,Xcode会对你的代码进行数字签名。通常,发送方对要发送的数据进行签名的流程如下:

  • 发送方使用特定的哈希算法(例如:sha256)对数据进行加密。哈希算法的输出称为"摘要"(例如:6e04f289)。
  • 然后,发送方使用自己的私钥摘要进行加密。这个加密后的摘要就是数据的"数字签名"。
  • 发送方将原始数据加密后的摘要一起发送出去。请注意,加密后的摘要仅用于验证发送方身份,而消息本身并未使用签名和验证所用的同一私钥进行加密。消息的加密是通过类似于上一节所述方式创建的私钥来完成的。

接收方验证接收到的数据的流程如下:

  • 接收方收到消息及其数字签名。
  • 接收方使用发送方的公钥解密数字签名 -> 得到的结果是摘要
  • 接收方使用与发送方相同的哈希算法,对收到的明文数据进行哈希运算 -> 这将输出一个摘要
  • 如果步骤2(数字签名解密后)输出的摘要 = 步骤3(对接收到的明文数据哈希后)输出的摘要 -> 接收方就可以验证数据的完整性。

在本教程中,用于数字签名的私钥将存储在安全隔离区中,而公钥则存储在安全隔离区之外,并与接收方共享。

从证书中获取公钥和私钥

classCryptoGraphicOperationViewModel{varp12Data:Datavarpassword:Stringinit(fileName:String="Certificate",ext:String="p12",password:String="1233"){self.p12Data=Self.insertCertificate()??Data()self.password=password}staticfuncinsertCertificate(fileName:String,ext:String,password:String)->Data?{returnUtils.dataFromFile(name:fileName,withExtension:ext)}publicfuncencrypt(data:Data,algorithm:SecKeyAlgorithm=.rsaEncryptionOAEPSHA512AESGCM)->Data?{guardletresult=Utils.certificateDataFromP12(p12Data:self.p12Data,password:self.password)else{returnnil}guardletpublicAndPrivateKey=Utils.publicAndPrivateKey(pkcs12Entry:result.pkcs12Entry)else{returnnil}returnself.encrypt(value:data,publicKey:publicAndPrivateKey.publicKey,algorithm:algorithm)}publicfuncdecrypt(data:Data,algorithm:SecKeyAlgorithm=.rsaEncryptionOAEPSHA512AESGCM)->Data?{guardletresult=Utils.certificateDataFromP12(p12Data:self.p12Data,password:self.password)else{returnnil}guardletpublicAndPrivateKey=Utils.publicAndPrivateKey(pkcs12Entry:result.pkcs12Entry)else{returnnil}returnself.decrypt(encrypted:data,privateKey:publicAndPrivateKey.privateKey,algorithm:algorithm)}publicfuncsign(dataToSign:Data,algorithm:SecKeyAlgorithm=.rsaSignatureMessagePKCS1v15SHA512)->Data?{guardletresult=Utils.certificateDataFromP12(p12Data:self.p12Data,password:self.password)else{returnnil}guardletpublicAndPrivateKey=Utils.publicAndPrivateKey(pkcs12Entry:result.pkcs12Entry)else{returnnil}returnself.signThe(data:dataToSign,privateKey:publicAndPrivateKey.privateKey,algorithm:algorithm)}publicfuncverify(signedData:Data,signature:Data,algorithm:SecKeyAlgorithm=.rsaSignatureMessagePKCS1v15SHA512)->Bool{guardletresult=Utils.certificateDataFromP12(p12Data:self.p12Data,password:self.password)else{returnfalse}guardletpublicAndPrivateKey=Utils.publicAndPrivateKey(pkcs12Entry:result.pkcs12Entry)else{returnfalse}returnself.verifySigned(data:signedData,signature:signature,publicKey:publicAndPrivateKey.publicKey,algorithm:algorithm)}internalfuncencrypt(value:Data,publicKey:SecKey,algorithm:SecKeyAlgorithm)->Data?{guardSecKeyIsAlgorithmSupported(publicKey,.encrypt,algorithm)else{debugPrint("不支持的加密算法")returnnil}varerrorRef:Unmanaged<CFError>?guardletencryptedData=SecKeyCreateEncryptedData(publicKey,algorithm,valueasCFData,&errorRef)else{leterror=errorRef?.takeRetainedValue()debugPrint("加密错误:\(String(describing:error))")returnnil}returnencryptedDataasData}internalfuncdecrypt(encrypted:Data,privateKey:SecKey,algorithm:SecKeyAlgorithm)->Data?{guardSecKeyIsAlgorithmSupported(privateKey,.decrypt,algorithm)else{debugPrint("不支持的解密算法")returnnil}varerrorRef:Unmanaged<CFError>?guardletdecryptedData=SecKeyCreateDecryptedData(privateKey,algorithm,encryptedasCFData,&errorRef)asData?else{leterror=errorRef?.takeRetainedValue()debugPrint("解密错误:\(String(describing:error))")returnnil}returndecryptedData}internalfuncsignThe(data:Data,privateKey:SecKey,algorithm:SecKeyAlgorithm)->Data?{guardSecKeyIsAlgorithmSupported(privateKey,.sign,algorithm)else{debugPrint("不支持的签名算法")returnnil}varerrorRef:Unmanaged<CFError>?guardletsignature=SecKeyCreateSignature(privateKey,algorithm,dataasCFData,&errorRef)asData?else{leterror=errorRef?.takeRetainedValue()debugPrint("签名错误:\(String(describing:error))")returnnil}returnsignatureasData}internalfuncverifySigned(data:Data,signature:Data,publicKey:SecKey,algorithm:SecKeyAlgorithm)->Bool{guardSecKeyIsAlgorithmSupported(publicKey,.verify,algorithm)else{debugPrint("不支持的验证算法")returnfalse}guarddata.isNotEmptyelse{debugPrint("无法使用空签名数据进行验证")returnfalse}varerrorRef:Unmanaged<CFError>?guardSecKeyVerifySignature(publicKey,algorithm,dataasCFData,signatureasCFData,&errorRef)else{debugPrint("验证错误:\(String(describing:errorRef?.takeRetainedValue()asError?))")returnfalse}returntrue}}

从iOS安全隔离区生成密钥

// 创建访问控制对象letaccess=SecAccessControlCreateWithFlags(kCFAllocatorDefault,// 1kSecAttrAccessibleWhenUnlockedThisDeviceOnly,// 2[.privateKeyUsage,.biometryAny],// 3nil// 4)!letsecEnclaveTag="YourKey".data(using:.utf8)!// 5letprivateKeyParams:[String:AnyObject]=[kSecAttrIsPermanentasString:trueasAnyObject,// 6kSecAttrApplicationTagasString:secEnclaveTagasAnyObject,// 7kSecAttrAccessControlasString:access// 8]letattributes=[kSecAttrKeyTypeasString:kSecAttrKeyTypeECSECPrimeRandom,// 9kSecAttrKeySizeInBitsasString:256,// 10kSecAttrTokenIDasString:kSecAttrTokenIDSecureEnclave,// 11kSecPrivateKeyAttrsasString:privateKeyParams// 12]asCFDictionaryvarerror:Unmanaged<CFError>?guardletprivateKey=SecKeyCreateRandomKey(attributesasCFDictionary,&error)else{throwerror!.takeRetainedValue()asError}guardletpublicKey=SecKeyCopyPublicKey(privateKey)else{print("公钥生成错误")return""}

创建签名

letmessage="AshishAwasthi"guardletmessageData=message.data(using:String.Encoding.utf8)else{print("无效的待签名消息。")returnnil}// 1. 创建签名guardletsignData=SecKeyCreateSignature(privateKey,SecKeyAlgorithm.ecdsaSignatureMessageX962SHA256,messageDataasCFData,nil)else{print("签名错误")returnnil}// 2. 获取签名数据letsignedData=signDataasDataletsignedString=signedData.base64EncodedString(options:[])print("签名字符串",signedString)// 3. 验证签名letmessageToVerify="AshishAwasthi"guardletmessageDataToVerify=messageToVerify.data(using:String.Encoding.utf8)else{print("ECC 无效的待验证消息")returnfalse}guardletsignatureData=signedDataelse{print("无效的待验证消息。")returnfalse}letverify=SecKeyVerifySignature(publicKey,SecKeyAlgorithm.ecdsaSignatureMessageX962SHA256,messageDataToVerifyasCFData,signatureDataasCFData,nil)

总结

在本教程中,您学到了:

  • 对称加密与非对称加密及解密的区别。
  • 如何在iOS应用中使用Swift安全API实现非对称加密。
  • iOS安全元件/隔离区。
  • 数字签名和验证。
  • 如何通过安全隔离区对数据进行数字签名和验证。

结语

如果您觉得本文信息量大,请考虑分享并留下反馈,以便它能触达更广泛的读者 👏👏👏👏👏 !!!FINISHED
CSD0tFqvECLokhw9aBeRqun7QRQBiR11shbIyj7WeHfnF6U3xpa+0XjfU5DHXhvAyl5l+jExjFG4yiYEgxlUn78vQpdt/iTlM7OZ+q6Yb8t99Q5GsOMP/Y5LZ6+0EoZbl1FbJH3na1nVAFh5ucwQIyIF+TLXD5Sz9UGvbCO1uQo=
更多精彩内容 请关注我的个人公众号 公众号(办公AI智能小助手)
对网络安全、黑客技术感兴趣的朋友可以关注我的安全公众号(网络安全技术点滴分享)

http://www.jsqmd.com/news/397111/

相关文章:

  • 题解:洛谷 P1070 [NOIP 2009 普及组] 道路游戏
  • 如何修复 Chrome Devtools Console 中无法粘贴代码的问题 All In One
  • Trae和Trae团队和Trae技术
  • 题解:洛谷 P1880 [NOI1995] 石子合并
  • COMSOL 隧道断层突水案例探究:不同开挖步数下的围岩奥秘
  • 题解:洛谷 P1435 [IOI 2000] 回文字串
  • Java 时间类(中):JDK8 全新时间 API 详细教程
  • 降AI率常见误区TOP10:别再走弯路了!2026年最全避坑指南
  • <P5464 缩小社交圈>
  • 支持实时预览与高质量导出的专业封面设计工具,完全免费:西瓜封面设计
  • 文科论文降AI比理工科更难?文科生专属降AI方案全解析
  • 题解:洛谷 P1541 [NOIP 2010 提高组] 乌龟棋
  • PEM 电解槽直流道两相流模拟:从建模到求解
  • 手把手教你使用vscode开发stm32!
  • 题解:洛谷 P1854 [IOI 1999] 花店橱窗布置
  • 题解:洛谷 P4310 绝世好题
  • 中华民族音乐传承出版工程服务平台界面设计
  • 用DeepSeek写的论文怎么降AI率?2026最新实操教程手把手教你
  • 2026毕业季降AI全攻略:从论文写作到最终提交一站式指南
  • 法智学教育软件课件UI设计
  • 【Python】【机器学习】集成算法(随机森林、提升算法)
  • 中小企业全生命周期知识产权管理100问:从初创到成熟,一文读懂核心要点
  • 题解:洛谷 P1004 [NOIP 2000 提高组] 方格取数
  • 基于高频信号的PMSM转矩脉动抑制:一场仿真探索之旅
  • 3分钟搞懂深度学习AI:感知机,AI模仿大脑
  • 题解:洛谷 P2679 [NOIP 2015 提高组] 子串
  • 论文降AI后导师说风格变了怎么办?保持个人写作风格的实用指南
  • 题解:洛谷 P1439 两个排列的最长公共子序列
  • php条件语句(混合php的if语句和js编程)
  • 题解:洛谷 P4933 大师