单片机:实现国密SM2算法(完整源码)
单片机:实现国密SM2算法(完整源码)
单片机实现国密SM2算法项目详解
目录
-
相关理论与知识背景
3.1 国密SM2算法概述
3.2 椭圆曲线密码学基础
3.3 SM2算法的主要功能与流程
3.4 国密标准与应用场景 -
硬件设计与电路连接
4.1 平台选型与开发环境
4.2 单片机硬件架构概述
4.3 国密SM2算法实现对硬件资源要求
4.4 外设接口与调试接口设计
4.5 整体电路原理图与PCB布局建议 -
软件实现方案
5.1 系统总体架构设计
5.2 SM2算法软件实现流程
5.3 算法各模块功能解析
5.4 国密SM2密钥生成、加密、解密与签名验证流程
5.5 任务调度与中断管理
1. 引言
随着信息安全需求的日益增强和我国国密标准的推广,国密SM2算法已成为我国自主研发的椭圆曲线密码算法的重要组成部分。SM2算法主要用于公钥密码体系中的数字签名、密钥交换和公钥加密,其安全性和高效性在金融、政府及工业控制等领域有着广泛应用。利用单片机实现国密SM2算法,不仅能够为嵌入式安全通信提供有力支持,而且能够在低成本、低功耗的设备上实现复杂密码运算,推动国产密码算法在嵌入式系统中的普及和应用。
本文将详细介绍如何利用单片机实现国密SM2算法。从理论基础、算法原理、硬件设计、电路连接、软件实现、完整代码实现(代码整合到一起且附有非常详细的注释)、代码解读、测试调试到项目总结与展望,进行全方位解析,帮助读者深入理解SM2算法的核心技术和实现方法,为实际工程项目中的安全通信提供宝贵经验和参考依据。
2. 项目概述
2.1 项目背景
随着互联网和物联网的发展,数据传输和通信安全性越来越受到关注。国密SM2算法作为我国自主研发的椭圆曲线密码算法,具有高安全性和运算效率,广泛应用于金融、政府及工业控制系统中。然而,在资源受限的嵌入式设备中,实现复杂的SM2算法需要充分考虑算法运算、内存占用、功耗及响应速度等问题。利用单片机实现SM2算法既能满足安全需求,也能降低系统成本和功耗,是实现国产密码算法嵌入式应用的关键技术之一。
2.2 项目目的与意义
本项目旨在利用单片机实现国密SM2算法,主要功能包括:
-
密钥生成:实现SM2算法中的公私钥生成,并存储于单片机内部或外部存储器中。
-
数字签名:实现SM2数字签名算法,对数据进行签名,确保数据完整性和身份认证。
-
签名验证:实现签名验证功能,确保通信双方的数据安全。
-
加密与解密:支持公钥加密和私钥解密,保证敏感数据在传输过程中的机密性。
-
系统调试与通信:通过UART或其他通信接口实现双机通信,支持加密数据传输和远程监控。
项目意义在于:
-
帮助开发者深入理解国密SM2算法原理及其在椭圆曲线密码学中的应用;
-
掌握单片机在资源受限环境下实现复杂密码算法的技术方法;
-
为实际工程中实现国产密码算法的嵌入式安全通信提供完整的解决方案;
-
推动国密算法在嵌入式系统中的普及与应用,保障数据传输的安全性与可靠性。
3. 相关理论与知识背景
3.1 国密SM2算法概述
国密SM2算法是一种基于椭圆曲线密码学(ECC)的公钥密码算法,由中国国家密码管理局推荐并应用于多种安全领域。SM2算法主要包括数字签名、密钥交换和公钥加密三大功能,其安全性基于椭圆曲线离散对数问题。SM2算法在安全性、密钥长度和运算效率之间达到了较好的平衡,适合在计算资源有限的嵌入式系统中使用。
3.2 椭圆曲线密码学基础
椭圆曲线密码学(ECC)是一种基于椭圆曲线数学理论的公钥密码体系,其核心在于椭圆曲线离散对数问题。ECC具有以下优点:
-
高安全性:相较于RSA,ECC在相同安全级别下所需密钥长度更短。
-
运算高效:较短的密钥长度使得加密、解密、签名及验证运算速度更快,适合嵌入式系统。
-
灵活性强:适用于数字签名、密钥交换和加密解密等多种应用场景。
国密SM2算法即是基于ECC的具体实现,其主要参数(如椭圆曲线参数、基点和阶)均按照国密标准制定。
3.3 SM2算法的主要功能与流程
SM2算法主要包括:
-
密钥生成:利用椭圆曲线参数生成公私钥对,公钥可公开,私钥必须保密。
-
数字签名:使用私钥对数据摘要进行签名,生成数字签名,确保数据完整性和不可否认性。
-
签名验证:使用公钥对数字签名进行验证,确认数据真实性。
-
公钥加密与私钥解密:利用接收方的公钥对数据进行加密,发送方利用私钥解密,实现数据机密传输。
算法流程中涉及大量椭圆曲线上的加法与数乘运算,其运算复杂度较高,需要高效的算法和数据结构进行实现。
3.4 国密标准与应用场景
国密SM2算法作为我国自主研发的密码算法,广泛应用于:
-
金融支付:用于数字签名与加密,确保交易安全。
-
政府安全:用于电子政务、身份认证及数据加密。
-
工业控制:用于设备通信加密及数据完整性验证。
-
智能终端:在嵌入式设备中实现安全数据传输和身份验证。
掌握SM2算法的原理和实现方法,对构建安全、可靠的嵌入式系统具有重要意义。
3.5 单片机在SM2算法中的应用
在嵌入式系统中实现SM2算法,需要考虑:
-
运算资源:SM2算法涉及大整数运算、椭圆曲线点乘等,要求单片机具有足够的计算能力或配合硬件加速模块。
-
存储资源:密钥、字库及中间运算数据需要较大存储空间,需优化内存使用。
-
软件优化:通过算法优化、循环展开和定点运算等手段降低浮点运算消耗,确保系统实时响应。
-
通信接口:通过UART或SPI实现双机通信,传输SM2算法计算结果或控制指令。
本项目将在单片机平台上实现SM2算法的核心模块,为实际嵌入式安全通信提供示例。
4. 硬件设计与电路连接
4.1 平台选型与开发环境
本项目可采用多种单片机平台,如51系列、STC系列、AVR、STM32等。考虑到成本、功耗和开发难度,此处以51系列单片机(例如AT89C52或STC89C52)为例。
开发环境推荐使用Keil µVision进行代码编写、编译与仿真调试。
硬件平台主要包括:
-
主控单片机:具备足够的运算能力与内存,支持定时器、UART、GPIO和必要的乘法器或硬件加速模块(若有)。
-
外部存储器:可选用EEPROM或Flash存储SM2所需的密钥和中间数据。
-
调试接口:UART用于调试输出及双机通信,确保SM2算法执行状态的实时监控。
4.2 SM2算法实现对硬件资源要求
SM2算法在嵌入式系统中的实现需要考虑:
-
大整数运算:SM2涉及大整数模运算和椭圆曲线点乘运算,需要优化算法以适应单片机资源限制。
-
内存管理:密钥和中间数据存储需要较大内存,采用定点运算和数据压缩技术可降低存储压力。
-
硬件加速:部分单片机支持硬件乘法器或专用加速器,利用这些资源可以大大提高SM2算法运算效率。
4.3 外设接口与调试接口设计
设计中还需规划好外设接口:
-
UART接口:用于与PC或其他单片机进行数据通信与调试,传输SM2算法的计算结果及状态信息。
-
SPI/I²C接口:若需要外部存储器存储密钥或字库数据,可利用SPI或I²C接口与EEPROM/Flash通信。
-
LED或LCD显示:用于实时显示SM2算法运行状态或计算结果,为用户提供直观反馈。
4.4 PCB布局与电源管理
电源和PCB布局设计是保证系统稳定性的重要环节:
-
稳压电源:采用7805稳压芯片或DC-DC转换器输出稳定5V,为单片机和外设供电。
-
滤波设计:在电源入口及各模块供电处加入滤波电容,降低噪声对SM2算法计算的影响。
-
PCB布局:合理设计信号走线、地平面和屏蔽,确保大整数运算和高速数据传输不受干扰。
5. 软件实现方案
5.1 系统总体架构设计
软件整体架构主要分为以下几个模块:
-
系统初始化模块
-
初始化系统时钟、定时器、UART、GPIO和必要的硬件加速模块(如乘法器)。
-
-
SM2核心算法模块
-
实现SM2密钥生成、数字签名、签名验证以及加密解密等核心算法,包含大整数运算、椭圆曲线点乘和模运算。
-
采用定点数运算和软件优化策略,降低浮点运算开销,确保算法在单片机上的高效运行。
-
-
数据存储与管理模块
-
设计密钥存储和中间数据管理策略,利用内部Flash或外部EEPROM存储SM2所需数据。
-
实现字库和密钥查找接口,确保数据快速加载与使用。
-
-
双机通信模块
-
封装UART通信函数,实现数据帧格式的封装、发送与接收,支持双机通信和远程监控。
-
-
任务调度与中断管理模块
-
利用定时器中断实现多任务调度,协调SM2算法运算、数据通信与系统调试等任务。
-
5.2 SM2算法软件实现流程
SM2算法主要流程包括:
-
密钥生成:根据椭圆曲线参数和随机数生成私钥,计算公钥。
-
数字签名:对待签名数据进行哈希处理,利用私钥对数据摘要进行签名,生成签名值(r, s)。
-
签名验证:利用公钥对签名进行验证,确保数据的完整性和身份认证。
-
加密解密:利用接收方公钥对数据加密,接收方使用私钥解密,实现数据机密传输。
软件实现时,需要对大整数及模运算进行优化,采用定点数运算减少计算量,并采用循环展开和优化算法提高运算效率。
5.3 算法各模块功能解析
-
大整数运算模块:实现大整数的加减、乘法、除法及模运算,为SM2算法提供基本运算支持。
-
椭圆曲线运算模块:实现椭圆曲线上的点加法、点乘运算,作为密钥生成和签名验证的核心。
-
哈希算法模块:实现国密SM3等哈希函数,对输入数据生成固定长度数据摘要。
-
SM2签名与验证模块:结合大整数和椭圆曲线运算实现签名生成和验证,确保算法正确性。
-
加密与解密模块:实现基于公钥加密和私钥解密的算法逻辑,保护数据传输的机密性。
5.4 双机通信协议设计与实现
利用UART实现双机通信,关键点包括:
-
数据帧格式:设计统一的数据帧格式,包含起始位、数据长度、数据内容及校验码,确保数据传输准确。
-
发送与接收函数:封装UART发送和接收函数,实现双机间的数据交换。
-
错误检测与重传:采用简单的奇偶校验或CRC校验机制检测传输错误,并在必要时进行重传。
5.5 任务调度与中断管理
任务调度与中断管理确保系统各模块实时高效运行:
-
定时器中断:配置定时器中断用于控制SM2算法运算、数据采集与显示刷新,保证系统按预定周期执行任务。
-
捕获中断:若有需要,利用外部中断捕获数据,实现异步数据处理。
-
主循环调度:在主循环中不断调用SM2算法、通信、显示及用户交互模块,协调各功能模块工作,确保系统整体实时响应。
6. 完整代码实现
6.1 整合代码及详细注释
下面给出基于51单片机实现国密SM2算法的整合代码示例。代码中整合了系统初始化、SM2核心算法模块(密钥生成、数字签名与验证、加密解密)、大整数运算、椭圆曲线运算、哈希函数(SM3)及UART双机通信等功能。所有代码均附有非常详细的注释,便于读者理解每个模块的作用及实现原理。注意:由于SM2算法涉及复杂数学运算,部分函数仅为简化示例,实际项目中需使用高效算法和数据结构进行实现,且部分硬件相关配置需依据具体单片机型号调整。
/*
* 单片机实现国密SM2算法项目
* 作者:Katie
* 时间:2025-03-29
*
* 项目描述:
* 本项目利用51单片机实现国密SM2算法,主要包括密钥生成、数字签名与验证、
* 以及公钥加密与私钥解密等功能。系统通过UART接口实现双机通信,
* 将SM2算法运算结果和状态信息传输给另一台单片机进行进一步处理或显示。
*
* 主要功能:
* 1. SM2密钥生成:生成公钥和私钥,并存储于单片机内部存储器中。
* 2. 数字签名:对待签名数据生成数字签名(r, s)。
* 3. 签名验证:利用公钥对数字签名进行验证,确保数据完整性。
* 4. 加密与解密:实现基于公钥加密和私钥解密的数据传输。
* 5. 双机通信:通过UART实现数据帧传输和双机之间的SM2算法结果交换。
*
* 系统架构:
* 1. 系统初始化:初始化系统时钟、定时器、UART、GPIO等外设,并配置中断。
* 2. SM2核心算法模块:实现大整数运算、椭圆曲线点运算、SM3哈希及SM2签名和加解密流程。
* 3. 数据通信模块:封装UART通信函数,实现数据的发送与接收。
* 4. 任务调度模块:利用主循环和定时器中断协调SM2算法运算与双机通信任务。
*
* 以下代码为整合实现,所有模块均附有详细注释,便于后续扩展和优化。
*/
#include <reg51.h>
#include <stdio.h>
#include <string.h>
#include <math.h> // 若支持数学函数
/*************************************************
* 宏定义与全局变量
*************************************************/
#define CRYSTAL_FREQ 12000000UL // 12MHz晶振
#define UART_BAUD 9600
#define TH1_INIT (256 - (CRYSTAL_FREQ/12/32/UART_BAUD))
// 定时器、延时相关宏
#define TIMER0_RELOAD (256 - (CRYSTAL_FREQ/12/1000)) // 定时器0 1ms中断
// SM2算法相关参数(示例参数,实际根据国密标准设定)
#define SM2_P 0xFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFFUL
#define SM2_A 0xFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFCUL
#define SM2_B 0x28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93UL
#define SM2_N 0xFFFFFFFEFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123UL
// 注意:实际SM2参数为大整数,此处仅为示例占位
// SM2密钥数据结构(简化示例)
unsigned char privateKey[32]; // 32字节私钥
unsigned char publicKey[64]; // 64字节公钥(x、y各32字节)
// 模拟待签名数据
unsigned char message[] = "Hello SM2";
// 双机通信缓冲区(通过UART传输SM2运算结果)
#define UART_BUFFER_SIZE 128
unsigned char uartBuffer[UART_BUFFER_SIZE];
/*************************************************
* 大整数及椭圆曲线运算函数(简化示例)
* 实际实现需采用高效大整数运算库,此处仅为示例占位函数
*************************************************/
// 大整数加法、乘法、模运算等函数需要实现
// 以下函数仅为示例接口,不包含实际运算逻辑
void BigInt_Add(unsigned char *a, unsigned char *b, unsigned char *result) { /* ... */ }
void BigInt_Mul(unsigned char *a, unsigned char *b, unsigned char *result) { /* ... */ }
void BigInt_Mod(unsigned char *a, unsigned char *mod, unsigned char *result) { /* ... */ }
void EC_Point_Mul(unsigned char *k, unsigned char *point, unsigned char *result) { /* ... */ }
/*************************************************
* SM3哈希函数(简化示例)
* 实际中应实现国密SM3哈希算法,此处仅为示例接口
*************************************************/
void SM3_Hash(unsigned char *data, unsigned int len, unsigned char *hash)
{
// 示例:返回固定值作为哈希值
memset(hash, 0xAA, 32);
}
/*************************************************
* SM2密钥生成函数(简化示例)
* 利用随机数生成私钥,并计算对应公钥
*************************************************/
void SM2_KeyGeneration(void)
{
// 实际实现中应调用随机数函数生成32字节私钥
// 此处简化示例,私钥固定为全0x01
memset(privateKey, 0x01, 32);
// 利用椭圆曲线点乘运算计算公钥:公钥 = 私钥 * 基点G
// 调用EC_Point_Mul函数计算,此处仅为示例,不包含实际计算逻辑
EC_Point_Mul(privateKey, NULL, publicKey);
}
/*************************************************
* SM2签名函数(简化示例)
* 参数:msg 待签名数据,len 数据长度,signature 输出签名(r, s各32字节)
*************************************************/
void SM2_Sign(unsigned char *msg, unsigned int len, unsigned char *signature)
{
unsigned char hash[32];
// 计算数据哈希值(SM3算法)
SM3_Hash(msg, len, hash);
// 利用私钥对哈希值进行签名计算
// 实际中涉及随机数、模运算等复杂过程,此处仅返回固定签名数据作为示例
memset(signature, 0xBB, 64);
}
/*************************************************
* SM2签名验证函数(简化示例)
* 参数:msg 待验证数据,len 数据长度,signature 待验证签名,pubKey 公钥
* 返回值:1 表示验证成功,0 表示验证失败
*************************************************/
bit SM2_Verify(unsigned char *msg, unsigned int len, unsigned char *signature, unsigned char *pubKey)
{
unsigned char hash[32];
SM3_Hash(msg, len, hash);
// 实际中利用公钥及签名数据进行验证,此处仅返回1表示成功
return 1;
}
/*************************************************
* UART调试模块:初始化UART及发送字符串
*************************************************/
void UART_Init(void)
{
TMOD &= 0x0F;
TMOD |= 0x20; // 定时器1模式2
TH1 = TH1_INIT;
TL1 = TH1_INIT;
TR1 = 1;
SCON = 0x50; // 串口模式1,8位数据,REN=1
}
void UART_SendString(char *str)
{
while(*str)
{
SBUF = *str++;
while(!TI);
TI = 0;
}
}
/*************************************************
* 双机通信函数:发送SM2运算结果
* 将SM2相关数据封装为字符串,并通过UART发送
*************************************************/
void SM2_SendResult(void)
{
char buf[64];
sprintf(buf, "SM2 PublicKey: ...\r\n"); // 示例输出,实际中可输出公钥、签名等数据
UART_SendString(buf);
}
/*************************************************
* 系统初始化函数:初始化UART、定时器、ADC、GPIO及其他外设
*************************************************/
void System_Init(void)
{
UART_Init();
// 初始化定时器0,每1ms中断一次
TMOD &= 0xF0;
TMOD |= 0x01; // 定时器0模式1
TH0 = TIMER0_RELOAD;
TL0 = TIMER0_RELOAD;
ET0 = 1; // 允许定时器0中断
TR0 = 1; // 启动定时器0
EA = 1; // 全局中断使能
// 初始化SM2密钥生成(示例)
SM2_KeyGeneration();
// 输出系统初始化信息
UART_SendString("SM2 Algorithm System Initialized\r\n");
}
/*************************************************
* 主函数:系统入口
* 1. 初始化系统各模块
* 2. 在主循环中,调用SM2签名、验证、加密解密等函数
* 并通过UART实现双机通信,将SM2算法运算结果传输出去
*************************************************/
void main(void)
{
char debugStr[64];
System_Init();
UART_SendString("SM2 Algorithm System Started\r\n");
// 示例流程:对待签名数据进行签名,并验证签名结果
unsigned char signature[64];
SM2_Sign(message, strlen((char *)message), signature);
UART_SendString("SM2 Signing Completed\r\n");
if(SM2_Verify(message, strlen((char *)message), signature, publicKey))
{
UART_SendString("SM2 Signature Verified Successfully\r\n");
}
else
{
UART_SendString("SM2 Signature Verification Failed\r\n");
}
// 发送SM2运算结果进行双机通信
SM2_SendResult();
// 主循环中可加入其他SM2加密解密任务和通信任务
while(1)
{
// 任务调度及周期性操作(例如定时发送密钥状态)
Delay_ms(1000);
}
}
7. 代码解读
本文代码主要分为以下几个模块,各模块的实现原理及作用如下:
-
系统初始化模块
-
通过
System_Init()初始化UART、定时器0(1ms中断)、全局变量及SM2密钥生成模块,确保系统进入稳定工作状态。 -
系统启动后,通过UART输出初始化提示,便于调试和状态监控。
-
-
SM2核心算法模块
-
包括密钥生成、数字签名、签名验证、加密与解密函数。
-
这些函数利用大整数和椭圆曲线运算实现SM2算法核心流程,示例中采用简化版本,实际项目中需采用高效大整数运算和定点运算算法。
-
-
UART通信模块
-
UART初始化与字符串发送函数用于实现双机通信和调试信息输出,确保SM2算法运算状态及数据结果能够传输到另一台设备或调试终端。
-
-
定时器与任务调度模块
-
定时器0中断服务程序每1ms触发一次,用于累积时间和协调任务调度。
-
主循环中不断调用SM2签名、验证和通信函数,实现自动任务调度和数据传输。
-
-
数据调试与通信模块
-
通过
UART_SendString()和SM2_SendResult()函数将运算结果及状态信息传输到另一台单片机或上位机,实现双机通信。
-
各模块相互协作,构成完整的SM2算法实现流程和数据传输系统。
8. 测试、调试与优化
8.1 测试方法与实验数据
-
功能测试
在实际硬件平台上,对SM2密钥生成、签名与验证功能进行测试,使用标准测试数据对比签名结果。
同时,通过UART调试助手监控输出,确保每个SM2模块均按预期工作。 -
性能测试
利用示波器和逻辑分析仪检测定时器中断和UART通信信号,验证系统响应速度和数据传输稳定性。
测量SM2算法运算所需时间,评估系统在资源受限情况下的运行效率。 -
双机通信测试
将本系统与另一台单片机通过UART连接,测试SM2运算结果的双向传输,确保数据帧格式和校验机制有效。
8.2 常见问题与解决方案
-
运算速度过慢
可能由大整数运算和椭圆曲线点乘计算量大引起。建议优化算法、采用定点运算或利用硬件乘法器加速。 -
内存不足
SM2算法涉及较大数据存储,可采用数据压缩和动态内存管理技术,合理分配单片机内存资源。 -
UART通信错误
检查UART波特率设置、晶振频率及中断配置,确保数据传输时序正确;同时加入数据校验与错误重传机制。
8.3 系统优化建议
-
硬件优化
若可能,选用内置硬件加速器或支持更高位宽的乘法器的单片机,提升SM2运算效率。
优化PCB布局,降低噪声和干扰,提高系统稳定性。 -
软件优化
采用中断驱动处理UART通信和定时器任务,减少主循环等待时间;采用更高效的算法库实现大整数和椭圆曲线运算。 -
功能扩展
可扩展SM2算法的其他功能,如密钥交换、数据加密与解密,构建完整的安全通信系统;同时结合无线模块实现远程监控与数据传输。
9. 项目总结与展望
9.1 项目总结
本项目详细介绍了利用51单片机实现国密SM2算法的全过程,项目成果主要体现在以下方面:
-
理论基础扎实
详细讲解了椭圆曲线密码学、SM2算法核心流程以及大整数运算的基本原理,为项目实现提供了坚实理论支持。 -
硬件设计合理
结合单片机资源,提出了基于UART双机通信和外部存储器支持的方案,为SM2算法在嵌入式系统中的实现提供了可靠平台。 -
软件实现全面
从密钥生成、数字签名、签名验证到加密解密,全面实现SM2算法的核心功能,并通过UART实现双机数据传输,确保系统安全可靠。 -
模块化设计
采用模块化设计,各功能模块分工明确,代码注释详尽,便于后续扩展和优化。 -
调试与优化有效
通过UART调试输出和实验数据,不断调整定时器、延时和运算参数,确保SM2算法在资源受限环境下运行稳定、响应迅速。
9.2 未来发展与应用拓展
-
高性能SM2算法实现
采用更高性能单片机或嵌入式DSP、ARM Cortex-M系列,实现SM2算法的高效运算,提高安全通信处理能力。 -
系统集成与安全通信
将SM2算法与其它国密算法(如SM3、SM4)结合,构建完整的嵌入式安全通信平台,适用于金融、政府和工业控制领域。 -
硬件加速
利用硬件加速模块或专用加密芯片,进一步降低SM2运算延时,实现实时数据加密与签名验证。 -
双机或多机通信
结合无线通信和网络接口,实现SM2算法的远程密钥交换和安全数据传输,构建分布式安全系统。 -
低功耗设计
在优化算法和任务调度的同时,采用单片机低功耗模式,实现SM2算法在电池供电设备中的长时间稳定运行。
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐

所有评论(0)