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

使用AES加密数据传输的iOS客户端实现方案

在现代应用开发中,确保数据传输的安全性是至关重要的。本文将介绍如何在iOS客户端中使用AES加密数据传输,并与服务器端保持加密解密的一致性。本文不会包含服务器端代码,但会解释其实现原理。

加密与解密的基本原理

AES(Advanced Encryption Standard)是一种对称加密算法,即加密和解密使用相同的密钥。为了增强安全性,AES通常与CBC(Cipher Block Chaining)模式和随机生成的初始化向量(IV)一起使用。

为什么IV明文传输不会影响安全性?
  1. 防止重复模式:IV确保相同的明文在每次加密时产生不同的密文,从而防止攻击者通过观察加密输出模式来推断输入模式。
  2. 随机性和唯一性:IV的唯一要求是随机性和唯一性,而不需要保密。因此,IV可以以明文形式与加密数据一起传输。
  3. 加密标准:大多数现代加密标准和协议(如AES-CBC、AES-GCM)都规定IV可以以明文形式传输。

客户端实现方案

在iOS客户端中,我们将使用以下步骤来实现AES加密数据传输:

  1. 生成和存储加密密钥:在用户登录成功后,从服务器获取并存储加密密钥。
  2. 加密请求数据:在每次发送请求时,使用AES和随机生成的IV对请求数据进行加密,并将IV与加密数据一起传输。
  3. 解密响应数据:在接收到服务器响应后,使用AES和IV对响应数据进行解密。

以下是实现这些步骤的详细代码。

AES加密解密类

import CommonCryptoclass AES {// 加密方法static func encrypt(data: Data, key: String) -> (Data, Data)? {return crypt(data: data, key: key, operation: CCOperation(kCCEncrypt))}// 解密方法static func decrypt(data: Data, key: String, iv: Data) -> Data? {return crypt(data: data, key: key, iv: iv, operation: CCOperation(kCCDecrypt)).map { $0.0 }}/**通用加密解密方法- Parameters:- data: 需要加密或解密的数据- key: 用于加密或解密的密钥- iv: 初始化向量。如果为空,则在加密时生成一个新的IV。在解密时需要传入之前生成的IV。- operation: 加密或解密操作(kCCEncrypt 或 kCCDecrypt)- Returns: 返回一个元组,包含加密或解密后的数据,以及用于加密的IV。如果操作失败,返回nil。*/private static func crypt(data: Data, key: String, iv: Data? = nil, operation: CCOperation) -> (Data, Data)? {// 确定AES密钥长度为128位(16字节)let keyLength = kCCKeySizeAES128var keyBytes = [UInt8](repeating: 0, count: keyLength)// 将密钥字符串转换为字节数组,并确保其长度为16字节key.getCString(&keyBytes, maxLength: keyLength + 1, encoding: .utf8)// 初始化向量(IV)的字节数组var ivBytes: [UInt8]if let iv = iv {// 如果传入了IV,使用传入的IVivBytes = [UInt8](iv)} else {// 如果没有传入IV,在加密时生成一个随机的IVlet ivSize = kCCBlockSizeAES128ivBytes = [UInt8](repeating: 0, count: ivSize)_ = SecRandomCopyBytes(kSecRandomDefault, ivSize, &ivBytes)}// 输入数据的长度let dataLength = data.count// 输出缓冲区大小应为数据长度加上一个AES块的大小let bufferSize = dataLength + kCCBlockSizeAES128var buffer = [UInt8](repeating: 0, count: bufferSize)// 存储实际加密或解密后的字节数var numBytesCrypted: size_t = 0// 调用CCCrypt函数执行加密或解密操作let cryptStatus = CCCrypt(operation,                  // 指定加密或解密操作CCAlgorithm(kCCAlgorithmAES128),  // 使用AES-128加密算法CCOptions(kCCOptionPKCS7Padding), // 使用PKCS7填充keyBytes,                   // 密钥字节数组keyLength,                  // 密钥长度ivBytes,                    // 初始化向量(IV)[UInt8](data),              // 输入数据字节数组dataLength,                 // 输入数据长度&buffer,                    // 输出缓冲区bufferSize,                 // 输出缓冲区大小&numBytesCrypted            // 实际加密或解密后的字节数)// 检查加密或解密操作是否成功if cryptStatus == kCCSuccess {// 返回加密或解密后的数据,以及用于加密的IVlet cryptData = Data(bytes: buffer, count: numBytesCrypted)return (cryptData, Data(ivBytes))}// 如果操作失败,返回nilreturn nil}
}

自定义Request和Response Serializer

为了处理请求和响应的加密解密,我们将创建自定义的AFJSONRequestSerializerAFHTTPResponseSerializer

import AFNetworking// 自定义Request Serializer
class EncryptedJSONRequestSerializer: AFJSONRequestSerializer {var encryptionKey: String?override func request(bySerializingRequest request: URLRequest, withParameters parameters: Any?, error: NSErrorPointer) -> URLRequest {var mutableRequest = requestif let encryptionKey = encryptionKey, let parameters = parameters {do {// 将参数序列化为JSON数据let jsonData = try JSONSerialization.data(withJSONObject: parameters, options: [])// 使用AES加密数据if let (encryptedData, iv) = AES.encrypt(data: jsonData, key: encryptionKey) {let base64String = encryptedData.base64EncodedString()let ivString = iv.base64EncodedString()// 将加密数据和IV一起传输let encryptedParameters = ["data": base64String, "iv": ivString]let encryptedJsonData = try JSONSerialization.data(withJSONObject: encryptedParameters, options: [])mutableRequest.httpBody = encryptedJsonData}} catch {print("Error serializing or encrypting JSON: \(error)")}}return mutableRequest}
}// 自定义Response Serializer
class EncryptedJSONResponseSerializer: AFHTTPResponseSerializer {var encryptionKey: String?override func responseObject(for response: URLResponse, data: Data?, error: NSErrorPointer) -> Any? {guard let encryptionKey = encryptionKey else {if error != nil {error?.pointee = NSError(domain: "Missing encryption key", code: -1, userInfo: nil)}return nil}guard let data = data else {if error != nil {error?.pointee = NSError(domain: "No data", code: -1, userInfo: nil)}return nil}do {// 解密响应数据if let jsonResponse = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],let encryptedDataString = jsonResponse["data"] as? String,let ivString = jsonResponse["iv"] as? String,let encryptedData = Data(base64Encoded: encryptedDataString),let ivData = Data(base64Encoded: ivString) {if let decryptedData = AES.decrypt(data: encryptedData, key: encryptionKey, iv: ivData) {return try JSONSerialization.jsonObject(with: decryptedData, options: [])}}} catch {if error != nil {error?.pointee = error as NSError}}return nil}
}

网络管理类

我们将创建一个网络管理类来处理登录和发送加密请求。

import AFNetworkingclass NetworkManager {static let shared = NetworkManager()private let baseURL = "https://localhost:8443"private var token: String?private var encryptionKey: String?private init() {}/**用户登录方法- Parameters:- username: 用户名- password: 密码- completion: 登录完成后的回调,传递登录是否成功的布尔值*/func login(username: String, password: String, completion: @escaping (Bool) -> Void) {let parameters: [String: Any] = ["username": username, "password": password]// 发起POST请求进行登录AFHTTPSessionManager().post("\(baseURL)/login", parameters: parameters, headers: nil, progress: nil, success: { [weak self] (task, responseObject) inif let response = responseObject as? [String: Any], let token = response["token"] as? String, let encryptionKey = response["encryptionKey"] as? String {// 保存token和加密密钥self?.token = tokenself?.encryptionKey = encryptionKeycompletion(true)} else {completion(false)}}) { (task, error) inprint("Login failed: \(error)")completion(false)}}/**发送加密请求方法- Parameters:- parameters: 请求参数- completion: 请求完成后的回调,传递结果*/func sendSecureRequest(parameters: [String: Any], completion: @escaping (Result<[String: Any], Error>) -> Void) {guard let token = token, let encryptionKey = encryptionKey else {completion(.failure(NSError(domain: "No token or encryption key", code: 0, userInfo: nil)))return}let manager = AFHTTPSessionManager()let requestSerializer = EncryptedJSONRequestSerializer()requestSerializer.encryptionKey = encryptionKeymanager.requestSerializer = requestSerializerlet responseSerializer = EncryptedJSONResponseSerializer()responseSerializer.encryptionKey = encryptionKeymanager.responseSerializer = responseSerializerlet headers: HTTPHeaders = ["Authorization": token]// 发起POST请求发送加密数据manager.post("\(baseURL)/secure-data", parameters: parameters, headers: headers, progress: nil, success: { (task, responseObject) inif let response = responseObject as? [String: Any] {completion(.success(response))} else {completion(.failure(NSError(domain: "Invalid response", code: 0, userInfo: nil)))}}) { (task, error) incompletion(.failure(error))}}
}

使用示例

let username = "testuser"
let password = "testpassword"// 用户登录
NetworkManager.shared.login(username: username, password: password) { success inif success {print("Login successful")// 发送加密请求let parameters: [String: Any] = ["example": "data"]NetworkManager.shared.sendSecureRequest(parameters: parameters) { result inswitch result {case .success(let response):print("Secure data response: \(response)")case .failure(let error):print("Request failed: \(error)")}}} else {print("Login failed")}
}

总结

本文介绍了如何在iOS客户端中使用AES加密数据传输,并确保与服务器端的一致性。通过使用随机生成的IV并将其明文传输,我们可以有效地防止重复模式攻击,增强数据传输的安全性。希望这篇文章对你在应用开发中的数据安全保护有所帮助。

相关文章:

使用AES加密数据传输的iOS客户端实现方案

在现代应用开发中&#xff0c;确保数据传输的安全性是至关重要的。本文将介绍如何在iOS客户端中使用AES加密数据传输&#xff0c;并与服务器端保持加密解密的一致性。本文不会包含服务器端代码&#xff0c;但会解释其实现原理。 加密与解密的基本原理 AES&#xff08;Advance…...

vue3【实战】语义化首页布局

技术要点&#xff0c;详见注释 <script setup></script><template><div class"page"><header>页头</header><nav>导航</nav><!-- 主体内容 --><main class"row"><aside>左侧边栏<s…...

FANG:利用社交网络图进行虚假新闻检测

1.概述 社交媒体已逐渐演变成为公众获取信息的主要途径。然而,值得警惕的是,并非所有流通的信息都具备真实性。特别是在政治选举、疫情爆发等关键节点,带有恶意企图的虚假信息(即“假新闻”)可能会对社会秩序、公平性和理性思考造成严重的干扰。作为全球抗击COVID-19的一部…...

Vue2 基础八电商后台管理项目——中

代码下载 商品分类页 新商品分类组件 goods/Cate.vue&#xff0c;在router.js中导入子级路由组件 Cate.vue&#xff0c;并设置路由规则。 绘制商品分类基本结构 在Cate.vue组件中添加面包屑导航以及卡片视图中的添加分类按钮&#xff1a; <template><div><…...

Typescript window.localStorage 存储 Obj Value区别

window.localStorage.setItem(UserC, JSON.stringify(userC)) const userC JSON.parse(window.localStorage.getItem(UserC) || {}) 不能获得UserC&#xff0c;所有保存的时候需要存储value&#xff0c;而不是对象。 {"__v_isShallow":false, "__v_isRef&quo…...

Linux要解压 .rar 文件,你应该使用 unrar 命令

命令 sudo tar -zxf ~/WebDemo.rar -C /usr/local 有一些问题。tar 命令通常用于解压 .tar、.tar.gz 或 .tar.bz2 文件&#xff0c;而不是 .rar 文件。要解压 .rar 文件&#xff0c;你应该使用 unrar 命令。下面是正确的步骤&#xff1a; 首先&#xff0c;安装 unrar&#xff0…...

【qt】如何获取网卡的信息?

网卡不只一种,有有线的,有无线的等等 我们用QNetworkInterface类的静态函数allInterfaces() 来获取所有的网卡 返回的是一个网卡的容器. 然后我们对每个网卡来获取其设备名称和硬件地址 可以通过静态函数humanReadableName() 来获取设备名称 可以通过静态函数**hardwareAddre…...

使用Netty框架实现WebSocket服务端与客户端通信(附ssl)

仓库地址&#xff1a; https://gitee.com/lfw1024/netty-websocket 导入后可直接运行 预览页面 自签证书&#xff1a; #换成自己的本地ip keytool -genkey -alias server -keyalg RSA -validity 3650 -keystore D:\mystore.jks -ext sanip:192.168.3.7,ip:127.0.0.1,dns:lo…...

ssm校园志愿服务信息系统-计算机毕业设计源码97697

摘 要 随着社会的进步和信息技术的发展&#xff0c;越来越多的学校开始重视志愿服务工作&#xff0c;通过组织各种志愿服务活动&#xff0c;让学生更好地了解社会、服务社会。然而&#xff0c;在实际操作中&#xff0c;志愿服务的组织和管理面临着诸多问题&#xff0c;如志愿者…...

JVM原理(二):JVM之HotSpot虚拟机中对象的创建寻位与定位整体流程

1. 对象的创建 遇到new指令时 当Java虚拟机遇到一个字节码new指令时。 首先会去检查这个指令的参数是否能在常量池中定位到一个类的符号引用&#xff0c;并且检查这个符号引用代表的类是否被加载、解析和初始化过。 如果没有&#xff0c;那么必须执行类的加载过程(加载、检查…...

(七)glDrawArry绘制

几何数据&#xff1a;vao和vbo 材质程序&#xff1a;vs和fs(顶点着色器和片元着色器) 接下来只需要告诉GPU&#xff0c;使用几何数据和材质程序来进行绘制。 #include <glad/glad.h>//glad必须在glfw头文件之前包含 #include <GLFW/glfw3.h> #include <iostrea…...

记一次小程序渗透

这次的小程序渗透刚好每一个漏洞都相当经典所以记录一下。 目录 前言 漏洞详情 未授权访问漏洞/ 敏感信息泄露&#xff08;高危&#xff09; 水平越权&#xff08;高危&#xff09; 会话重用&#xff08;高危&#xff09; 硬编码加密密钥泄露&#xff08;中危&#xff0…...

C++ 的常见算法 之一

C 的常见算法 之一 不修改序列算法for_eachcountfind 修改序列算法copymove 不修改序列算法 for_each #include <iostream> // std::cout #include <algorithm> // std::for_each #include <vector> // std::vectorusing namespace std;struc…...

微前端的需求有哪些?微前端的原理是怎么样的?为什么这么设计,及微前端的应用场景是什么?对有些客户,前端的重要性高于后端

微前端&#xff08;Micro Frontends&#xff09;是将前端应用拆分成多个独立、可部署的部分&#xff0c;每个部分可以由不同的团队独立开发、测试、部署和维护。这种架构类似于微服务在后端的应用&#xff0c;是为了应对复杂前端应用的维护和扩展问题而提出的。 来龙去脉 背景…...

【Spring Boot】统一数据返回

目录 统一数据返回一. 概念二.实现统一数据返回2.1 重写responseAdvice方法2.2 重写beforeBodyWriter方法 三. 特殊类型-String的处理四. 全部代码 统一数据返回 一. 概念 其实统一数据返回是运用了AOP&#xff08;对某一类事情的集中处理&#xff09;的思维&#xff0c;简单…...

证券交易系统中服务器监控系统功能设计

1.背景介绍 此服务器监控系统的目的在于提高行情服务器的监管效率&#xff0c;因目前的的行情服务器&#xff0c;包括DM、DT、DS配置数量较多&#xff0c;巡回维护耗时较多&#xff0c;当行情服务器出现异常故障&#xff0c;或者因为网络问题造成数据断线等情况时&#xff0c;监…...

【线性代数的本质】矩阵与线性变换

线性变化要满足两点性质&#xff1a; 直线&#xff08;连续的点&#xff09;在变换后还是直线。原点不变。 假设有坐标轴&#xff08;基底&#xff09; i ^ \widehat{i} i 和 j ^ \widehat{j} j ​&#xff1a; i ^ [ 1 0 ] , j ^ [ 0 1 ] \widehat{i}\begin{bmatrix} 1 \…...

CV02_超强数据集:MSCOCO数据集的简单介绍

1.1 简介 MSCOCO数据集&#xff0c;全称为Microsoft Common Objects in Context&#xff0c;是由微软公司在2014年推出并维护的一个大规模的图像数据集&#xff0c;旨在推动计算机视觉领域的研究&#xff0c;尤其是目标识别、目标检测、实例分割、图像描述生成等任务。该数据集…...

Linux--信号(万字详解!超完整!)

目录 0.预备知识 0.1.基本概念 0.2.信号的捕捉 0.3.理解信号的发送与保存 1.信号的产生&#xff08;阶段一&#xff09; 1.通过kill命令&#xff0c;向指定进程发送指定的信号 2.通过终端按键产生信号&#xff1a;ctrlc&#xff08;信号2&#xff09;&#xff0c;ctrl\(…...

onnx模型转rknn到部署

简介 最近开始用3568的板子&#xff0c;之前是在用3399&#xff0c;cpu的话3399比3568强&#xff0c;但是3568有1T的npu算力&#xff0c;所以模型移植过来用npu使用&#xff0c;之前用ncnn感觉太慢了&#xff0c;rk的npu使用没有开源&#xff0c;所以没法兼容&#xff0c;只能跑…...

微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】

微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来&#xff0c;Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...

Zustand 状态管理库:极简而强大的解决方案

Zustand 是一个轻量级、快速和可扩展的状态管理库&#xff0c;特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...

将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?

Otsu 是一种自动阈值化方法&#xff0c;用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理&#xff0c;能够自动确定一个阈值&#xff0c;将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...

【2025年】解决Burpsuite抓不到https包的问题

环境&#xff1a;windows11 burpsuite:2025.5 在抓取https网站时&#xff0c;burpsuite抓取不到https数据包&#xff0c;只显示&#xff1a; 解决该问题只需如下三个步骤&#xff1a; 1、浏览器中访问 http://burp 2、下载 CA certificate 证书 3、在设置--隐私与安全--…...

Psychopy音频的使用

Psychopy音频的使用 本文主要解决以下问题&#xff1a; 指定音频引擎与设备&#xff1b;播放音频文件 本文所使用的环境&#xff1a; Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...

IoT/HCIP实验-3/LiteOS操作系统内核实验(任务、内存、信号量、CMSIS..)

文章目录 概述HelloWorld 工程C/C配置编译器主配置Makefile脚本烧录器主配置运行结果程序调用栈 任务管理实验实验结果osal 系统适配层osal_task_create 其他实验实验源码内存管理实验互斥锁实验信号量实验 CMISIS接口实验还是得JlINKCMSIS 简介LiteOS->CMSIS任务间消息交互…...

AspectJ 在 Android 中的完整使用指南

一、环境配置&#xff08;Gradle 7.0 适配&#xff09; 1. 项目级 build.gradle // 注意&#xff1a;沪江插件已停更&#xff0c;推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...

初探Service服务发现机制

1.Service简介 Service是将运行在一组Pod上的应用程序发布为网络服务的抽象方法。 主要功能&#xff1a;服务发现和负载均衡。 Service类型的包括ClusterIP类型、NodePort类型、LoadBalancer类型、ExternalName类型 2.Endpoints简介 Endpoints是一种Kubernetes资源&#xf…...

return this;返回的是谁

一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请&#xff0c;不同级别的经理有不同的审批权限&#xff1a; // 抽象处理者&#xff1a;审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...

关于uniapp展示PDF的解决方案

在 UniApp 的 H5 环境中使用 pdf-vue3 组件可以实现完整的 PDF 预览功能。以下是详细实现步骤和注意事项&#xff1a; 一、安装依赖 安装 pdf-vue3 和 PDF.js 核心库&#xff1a; npm install pdf-vue3 pdfjs-dist二、基本使用示例 <template><view class"con…...