iOS AES/CBC/CTR加解密以及AES-CMAC
感觉iOS自带的CryptoKit不好用,有个第三方库CryptoSwift还不错,好巧不巧,清理过Xcode缓存后死活下载不下来,当然也可以自己编译个Framework,但是偏偏不想用第三方库了,于是研究了一下,自带的CommonCrypto也可以达到项目需求。
代码主要包含以下算法:
AES128/CBC/NoPadding
AES128/CTR/NoPadding
AES-CMAC
import Foundation
import CommonCryptoclass AESUtil {private init(){}//////AES-CMAC///static func CMAC(key: Data, data: Data) -> Data? {let blockSize = 16var subKey1 = Data(count: blockSize)var subKey2 = Data(count: blockSize)// Step 1: Generate subkeysguard generateSubKeys(key: key, subKey1: &subKey1, subKey2: &subKey2) else {return nil}// Step 2: Calculate the number of blockslet blockCount = (data.count + blockSize - 1) / blockSize// Step 3: Process each blockvar lastBlock = Data(count: blockSize)for i in 0..<blockCount {let blockRange = i * blockSize..<min((i + 1) * blockSize, data.count)var block = data.subdata(in: blockRange)if i == blockCount - 1 {if block.count < blockSize {block.append(0x80)while block.count < blockSize {block.append(0x00)}block = xor(data: block, with: subKey2)} else {block = xor(data: block, with: subKey1)}}lastBlock = xor(data: lastBlock, with: block)lastBlock = CBC(key: key, data: lastBlock, isEncrypt: true)!}return lastBlock}private static func generateSubKeys(key: Data, subKey1: inout Data, subKey2: inout Data) -> Bool {let blockSize = 16let zeroBlock = Data(count: blockSize)guard let L = CBC(key: key, data: zeroBlock, isEncrypt: true) else {return false}subKey1 = generateSubKey(block: L)subKey2 = generateSubKey(block: subKey1)return true}private static func generateSubKey(block: Data) -> Data {let blockSize = 16var subKey = Data(count: 16)var overflow = falsefor i in (0..<blockSize).reversed() {let byte = block[i]let shiftedByte = byte << 1subKey[i] = shiftedByte | (overflow ? 1 : 0)overflow = (byte & 0x80) != 0}if overflow {subKey[blockSize - 1] ^= 0x87}return subKey}private static func xor(data: Data, with other: Data) -> Data {var result = Data(count: data.count)for i in 0..<data.count {result[i] = data[i] ^ other[i]}return result}//////AES128/CBC/NoPadding加解密//////@param isEncrypt true加密,false解密///static func CBC(key: Data, data: Data, isEncrypt: Bool) -> Data? {return AES128NoPadding(key: key, iv: Data(count: 16), data: data, mode: "CBC", isEncrypt: isEncrypt)}//////AES128/CTR/NoPadding加解密//////@param isEncrypt true加密,false解密///static func CTR(key: Data, data: Data, isEncrypt: Bool) -> Data? {return AES128NoPadding(key: key, iv: Data(count: 16), data: data, mode: "CTR", isEncrypt: isEncrypt)}//////AES128/NoPadding加解密//////@param mode 支持CBC、CTR///@param isEncrypt true加密,false解密///static func AES128NoPadding(key: Data, iv: Data, data: Data, mode: String, isEncrypt: Bool) -> Data? {let bufferLength = data.count + kCCKeySizeAES128var buffer = Data(count: bufferLength)var numBytesEncrypted: size_t = 0let operation = isEncrypt ? kCCEncrypt : kCCDecryptlet cryptStatus: CCCryptorStatus = buffer.withUnsafeMutableBytes { (bufferPtr: UnsafeMutableRawBufferPointer) inkey.withUnsafeBytes { (keyPtr: UnsafeRawBufferPointer) iniv.withUnsafeBytes { (ivPtr: UnsafeRawBufferPointer) indata.withUnsafeBytes { (dataPtr: UnsafeRawBufferPointer) in//调用加密函数var modeSource = 0if mode == "CBC" {modeSource = kCCModeCBC} else if mode == "CTR" {modeSource = kCCModeCTR}let cryptorRef = UnsafeMutablePointer<CCCryptorRef?>.allocate(capacity: 1)var status = CCCryptorCreateWithMode(CCOperation(operation), CCMode(modeSource), CCAlgorithm(kCCAlgorithmAES), CCPadding(ccNoPadding), ivPtr.baseAddress, keyPtr.baseAddress, kCCKeySizeAES128, nil, 0, 0, CCModeOptions(0), cryptorRef)if status == kCCSuccess {status = CCCryptorUpdate(cryptorRef.pointee, dataPtr.baseAddress, data.count, bufferPtr.baseAddress, bufferLength, &numBytesEncrypted)} else {print("CCCryptorCreateWithMode fail: \(encryptError(status))")}return status}}}}if cryptStatus == kCCSuccess {buffer.removeSubrange(numBytesEncrypted..<bufferLength)return buffer}print("AES/\(mode)/NoPadding加解密失败: \(encryptError(cryptStatus))")return nil}private static func encryptError(_ status: CCCryptorStatus)-> String {if status == kCCParamError {return "kCCParamError"} else if status == kCCBufferTooSmall {return "kCCBufferTooSmall"} else if status == kCCMemoryFailure {return "kCCMemoryFailure"} else if status == kCCAlignmentError {return "kCCAlignmentError"} else if status == kCCDecodeError {return "kCCDecodeError"} else if status == kCCUnimplemented {return "kCCUnimplemented"} else if status == kCCOverflow {return "kCCOverflow"} else if status == kCCRNGFailure {return "kCCRNGFailure"} else if status == kCCUnspecifiedError {return "kCCUnspecifiedError"} else if status == kCCCallSequenceError {return "kCCCallSequenceError"} else if status == kCCKeySizeError {return "kCCKeySizeError"} else if status == kCCInvalidKey {return "kCCInvalidKey"}return "\(status)"}
}
相关文章:
iOS AES/CBC/CTR加解密以及AES-CMAC
感觉iOS自带的CryptoKit不好用,有个第三方库CryptoSwift还不错,好巧不巧,清理过Xcode缓存后死活下载不下来,当然也可以自己编译个Framework,但是偏偏不想用第三方库了,于是研究了一下,自带的Com…...
错误报告:WebSocket 设备连接断开处理问题
错误报告:WebSocket 设备连接断开处理问题 项目背景 设备通过自启动的客户端连接到服务器,服务器将设备的 mac_address 和设备信息存入 Redis。前端通过 Redis 接口查看设备信息并展示。 问题描述 设备连接到服务器后,前端无法立即看到设…...
点云配准网络
【论文笔记】点云配准网络 PCRNet: Point Cloud Registration Network using PointNet Encoding 2019_pcr-net-CSDN博客 【点云配准】【深度学习】Windows11下PCRNet代码Pytorch实现与源码讲解-CSDN博客 【点云配准】【深度学习】Windows11下GCNet代码Pytorch实现与源码讲解_…...

黑马Redis详细笔记(实战篇---短信登录)
目录 一.短信登录 1.1 导入项目 1.2 Session 实现短信登录 1.3 集群的 Session 共享问题 1.4 基于 Redis 实现共享 Session 登录 一.短信登录 1.1 导入项目 数据库准备 -- 创建用户表 CREATE TABLE user (id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT 用户ID,phone …...
51单片机俄罗斯方块整行消除函数
/************************************************************************************************************** * 名称:flash * 功能:行清除动画 * 参数:NULL * 返回:NULL * 备注: * 采用非阻塞延时࿰…...
Vue 3 30天精进之旅:Day 21 - 项目实践:打造功能完备的Todo应用
前言 经过前20天的学习,我们已经掌握了Vue 3的核心概念、组合式API、路由、状态管理等关键技术。今天将通过一个完整的项目实践——Todo应用,将所学知识融会贯通。我们将为Todo应用添加编辑、删除、过滤等进阶功能,并优化代码结构。 一、项目…...

32单片机学习记录1之GPIO
32单片机学习记录1之GPIO 前置 GPIO口在单片机中扮演着什么角色? 在单片机中,GPIO口(General Purpose Input/Output) 是一种通用输入/输出接口,扮演着连接单片机与外部设备的桥梁角色。具体来说,它在单片…...
AI 编程助手 Cline
Cline 是一款集成于 Visual Studio Code(VS Code)的 AI 编程助手,旨在提升开发者的编程效率和代码质量。 主要功能: 代码生成与补全:Cline 能根据开发者的输入,自动生成代码片段或完整的函数,减…...
YOLOv11-ultralytics-8.3.67部分代码阅读笔记-patches.py
patches.py ultralytics\utils\patches.py 目录 patches.py 1.所需的库和模块 2.def imread(filename: str, flags: int cv2.IMREAD_COLOR): 3.def imwrite(filename: str, img: np.ndarray, paramsNone): 4.def imshow(winname: str, mat: np.ndarray): 5.PyTorch…...

R语言LCMM多维度潜在类别模型流行病学研究:LCA、MM方法分析纵向数据
全文代码数据:https://tecdat.cn/?p39710 在数据分析领域,当我们面对一组数据时,通常会有已知的分组情况,比如不同的治疗组、性别组或种族组等(点击文末“阅读原文”获取完整代码数据)。 然而,…...
2025 年前端开发现状分析:卷疯了还是卷麻了?
一、前端现状:框架狂飙,开发者崩溃 如果你是个前端开发者,那么你大概率经历过这些场景: 早上打开 CSDN(或者掘金,随便),发现又有新框架发布了,名字可能是 VueXNext.js 之…...

RDK新一代模型转换可视化工具!!!
作者:SkyXZ CSDN:SkyXZ~-CSDN博客 博客园:SkyXZ - 博客园 之前在使用的RDK X3的时候,吴诺老师wunuo发布了新一代量化转换工具链使用教程,这个工具真的非常的方便,能非常快速的完成X3上模型的量化…...

JVM春招快速学习指南
1.说在前面 在Java相关岗位的春/秋招面试过程中,JVM的学习是必不可少的。本文主要是通过《深入理解Java虚拟机》第三版来介绍JVM的学习路线和方法,并对没有过JVM基础的给出阅读和学习建议,尽可能更加快速高效的进行JVM的学习与秋招面试的备战…...

C#中的序列化和反序列化
序列化是指将对象转换为可存储或传输的格式,例如将对象转换为JSON字符串或字节流。反序列化则是将存储或传输的数据转换回对象的过程。这两个过程在数据持久化、数据交换以及与外部系统的通信中非常常见 把对象转换成josn字符串格式 这个过程就是序列化 josn字符…...
xcode常见设置
1、如何使用cmake构建archs为$(ARCHS_STANDARD)的xcode项目 在cmake中使用如下指令 set(CMAKE_OSX_ARCHITECTURES "$(ARCHS_STANDARD)") cmake - nomadli的博客 | nomadli Blog...

PG高可用学习@2
目录标题 一、Patroni 支持在同步复制下备库故障时自动降级为异步复制?参考依据1. PostgreSQL 官方文档2. Patroni 官方文档3. 高可用和容错设计原则 二、patroni 是如何检测备库故障的?1. 心跳机制2. 监控数据库进程状态3. 查询系统视图4. 复制延迟监测5. 网络连接…...

centos 8和centos 9 stream x64的区别
以下是 CentOS 8 与 CentOS Stream 9 的主要区别,从技术架构、更新策略到适用场景等维度进行对比: AI产品独立开发实战营 联系我了解 1. 定位与更新策略 特性CentOS 8CentOS Stream 9定位原为 RHEL 8 的免费稳定复刻版RHEL 9 的上游开发分支ÿ…...

C++基础学习记录—类
1、面向对象的三大特征:封装、继承、多态 2、类和对象 2.1、类的概念 类:类是一个抽象的概念,用于描述同一类对象的特点。 对象:根据类的概念所创造的实体。 类中包含属性和行为 属性:描述类的数据,一…...
云原生时代的后端开发:架构、工具与最佳实践
随着云计算的迅猛发展,云原生(Cloud Native)逐渐成为后端开发的主流趋势。云原生后端不仅能够提高应用的灵活性和可扩展性,还能显著优化开发和运维流程。本文将围绕云原生后端的关键概念、当前热门技术及最佳实践,帮助…...

ARM Cortex-M3/M4 权威指南 笔记【一】技术综述
一、Cortex-M3/M4 处理器的一般信息 1.1 处理器类型 ARM Cortex-M 为 32 位 RISC(精简指令集)处理器,其具有: 32位寄存器32位内部数据通路32位总线接口 除了 32 位数据,Cortex-M 处理器(以及其他任何 A…...

idea大量爆红问题解决
问题描述 在学习和工作中,idea是程序员不可缺少的一个工具,但是突然在有些时候就会出现大量爆红的问题,发现无法跳转,无论是关机重启或者是替换root都无法解决 就是如上所展示的问题,但是程序依然可以启动。 问题解决…...
【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15
缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下: struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...

基于FPGA的PID算法学习———实现PID比例控制算法
基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容:参考网站: PID算法控制 PID即:Proportional(比例)、Integral(积分&…...

【OSG学习笔记】Day 18: 碰撞检测与物理交互
物理引擎(Physics Engine) 物理引擎 是一种通过计算机模拟物理规律(如力学、碰撞、重力、流体动力学等)的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互,广泛应用于 游戏开发、动画制作、虚…...

工业安全零事故的智能守护者:一体化AI智能安防平台
前言: 通过AI视觉技术,为船厂提供全面的安全监控解决方案,涵盖交通违规检测、起重机轨道安全、非法入侵检测、盗窃防范、安全规范执行监控等多个方面,能够实现对应负责人反馈机制,并最终实现数据的统计报表。提升船厂…...

JavaScript 中的 ES|QL:利用 Apache Arrow 工具
作者:来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗?了解下一期 Elasticsearch Engineer 培训的时间吧! Elasticsearch 拥有众多新功能,助你为自己…...

MODBUS TCP转CANopen 技术赋能高效协同作业
在现代工业自动化领域,MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步,这两种通讯协议也正在被逐步融合,形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)
宇树机器人多姿态起立控制强化学习框架论文解析 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一) 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...
C# SqlSugar:依赖注入与仓储模式实践
C# SqlSugar:依赖注入与仓储模式实践 在 C# 的应用开发中,数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护,许多开发者会选择成熟的 ORM(对象关系映射)框架,SqlSugar 就是其中备受…...

C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。
1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj,再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...