python实现AES加密解密

1. 前言
AES是一种对称加密,所谓对称加密就是加密与解密使用的秘钥是一个。

之前写过一片关于python AES加密解密的文章,但是这里面细节实在很多,这次我从 参数类型、加密模式、编码模式、补全模式、等等方面 系统的说明如何使用AES加密解密。

看文章不能急功近利,为了解决一个问题临时查到一个代码套用进去,或许可以迅速解决问题,但是遇到新的问题还需要再次查询,这种我认为还是比较浪费时间的。我相信看完认真看完这篇文章的你会大有收获。

2. 环境安装
pip uninstall crypto
pip uninstall pycryptodome
pip install pycryptodome

前面两个卸载命令是为了防止一些安装环境问题,具体请看文章

3.加密模式

 AES 加密最常用的模式就是 ECB模式 和 CBC 模式,当然还有很多其它模式,他们都属于AES加密。ECB模式和CBC 模式俩者区别就是 ECB 不需要 iv偏移量,而CBC需要。

4.AES加密使用参数

以下参数都是在python中使用的。

参数作用及数据类型
秘钥加密的时候用秘钥,解密的时候需要同样的秘钥才能解出来; 数据类型为bytes
明文需要加密的参数; 数据类型为bytes
模式aes 加密常用的有 ECB 和 CBC 模式(我只用了这两个模式,还有其他模式);数据类型为aes类内部的枚举量
iv 偏移量这个参数在 ECB 模式下不需要,在 CBC 模式下需要;数据类型为byte

下面简单的一个例子ECB模式加密解密 :

from Crypto.Cipher import AES

password = b'1234567812345678' #秘钥,b就是表示为bytes类型
text = b'abcdefghijklmnhi' #需要加密的内容,bytes类型
aes = AES.new(password,AES.MODE_ECB) #创建一个aes对象
# AES.MODE_ECB 表示模式是ECB模式
en_text = aes.encrypt(text) #加密明文
print("密文:",en_text) #加密明文,bytes类型
den_text = aes.decrypt(en_text) # 解密密文
print("明文:",den_text)

输出:

密文: b'WU\xe0\x0e\xa3\x87\x12\x95\\]O\xd7\xe3\xd4 )'
明文: b'abcdefghijklmnhi'

以上是针对ECB模式的加密解密,从这个例子中可以看出参数中有几个限制。

  1. 秘钥必须为16字节或者16字节的倍数的字节型数据。
  2. 明文必须为16字节或者16字节的倍数的字节型数据,如果不够16字节需要进行补全,关于补全规则,后面会在补全模式中具体介绍。

通过CBC模式例子:

from Crypto.Cipher import AES
password = b'1234567812345678' #秘钥,b就是表示为bytes类型
iv = b'1234567812345678' # iv偏移量,bytes类型
text = b'abcdefghijklmnhi' #需要加密的内容,bytes类型
aes = AES.new(password,AES.MODE_CBC,iv) #创建一个aes对象
# AES.MODE_CBC 表示模式是CBC模式
en_text = aes.encrypt(text) 
print("密文:",en_text) #加密明文,bytes类型
aes = AES.new(password,AES.MODE_CBC,iv) #CBC模式下解密需要重新创建一个aes对象
den_text = aes.decrypt(en_text)
print("明文:",den_text)

输出:

密文: b'\x93\x8bN!\xe7~>\xb0M\xba\x91\xab74;0'
明文: b'abcdefghijklmnhi'

通过上面CBC模式的例子,可以简单看出CBC模式与ECB模式的区别:AES.new() 解密和加密重新生成了aes对象,加密和解密不能调用同一个aes对象,否则会报错TypeError: decrypt() cannot be called after encrypt()。

总结:

1. 在Python中进行AES加密解密时,所传入的密文、明文、秘钥、iv偏移量、都需要是bytes(字节型)数据。python 在构建aes对象时也只能接受bytes类型数据。

2.当秘钥,iv偏移量,待加密的明文,字节长度不够16字节或者16字节倍数的时候需要进行补全。

3. CBC模式需要重新生成AES对象,为了防止这类错误,我写代码无论是什么模式都重新生成AES对象。


5.编码模式

前面说了,python中的 AES 加密解密,只能接受字节型(bytes)数据。而我们常见的 待加密的明文可能是中文,或者待解密的密文经过base64编码的,这种都需要先进行编码或者解码,然后才能用AES进行加密或解密。反正无论是什么情况,在python使用AES进行加密或者解密时,都需要先转换成bytes型数据。

我们以ECB模式针对中文明文进行加密解密举例:

from Crypto.Cipher import AES

password = b'1234567812345678' #秘钥,b就是表示为bytes类型
text = "好好学习天天向上".encode('gbk') #gbk编码,是1个中文字符对应2个字节,8个中文正好16字节
aes = AES.new(password,AES.MODE_ECB) #创建一个aes对象
# AES.MODE_ECB 表示模式是ECB模式
print(len(text))
en_text = aes.encrypt(text) #加密明文
print("密文:",en_text) #加密明文,bytes类型
den_text = aes.decrypt(en_text) # 解密密文
print("明文:",den_text.decode("gbk")) # 解密后同样需要进行解码

输出:

16
密文: b'=\xdd8k\x86\xed\xec\x17\x1f\xf7\xb2\x84~\x02\xc6C'
明文: 好好学习天天向上

对于中文明文,我们可以使用encode()函数进行编码,将字符串转换成bytes类型数据,而这里我选择gbk编码,是为了正好能满足16字节,utf8编码是一个中文字符对应3个字节。这里为了举例所以才选择使用gbk编码。

在解密后,同样是需要decode()函数进行解码的,将字节型数据转换回中文字符(字符串类型)。

现在我们来看另外一种情况,密文是经过base64编码的(这种也是非常常见的,很多网站也是这样使用的),我们用 http://tool.chacuo.net/cryptaes/ 这个网站举例子:

模式:ECB

密码: 1234567812345678

字符集:gbk编码

输出: base64

我们来写一个python 进行aes解密:

from Crypto.Cipher import AES
import base64

password = b'1234567812345678' 
aes = AES.new(password,AES.MODE_ECB) 
en_text = b"Pd04a4bt7Bcf97KEfgLGQw=="
en_text = base64.decodebytes(en_text) #将进行base64解码,返回值依然是bytes
den_text = aes.decrypt(en_text)
print("明文:",den_text.decode("gbk")) 

输出:

明文: 好好学习天天向上

这里的 b"Pd04a4bt7Bcf97KEfgLGQw==" 是一个bytes数据, 如果你传递的是一个字符串,你可以直接使用 encode()函数 将其转换为 bytes类型数据。

from Crypto.Cipher import AES
import base64

password = b'1234567812345678' 
aes = AES.new(password,AES.MODE_ECB) 
en_text = "Pd04a4bt7Bcf97KEfgLGQw==".encode() #将字符串转换成bytes数据
en_text = base64.decodebytes(en_text) #将进行base64解码,参数为bytes数据,返回值依然是bytes
den_text = aes.decrypt(en_text) 
print("明文:",den_text.decode("gbk")) 

因为无论是 utf8 和 gbk 编码,针对英文字符编码都是一个字符对应一个字节,所以这里**encode()**函数主要作用就是转换成bytes数据,然后使用base64进行解码。

hexstr,base64编码解码例子:

import base64
import binascii
data = "hello".encode()
data = base64.b64encode(data)
print("base64编码:",data)
data = base64.b64decode(data)
print("base64解码:",data)
data = binascii.b2a_hex(data)
print("hexstr编码:",data)
data = binascii.a2b_hex(data)
print("hexstr解码:",data)

输出:

base64编码: b'aGVsbG8='
base64解码: b'hello'
hexstr编码: b'68656c6c6f'
hexstr解码: b'hello'

这里要说明一下,有一些AES加密,所用的秘钥,或者IV向量是通过 base64编码或者 hexstr编码后的。针对这种,首先要进行的就是进行解码,都转换回 bytes数据,再次强调,python实现 AES加密解密传递的参数都是 bytes(字节型) 数据。

另外,我记得之前的 pycryptodome库,传递IV向量时,和明文时可以直接使用字符串类型数据,不过现在新的版本都必须为 字节型数据了,可能是为了统一好记。

6.填充模式

前面我使用秘钥,还有明文,包括IV向量,都是固定16字节,也就是数据块对齐了。而填充模式就是为了解决数据块不对齐的问题,使用什么字符进行填充就对应着不同的填充模式

AES补全模式常见有以下几种:

模式意义
ZeroPadding用b’\x00’进行填充,这里的0可不是字符串0,而是字节型数据的b’\x00’
PKCS7Padding当需要N个数据才能对齐时,填充字节型数据为N、并且填充N个
PKCS5Padding与PKCS7Padding相同,在AES加密解密填充方面我没感到什么区别
no padding当为16字节数据时候,可以不进行填充,而不够16字节数据时同ZeroPadding一样

这里有一个细节问题,我发现很多文章说的也是不对的。

ZeroPadding填充模式的意义:很多文章解释是当为16字节倍数时就不填充,然后当不够16字节倍数时再用字节数据0填充,这个解释是不对的,这解释应该是no padding的,而ZeroPadding是不管数据是否对其,都进行填充,直到填充到下一次对齐为止,也就是说即使你够了16字节数据,它会继续填充16字节的0,然后一共数据就是32字节。

这里可能会有一个疑问,为什么是16字节 ,其实这个是 数据块的大小,网站上也有对应设置,网站上对应的叫128位,也就是16字节对齐,当然也有192位(24字节),256位(32字节)。

本文在这个解释之后,后面就说数据块对齐问题了,而不会再说16字节倍数了。

除了no padding 填充模式,剩下的填充模式都会填充到下一次数据块对齐为止,而不会出现不填充的问题。

PKCS7Padding和 PKCS5Padding需要填充字节对应表:

明文长度值(mod 16)添加的填充字节数每个填充字节的值
0160x10
1150x0F
2140x0E
3130X0D
4120x0C
5110x0B
6100x0A
790x09
880x08
970x08
1060x07
1150x06
1240x05
1330x04
1420x03
1510x01

这里可以看到,当明文长度值已经对齐时(mod 16 = 0),还是需要进行填充,并且填充16个字节值为0x10。ZeroPadding填充逻辑也是类似的,只不过填充的字节值都为0x00,在python表示成 b'\x00'。

填充完毕后,就可以使用 AES进行加密解密了,当然解密后,也需要剔除填充的数据,无奈Python这些步骤需要自己实现(如果有这样的库还请评论指出)。

7.Python的完整实现:
from Crypto.Cipher import AES
import base64
import binascii

# 数据类
class MData():
    def __init__(self, data = b"",characterSet='utf-8'):
        # data肯定为bytes
        self.data = data
        self.characterSet = characterSet
  
    def saveData(self,FileName):
        with open(FileName,'wb') as f:
            f.write(self.data)

    def fromString(self,data):
        self.data = data.encode(self.characterSet)
        return self.data

    def fromBase64(self,data):
        self.data = base64.b64decode(data.encode(self.characterSet))
        return self.data

    def fromHexStr(self,data):
        self.data = binascii.a2b_hex(data)
        return self.data

    def toString(self):
        return self.data.decode(self.characterSet)

    def toBase64(self):
        return base64.b64encode(self.data).decode()

    def toHexStr(self):
        return binascii.b2a_hex(self.data).decode()

    def toBytes(self):
        return self.data

    def __str__(self):
        try:
            return self.toString()
        except Exception:
            return self.toBase64()


### 封装类
class AEScryptor():
    def __init__(self,key,mode,iv = '',paddingMode= "NoPadding",characterSet ="utf-8"):
        '''
        构建一个AES对象
        key: 秘钥,字节型数据
        mode: 使用模式,只提供两种,AES.MODE_CBC, AES.MODE_ECB
        iv: iv偏移量,字节型数据
        paddingMode: 填充模式,默认为NoPadding, 可选NoPadding,ZeroPadding,PKCS5Padding,PKCS7Padding
        characterSet: 字符集编码
        '''
        self.key = key
        self.mode = mode
        self.iv = iv
        self.characterSet = characterSet
        self.paddingMode = paddingMode
        self.data = ""

    def __ZeroPadding(self,data):
        data += b'\x00'
        while len(data) % 16 != 0:
            data += b'\x00'
        return data

    def __StripZeroPadding(self,data):
        data = data[:-1]
        while len(data) % 16 != 0:
            data = data.rstrip(b'\x00')
            if data[-1] != b"\x00":
                break
        return data

    def __PKCS5_7Padding(self,data):
        needSize = 16-len(data) % 16
        if needSize == 0:
            needSize = 16
        return data + needSize.to_bytes(1,'little')*needSize

    def __StripPKCS5_7Padding(self,data):
        paddingSize = data[-1]
        return data.rstrip(paddingSize.to_bytes(1,'little'))

    def __paddingData(self,data):
        if self.paddingMode == "NoPadding":
            if len(data) % 16 == 0:
                return data
            else:
                return self.__ZeroPadding(data)
        elif self.paddingMode == "ZeroPadding":
            return self.__ZeroPadding(data)
        elif self.paddingMode == "PKCS5Padding" or self.paddingMode == "PKCS7Padding":
            return self.__PKCS5_7Padding(data)
        else:
            print("不支持Padding")

    def __stripPaddingData(self,data):
        if self.paddingMode == "NoPadding":
            return self.__StripZeroPadding(data)
        elif self.paddingMode == "ZeroPadding":
            return self.__StripZeroPadding(data)

        elif self.paddingMode == "PKCS5Padding" or self.paddingMode == "PKCS7Padding":
            return self.__StripPKCS5_7Padding(data)
        else:
            print("不支持Padding")

    def setCharacterSet(self,characterSet):
        '''
        设置字符集编码
        characterSet: 字符集编码
        '''
        self.characterSet = characterSet

    def setPaddingMode(self,mode):
        '''
        设置填充模式
        mode: 可选NoPadding,ZeroPadding,PKCS5Padding,PKCS7Padding
        '''
        self.paddingMode = mode

    def decryptFromBase64(self,entext):
        '''
        从base64编码字符串编码进行AES解密
        entext: 数据类型str
        '''
        mData = MData(characterSet=self.characterSet)
        self.data = mData.fromBase64(entext)
        return self.__decrypt()

    def decryptFromHexStr(self,entext):
        '''
        从hexstr编码字符串编码进行AES解密
        entext: 数据类型str
        '''
        mData = MData(characterSet=self.characterSet)
        self.data = mData.fromHexStr(entext)
        return self.__decrypt()

    def decryptFromString(self,entext):
        '''
        从字符串进行AES解密
        entext: 数据类型str
        '''
        mData = MData(characterSet=self.characterSet)
        self.data = mData.fromString(entext)
        return self.__decrypt()

    def decryptFromBytes(self,entext):
        '''
        从二进制进行AES解密
        entext: 数据类型bytes
        '''
        self.data = entext
        return self.__decrypt()

    def encryptFromString(self,data):
        '''
        对字符串进行AES加密
        data: 待加密字符串,数据类型为str
        '''
        self.data = data.encode(self.characterSet)
        return self.__encrypt()

    def __encrypt(self):
        if self.mode == AES.MODE_CBC:
            aes = AES.new(self.key,self.mode,self.iv) 
        elif self.mode == AES.MODE_ECB:
            aes = AES.new(self.key,self.mode) 
        else:
            print("不支持这种模式")  
            return           

        data = self.__paddingData(self.data)
        enData = aes.encrypt(data)
        return MData(enData)

    def __decrypt(self):
        if self.mode == AES.MODE_CBC:
            aes = AES.new(self.key,self.mode,self.iv) 
        elif self.mode == AES.MODE_ECB:
            aes = AES.new(self.key,self.mode) 
        else:
            print("不支持这种模式")  
            return           
        data = aes.decrypt(self.data)
        mData = MData(self.__stripPaddingData(data),characterSet=self.characterSet)
        return mData


if __name__ == '__main__':
    key = b"1234567812345678"
    iv =  b"0000000000000000"
    aes = AEScryptor(key,AES.MODE_CBC,iv,paddingMode= "ZeroPadding",characterSet='utf-8')
    
    data = "好好学习"
    rData = aes.encryptFromString(data)
    print("密文:",rData.toBase64())
    rData = aes.decryptFromBase64(rData.toBase64())
    print("明文:",rData)

我简单的对其进行了封装,加密和解密返回的数据类型可以使用toBase64(),toHexStr() 进行编码。另外我没有对key和iv进行补全,可以使用MData类自己实现,更多详细使用可以通过源码中注释了解。

文章出自:

原文链接:https://blog.csdn.net/chouzhou9701/article/details/122019967

csdn上发现的一位大佬写,怕找不到了就完全复制他是文章

==================================================

在使用requests库中的POST方法时传参是  

post 传json时,这里的是传python中的dict 而不是dict做dumps后的数据,这里是坑,测试了几次

def getToken():
    url = f"{IP}:{PORT}/xxxxx
    pubkey = getPublickey()

    rsaPassword = get_encrypt_password(pubkey, PASSWORD)
    data = {
        "grant_type": "password",
        "username": USERNAME,
        "password": rsaPassword,
        "client_id": CLIENT_ID,
        "client_secret": CLIENT_SECRET,
        "public_key": pubkey
    }
    # jdata = json.dumps(data)
    
    # post 传json时,这里的是传python中的dict 而不是dict做dumps后的数据,这里是坑,测试了几次
    res = requests.post(url=url, json=data, verify=False,)
    return res.json()

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

存储xss实现获取cookie(本地实战)

实战更能体验收获&#xff01;&#xff01;&#xff01; 环境准备&#xff1a; 1.phpstudy 2.dvwa靶场 实战 首先我们在phpstudy指定的localhost网站目录下编写一个xss.php文件&#xff0c;内容如下&#xff1a; <?php $cookie $_GET[cookie]; $ip getenv (REMOTE_…

零基础小白到底适不适合学鸿蒙,请看完这篇再决定吧~

随着华为鸿蒙系统的问世&#xff0c;不少技术小白在是否学习鸿蒙的问题上犹豫不决。鸿蒙作为华为自主研发的操作系统&#xff0c;拥有许多独特的技术优势和市场前景。但对于小白来说&#xff0c;是否值得投入时间和精力去学习鸿蒙开发呢&#xff1f; 1.鸿蒙系统开发&#xff1…

Java8 - LocalDateTime时间日期类使用详解

&#x1f3f7;️个人主页&#xff1a;牵着猫散步的鼠鼠 &#x1f3f7;️系列专栏&#xff1a;Java全栈-专栏 &#x1f3f7;️个人学习笔记&#xff0c;若有缺误&#xff0c;欢迎评论区指正 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&…

云南经贸Day01

day01 一. VMware创建虚拟机二.VMware安装Linux三 虚拟机网络配置1. 查看网络信息2. 修改网络IP 四. 虚拟机操作管理1. 通过VMware为虚拟机拍摄快照2. VMware 为虚拟机执行克隆 五. Xshell的安装和使用 一. VMware创建虚拟机 二.VMware安装Linux 清华大学镜像源网址: https://m…

南方电网的能源棋局上,蔚来换电扮演什么角色?

2 月 26 日&#xff0c;南网储能科技与蔚来能源签署协议&#xff0c;将充换电站、储能站、可调负载等聚合资源连接到虚拟电厂平台&#xff0c;推动换电站作为分布式储能在虚拟电厂项目上的应用。 蔚来换电站是国内首个智慧微电网型分布式换电设施&#xff0c;可透过换电订单预…

【C++ map和set】

文章目录 map和set序列式容器和关联式容器键值对setset的主要操作 mapmap主要操作 multiset和multimap map和set 序列式容器和关联式容器 之前我们接触的vector,list,deque等&#xff0c;这些容器统称为序列式容器&#xff0c;其底层为线性序列的的数据结构&#xff0c;里面存…

面试数据库篇(mysql)- 08事务

原理 事务是一组操作的集合,它是一个不可分割的工作单位,事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求,即这些操作要么同时成功,要么同时失败。 ACID是什么?可以详细说一下吗? 原子性(Atomicity):事务是不可分割的最小操作单元,要么全部成功,要么全…

栈的概念结构和实现

文章目录 一、什么是栈二、栈的实现三、实现栈所需的函数四、完整栈的展现五、栈的思维导图 一、什么是栈 栈是一种特殊的线性表&#xff0c;只允许在固定的一端进行插入和删除操作。进行插入和删除的一段叫做栈顶&#xff0c;另一段叫做栈底 压栈&#xff1a;插入数据 出栈&a…

ShardingSphere 5.x 系列【18】自定义类分片算法

有道无术,术尚可求,有术无道,止于术。 本系列Spring Boot 版本 3.1.0 本系列ShardingSphere 版本 5.4.0 源码地址:https://gitee.com/pearl-organization/study-sharding-sphere-demo 文章目录 1. 概述2. ClassBasedShardingAlgorithm3. 案例演示3.1 STANDARD3.2 COMPLEX…

【递归搜索回溯专栏】前言与本专栏介绍

本专栏内容为&#xff1a;递归&#xff0c;搜索与回溯算法专栏。 通过本专栏的深入学习&#xff0c;你可以了解并掌握算法。 &#x1f493;博主csdn个人主页&#xff1a;小小unicorn ⏩专栏分类&#xff1a;递归搜索回溯专栏 &#x1f69a;代码仓库&#xff1a;小小unicorn的代…

视频学习胜过读书吗

现在&#xff0c;网上的课程视频和讲座视频&#xff0c;越来越多。同样的内容&#xff0c;可以读书学习&#xff0c;也可以视频学习&#xff0c;大家喜欢哪一种&#xff1f; 我比较喜欢读书&#xff0c;实在没耐心视频学习。 书籍只要随手一翻&#xff0c;就知道大概的内容了&…

[Android View] 可绘制形状 (Shape Xml)

一切以官方文档为主 官方文档https://developer.android.com/guide/topics/resources/drawable-resource?hlzh-cn#Shape 什么是可绘制形状 可以理解为用xml文件来描述一个简单的Drawable图形&#xff0c;比如说以下这段xml就可以用来描述一个白色的圆形&#xff1a; <?…

存储过程基本了解

文章目录 介绍存储过程示例1. 目的2. 输入参数3. 输出参数4. 执行逻辑5. 返回值6. 示例用法7. 注意事项 存储过程的关键字有哪些简单实操 介绍 存储过程是一组预编译的SQL语句&#xff0c;以及流程控制语句&#xff0c;封装在数据库服务器中并可以被重复调用。它们可以接收参数…

浅析扩散模型与图像生成【应用篇】(四)——Palette

4. Palette: Image-to-Image Diffusion Models 该文提出一种基于扩散模型的通用图像转换&#xff08;Image-to-Image Translation&#xff09;模型——Palette&#xff0c;可用于图像着色&#xff0c;图像修复&#xff0c;图像补全和JPEG图像恢复等多种转换任务。Palette是一种…

Harbor高可用(haproxy和keepalived)

Harbor高可用&#xff08;haproxy和keepalived&#xff09; 文章目录 Harbor高可用&#xff08;haproxy和keepalived&#xff09;1.Harbor高可用集群部署架构1.1 主机初始化1.1.1 设置网卡名和ip地址1.1.2 设置主机名1.1.3 配置镜像源1.1.4 关闭防火墙1.1.5 禁用SELinux1.1.6 设…

Linux Seccomp 简介

文章目录 一、简介二、架构三、Original/Strict Mode四、Seccomp-bpf五、seccomp系统调用六、Linux Capabilities and Seccomp6.1 Linux Capabilities6.2 Linux Seccomp 参考资料 一、简介 Seccomp&#xff08;secure computing&#xff09;是Linux内核中的一项计算机安全功能…

HTTPS是什么,详解它的加密过程

目录 1.前言 2.两种加密解密方式 2.1对称加密 2.2非对称加密 3.HTTPS的加密过程 3.1针对明文的对称加密 3.2针对密钥的非对称加密 3.3证书的作用 1.前言 我们知道HTTP协议是超文本传输协议,它被广泛的应用在客户端服务器上,用来传输文字,图片,视频,js,html等.但是这种传…

DataGrip的MySQL数据导出和导入操作指南

场景描述 将开发环境的数据&#xff0c;复制一份到本地&#xff0c;进行本地连接开发工作&#xff0c;避免组内其他开发人员的干扰。假若你的电脑上只安装了DataGrip和MySQL环境&#xff0c;本篇指南就是你所需要的。 一、导出dump数据 将开发环境的数据和结构导出一份到本地…

嵌入式中回调函数的实现方法

一、什么是回调函数 1.1、回调函数的定义和基本概念 回调函数是一种特殊的函数&#xff0c;它作为参数传递给另一个函数&#xff0c;并在被调用函数执行完毕后被调用。回调函数通常用于事件处理、异步编程和处理各种操作系统和框架的API。 基本概念&#xff1a; 回调&#xf…

WSL2部署RV1126 SDK编译环境

1 下载RV1126 SDK 在 Firefly | 让科技更简单&#xff0c;让生活更智能 下载REPO_SDK 这里将SDK下载到了F:\SDK 2 解压SDK到WSL2 tar -xvf /mnt/f/SDK/rv1126_rv1109_linux_release_20211022.tgz 3 编译依赖安装 gcc、g版本依赖安装 sudo apt-get install lib32gcc-7-dev g-7 l…
最新文章