iOS AES/CBC/CTR加解密以及AES-CMAC

news2025/2/12 1:20:47

感觉iOS自带的CryptoKit不好用,有个第三方库CryptoSwift还不错,好巧不巧,清理过Xcode缓存后死活下载不下来,当然也可以自己编译个Framework,但是偏偏不想用第三方库了,于是研究了一下,自带的CommonCrypto也可以达到项目需求。

代码主要包含以下算法:

AES128/CBC/NoPadding

AES128/CTR/NoPadding

AES-CMAC

import Foundation
import CommonCrypto

class AESUtil {
    
    private init(){}

    ///
    ///AES-CMAC
    ///
    static func CMAC(key: Data, data: Data) -> Data? {
        let blockSize = 16
        var subKey1 = Data(count: blockSize)
        var subKey2 = Data(count: blockSize)

        // Step 1: Generate subkeys
        guard generateSubKeys(key: key, subKey1: &subKey1, subKey2: &subKey2) else {
            return nil
        }

        // Step 2: Calculate the number of blocks
        let blockCount = (data.count + blockSize - 1) / blockSize

        // Step 3: Process each block
        var 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 = 16
        let 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 = 16
        var subKey = Data(count: 16)

        var overflow = false
        for i in (0..<blockSize).reversed() {
            let byte = block[i]
            let shiftedByte = byte << 1
            subKey[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 + kCCKeySizeAES128
        var buffer = Data(count: bufferLength)
        var numBytesEncrypted: size_t = 0
        
        let operation = isEncrypt ? kCCEncrypt : kCCDecrypt
        
        let cryptStatus: CCCryptorStatus = buffer.withUnsafeMutableBytes { (bufferPtr: UnsafeMutableRawBufferPointer) in
            key.withUnsafeBytes { (keyPtr: UnsafeRawBufferPointer) in
                iv.withUnsafeBytes { (ivPtr: UnsafeRawBufferPointer) in
                    data.withUnsafeBytes { (dataPtr: UnsafeRawBufferPointer) in
                        //调用加密函数
                        var modeSource = 0
                        if 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)"
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2296586.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2025年02月10日Github流行趋势

项目名称&#xff1a;dify 项目地址url&#xff1a;https://github.com/langgenius/dify项目语言&#xff1a;TypeScript历史star数&#xff1a;64707今日star数&#xff1a;376项目维护者&#xff1a;takatost, crazywoola, laipz8200, iamjoel, JohnJyong项目简介&#xff1a…

Ansible简单介绍及用法

一、简介 Ansible是一个简单的自动化运维管理工具&#xff0c;基于Python语言实现&#xff0c;由Paramiko和PyYAML两个关键模块构建&#xff0c;可用于自动化部署应用、配置、编排task(持续交付、无宕机更新等)。主版本大概每2个月发布一次。 Ansible与Saltstack最大的区别是…

渗透利器工具:Burp Suite 联动 XRAY 图形化工具.(主动扫描+被动扫描)

Burp Suite 联动 XRAY 图形化工具.&#xff08;主动扫描被动扫描&#xff09; Burp Suite 和 Xray 联合使用&#xff0c;能够将 Burp 的强大流量拦截与修改功能&#xff0c;与 Xray 的高效漏洞检测能力相结合&#xff0c;实现更全面、高效的网络安全测试&#xff0c;同时提升漏…

HTML-day1(学习自用)

目录 一、HTML介绍 二、常用的标签 1、各级标题&#xff08;h1-h6&#xff09; 2、段落标签&#xff08;p&#xff09; 3、文本容器&#xff08;span&#xff09; 4、图片标签&#xff08;img&#xff09; 5、超链接标签&#xff08;a&#xff09; 6、表格&#xff08;t…

Vue07

一、Vuex 概述 目标&#xff1a;明确Vuex是什么&#xff0c;应用场景以及优势 1.是什么 Vuex 是一个 Vue 的 状态管理工具&#xff0c;状态就是数据。 大白话&#xff1a;Vuex 是一个插件&#xff0c;可以管理 Vue 通用的数据 (多组件共享的数据)。例如&#xff1a;购物车数…

Godot开发框架探索#2

前言 距离上次发文又又又隔了很长一段时间。主要原因还是因为思绪在徘徊&#xff0c;最近纠结的点有以下几个&#xff1a;1.渴求一个稳定的Godot开发框架&#xff1b;2.要不要使用更轻量的开发框架&#xff0c;或者直接写引擎&#xff1b; 3.对自己想做的游戏品类拿不定主意。…

deepseek实现私有知识库

前言 之前写了如何本地部署deepseek&#xff0c;已经可以私有化问答了&#xff0c;本地搭建deepseek实操&#xff08;ollama搭建&#xff0c;docker管理&#xff0c;open-webui使用&#xff09; 其中我觉得最厉害的还是这个模型蒸馏&#xff0c;使我们可以用很低的代价使用大模…

【探索未来科技】2025年国际学术会议前瞻

【探索未来科技】2025年国际学术会议前瞻 【探索未来科技】2025年国际学术会议前瞻 文章目录 【探索未来科技】2025年国际学术会议前瞻前言1. 第四届电子信息工程、大数据与计算机技术国际学术会议&#xff08; EIBDCT 2025&#xff09;代码示例&#xff1a;机器学习中的线性回…

大模型基本原理(四)——如何武装ChatGPT

传统的LLM存在几个短板&#xff1a;编造事实、计算不准确、数据过时等&#xff0c;为了应对这几个问题&#xff0c;可以借助一些外部工具或数据把AI武装起来。 实现这一思路的框架包括RAG、PAL、ReAct。 1、RAG&#xff08;检索增强生成&#xff09; LLM生成的内容会受到训练…

开发完的小程序如何分包

好几次了&#xff0c;终于想起来写个笔记记一下 我最开始并不会给小程序分包&#xff0c;然后我就各种搜&#xff0c;发现讲的基本上都是开发之前的小程序分包&#xff0c;可是我都开发完要发布了&#xff0c;提示我说主包太大需要分包&#xff0c;所以我就不会了。。。 好了…

java配置api,vue网页调用api从oracle数据库读取数据

一、主入口文件 1&#xff1a;java后端端口号 2&#xff1a;数据库类型 和 数据库所在服务器ip地址 3&#xff1a;服务器用户名和密码 二、映射数据库表中的数据 resources/mapper/.xml文件 1&#xff1a;column后变量名是数据库中存储的变量名 property的值是column值的…

iOS三方登录 - Facebook登录

引言 在出海APP的开发中&#xff0c;集成主流社交平台的三方登录已成为必不可少的一环。Facebook 作为全球最大的社交网络平台之一&#xff0c;其提供的 Facebook 登录功能能够大大简化用户注册和登录流程&#xff0c;提高用户体验&#xff0c;减少流失率。对于开发者而言&…

机器学习 - 理解偏差-方差分解

为了避免过拟合&#xff0c;我们经常会在模型的拟合能力和复杂度之间进行权衡。拟合能力强的模型一般复杂度会比较高&#xff0c;容易导致过拟合。相反&#xff0c;如果限制模型的复杂度&#xff0c;降低其拟合能力&#xff0c;又可能会导致欠拟合。因此&#xff0c;如何在模型…

深度学习01 神经网络

目录 神经网络 ​感知器 感知器的定义 感知器的数学表达 感知器的局限性 多层感知器&#xff08;MLP, Multi-Layer Perceptron&#xff09; 多层感知器的定义 多层感知器的结构 多层感知器的优势 偏置 偏置的作用 偏置的数学表达 神经网络的构造 ​神经网络的基本…

自动化xpath定位元素(附几款浏览器xpath插件)

在 Web 自动化测试、数据采集、前端调试中&#xff0c;XPath 仍然是不可或缺的技能。虽然 CSS 选择器越来越强大&#xff0c;但面对复杂 DOM 结构时&#xff0c;XPath 仍然更具灵活性。因此&#xff0c;掌握 XPath&#xff0c;不仅能提高自动化测试的稳定性&#xff0c;还能在爬…

PromptSource官方文档翻译

目录 核心概念解析 提示模板&#xff08;Prompt Template&#xff09; P3数据集 安装指南 基础安装&#xff08;仅使用提示&#xff09; 开发环境安装&#xff08;需创建提示&#xff09; API使用详解 基本用法 子数据集处理 批量操作 提示创建流程 Web界面操作 手…

2025年软件测试五大趋势:AI、API安全、云测试等前沿实践

随着软件开发的不断进步&#xff0c;测试方法也在演变。企业需要紧跟新兴趋势&#xff0c;以提升软件质量、提高测试效率&#xff0c;并确保安全性&#xff0c;在竞争激烈的技术环境中保持领先地位。本文将深入探讨2025年最值得关注的五大软件测试趋势。 Parasoft下载https://…

js的DOM一遍过

一、获取元素 1.根据id获取 document.getElementById(id);2.根据标签名获取 使用 getElementsByTagName() 方法可以返回带有指定标签名的对象的集合。 document.getElementsByTagName(标签名);获取某个元素(父元素)内部所有指定标签名的子元素。 element.getElementsByTag…

Machine Learning:Introduction

文章目录 Machine LearningTrainingStep 1.Contract Function with Unknown ParametersStep 2.Define Loss from Training DataStep 3.Optimization Linear ModelPiecewise Linear CurveBeyond Piecewise Liner?FunctionLossOptimization Model Deformation Machine Learning …

Excel 笔记

实际问题记录 VBA脚本实现特殊的行转列 已知&#xff1a;位于同一Excel工作簿文件中的两个工作表&#xff1a;Sheet1、Sheet2。 问题&#xff1a;现要将Sheet2中的每一行&#xff0c;按Sheet1中的样子进行转置&#xff1a; Sheet2中每一行的黄色单元格&#xff0c;为列头。…