Python实现AES算法和国密SM4算法

news2025/1/11 10:05:59

本文主要介绍使用AES加密算法的Python实现和shell脚本实现、SM4国密算法的Python实现。Python使用pycryptodome实现AES加解密、使用GmSSL实现SM4加解密算法;Shell脚本使用openssl实现AES加解密,详细见下文。


1、Python实现加密和解密
1.1 Python实现AES加密和解密

1)pycryptodome包

pycryptodome是Python中一个常用的加密模块,它是Cryptography及PyCrypto项目的继承者,可以支持多种对称和非对称加密算法,包括AES、Blowfish、RSA和DSA等。在PyCrypto已经不再更新之后,推荐使用pycryptodome来代替PyCrypto。

在这里插入图片描述

2)AES加密算法

AES加密算法,全称高级加密标准(Advanced Encryption Standard),是美国联邦政府采用的一种区块加密标准。在密码学中,它是一种对称加密算法,可支持128、192和256位的密钥长度。该算法基于比特块的转换、替换和移位操作,进行多次迭代以实现加密。加密过程中,明文被分成若干个128位的比特块,然后通过与密钥的相互作用,经过多轮加密操作,最终生成密文。每一轮都使用不同的子密钥,而这些子密钥又由原始密钥经过一系列的加密函数生成。

AES加密算法有五种工作模式,这些模式可以应用到数据加密的标准流程中:

  • 电码本模式(Electronic Codebook (ECB)):将整个明文分成若干段相同的小段,然后对每一小段进行加密。
  • 密码分组链接模式(Cipher Block Chaining (CBC)):先将明文切分成若干小段,然后每一小段与初始块或者上一段的密文段进行异或运算后,再与密钥进行加密。
  • 计算器模式(Counter (CTR)):不常见,使用一个自增的算子,这个算子用密钥加密之后的输出和明文异或的结果得到密文,相当于一次一密。
  • 密码反馈模式(Cipher FeedBack (CFB)):比较复杂,IV(初始化向量)将加密后的密文length-n位再次加密,每次能加密n位。
  • 输出反馈模式(Output FeedBack (OFB)):比较复杂。

AES.MODE_EAX,全称AES Encrypt-and-Authenticate (加密和认证)模式,是一种同时提供加密和认证的密码模式。在这种模式下,即使攻击者能够得到密文和认证数据,没有正确的密钥,他们也无法解密得到明文数据,同时通过认证数据也可以保证数据的完整性。

3)Python实现AES-CBC模式加密和解密

# -*- coding: utf-8 -*-

from Crypto.Cipher import AES  
from Crypto.Util.Padding import pad, unpad  
from Crypto.Random import get_random_bytes  

# 创建AES对象,使用CBC模式,使用一个16字节的随机IV   
def aes_encrypt(data, key):  
    cipher = AES.new(key, AES.MODE_CBC,get_random_bytes(16))  
    ct_bytes = cipher.encrypt(pad(data, AES.block_size))  
    iv = cipher.iv  
    return iv, ct_bytes  
 
# 创建新的AES对象,用于解密 
def aes_decrypt(iv, ct_bytes, key):  
    cipher = AES.new(key, AES.MODE_CBC, iv=iv)  
    pt = unpad(cipher.decrypt(ct_bytes), AES.block_size)  
    return pt  
  
# 生成一个随机密钥  
key = get_random_bytes(16)  
  
# 加密数据  
data = b"Hello@2023"  
iv,ct = aes_encrypt(data, key)  
print("Ciphertext:", ct)  
  
# 解密数据  
decrypted = aes_decrypt(iv, ct, key)  
print("Decrypted text:", decrypted)

4)Python实现AES-EAX模式加密和解密

# -*- coding: utf-8 -*-

from Crypto.Cipher import AES  
#from Crypto.Util.Padding import pad, unpad  
from Crypto.Random import get_random_bytes  

# 创建AES对象,使用EAX模式,使用一个16字节的随机IV   
def aes_encrypt(data, key):  
    cipher = AES.new(key, AES.MODE_EAX) 
    ciphertext, tag = cipher.encrypt_and_digest(data)  
    nonce = cipher.nonce  
    return ciphertext,tag,nonce  
 
# 创建新的AES对象,用于解密 
def aes_decrypt(ct_bytes, key, nonce, tag):  
    cipher = AES.new(key, AES.MODE_EAX, nonce=nonce)
    pt = cipher.decrypt(ct_bytes)
    try:
        cipher.verify(tag)
        pt_verify = 1
    except ValueError:
        pt_verify = 0
        print('密钥不正确或消息被破坏')
    return pt,pt_verify  
  
# 生成一个随机密钥  
key = get_random_bytes(16)  
  
# 加密数据  
data = b"Hello@2023"  
ct,tag,nonce = aes_encrypt(data, key)  
print("Ciphertext:", ct)  
  
# 解密数据  
decrypted,flag = aes_decrypt(ct, key, nonce, tag)
if flag==1:  
	print("Decrypted text:", decrypted)
else:
	print('密钥不正确或消息被破坏')
1.2 Python实现国密SM4加密和解密

1)GmSSL库

GmSSL是由北京大学自主开发的国产商用密码开源库,实现了对国密算法、标准和安全通信协议的全面功能覆盖,包括SM3、SM4等国密算法。该库支持包括移动端在内的主流操作系统和处理器,支持密码钥匙、密码卡等典型国产密码硬件,并提供了功能丰富的命令行工具以及多种编译语言编程接口。此外,GmSSL大幅度降低了内存需求和二进制代码体积,具有轻量化的特点。

在这里插入图片描述

2)SM1、SM2、SM3和SM4加密算法

SM1、SM2、SM3和SM4是中国国家密码管理局发布的四个密码算法标准,介绍如下:

  • SM1是一种对称密码算法。它的密钥长度为128位,分组长度为128位,采用分组密码的加密方式,即将明文分为若干个长度相同的分组,每个分组进行加密运算,最后合并为密文。SM1的加密过程中包括了置换、代换、线性变换等步骤,从而保证了加密的强度和安全性。需要注意的是,SM1算法仅用于加密小数据量。
  • SM2是一种非对称密码算法。它采用了椭圆曲线密码学,可以用于数字签名、密钥协商、加密和解密等操作。SM2的安全性基于离散对数问题的难度,通过椭圆曲线的运算实现加密和解密操作。它的私钥长度为256位,公钥长度为512位,可以提供与1024位RSA算法相当的安全性。
  • SM3是一种哈希函数。它可以用于对任意长度的消息进行摘要操作,可以生成一个固定长度的消息摘要。SM3算法采用了置换、代换、移位、加法等操作,可以保证摘要的强度和唯一性。它的安全性可达到256位。
  • SM4是一种分组对称密码算法。它的密钥长度为128位,分组长度为128位,具有高效性和安全性。SM4算法采用了Feistel结构,将明文分成多个数据块,每个数据块分别进行加密操作。SM4算法采用了S盒、置换、线性变换等操作,从而保证了加密的强度和安全性。

3)Python实现SM4算法加密和解密

# -*- coding: utf-8 -*-

from gmssl.sm4 import CryptSM4, SM4_ENCRYPT, SM4_DECRYPT
import binascii
import os

def str_to_hexStr(hex_str):
    """
    字符串转hex
    :param hex_str: 字符串
    :return: hex
    """
    hex_data = hex_str.encode('utf-8')
    str_bin = binascii.unhexlify(hex_data)
    return str_bin.decode('utf-8')

def encrypt(crypt_sm4,encrypt_key, value):
    """
    国密sm4加密
    :param encrypt_key: sm4加密key
    :param value: 待加密的字符串
    :return: sm4加密后的hex值
    """
    crypt_sm4.set_key(encrypt_key, SM4_ENCRYPT)
    encrypt_value = crypt_sm4.crypt_ecb(value)  # bytes类型
    return encrypt_value.hex()

def decrypt(crypt_sm4,decrypt_key, encrypt_value):
    """
    国密sm4解密
    :param decrypt_key:sm4加密key
    :param encrypt_value: 待解密的hex值
    :return: 原字符串
    """
    crypt_sm4.set_key(decrypt_key, SM4_DECRYPT)
    decrypt_value = crypt_sm4.crypt_ecb(bytes.fromhex(encrypt_value))  # bytes类型
    return str_to_hexStr(decrypt_value.hex())


key = os.urandom(16) 
value = b'Hello@2023' #  bytes类型
crypt_sm4 = CryptSM4()

# 加密
enc_value = encrypt(crypt_sm4,key,value)

#解密
dec_value = encrypt(crypt_sm4,key,enc_value)
2、Shell脚本实现AES加密和解密

在Shell脚本中,可以使用OpenSSL命令行工具来实现AES解密。

  • 使用urandom生成16字节的随机字符串
  • 使用openssl enc -aes-256-cbc实现AES加密和解密

完整代码如下所示:

#!/bin/bash  
  
# 加密/解密工具  
program_openssl=$(command -v openssl)  
program_gpg=$(command -v gpg)  
  
# 待加密/解密的数据  
data_file="data.txt"  
  
# 加密后的数据文件  
encrypted_file="encrypted.aes"  
  
# 解密后的数据文件  
decrypted_file="decrypted.txt"  
  
# 密钥(16字节)  
key=$(cat /dev/urandom |head -n 16|md5sum |cut -c 1-16)
  
# 初始化向量(16字节)  
iv=$(cat /dev/urandom |head -n 16|md5sum |cut -c 1-16)

# 使用AES-256加密  
function encrypt() {  
    if [ -f "$data_file" ]; then  
        if [ -x "$program_openssl" ]; then  
            openssl enc -nosalt -K "$key" -iv "$iv" -in "$data_file" -out "$encrypted_file" -aes-256-cbc  
            if [ $? -eq 0 ]; then  
                echo "加密成功!加密后的数据在 $encrypted_file 文件中。"  
            else  
                echo "加密失败。"  
            fi  
        else  
            echo "未找到 openssl 命令。"  
        fi  
    else  
        echo "未找到待加密的数据文件 $data_file。"  
    fi  
}  
  
# 使用AES-256解密  
function decrypt() {  
    if [ -f "$encrypted_file" ]; then  
        if [ -x "$program_openssl" ]; then  
            openssl enc -d -nosalt -K "$key" -iv "$iv" -in "$encrypted_file" -out "$decrypted_file" -aes-256-cbc  
            if [ $? -eq 0 ]; then  
                echo "解密成功!解密后的数据在 $decrypted_file 文件中。"  
            else  
                echo "解密失败。"  
            fi  
        else  
            echo "未找到 openssl 命令。"  
        fi  
    else  
        echo "未找到待解密的数据文件 $encrypted_file。"  
    fi  
}  
  
# 测试AES加密和解密  
encrypt
decrypt

参考资料:

  1. https://pypi.org/project/gmssl/

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

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

相关文章

最新AI创作系统源码ChatGPT网站源码V2.6.3/支持Midjourney绘画/支持OpenAI GPT全模型+国内AI全模型

一、AI创作系统 SparkAi创作系统是基于OpenAI很火的ChatGPT进行开发的Ai智能问答系统,支持OpenAI GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美,可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如何搭建部署AI创作Chat…

《人间失格》阅读笔记

《人间失格》读书笔记 2023年10月7日读完,在过去的三个月时间内,有忙碌申博、从杭州辞职回家、准备入学、到澳门入学的事情,终于忙完了这些所有事情,回到了横琴的小房子里读完了这本书。 这本书前半部分讲了主角,作为…

香港Web3.0生态现状

目前香港Web3.0生态正在快速发展。香港政府和金融机构正在积极推动Web3.0生态的建设,以推动数字经济和智慧城市的发展。香港政府已经发布了有关虚拟资产发展的政策宣言,鼓励和监管并重,加大力度推动虚拟资产产业向前发展。同时,香…

【用unity实现100个游戏之14】Unity2d做一个建造与防御类rts游戏

前言 欢迎来到本次教程,我将为您讲解如何使用 Unity 引擎来开发一个建造与防御类 RTS(即实时战略)游戏。 在本教程中,我们将学习如何创建 2D 场景、设计 2D 精灵、制作 2D 动画、响应用户输入、管理游戏数据、以及其他有关游戏开…

聊聊分布式架构——BIO到NIO的演进

目录 I/O I/O模型 BIO示例 BIO与NIO比较 NIO的三大核心 NIO核心之缓冲区 Buffer常用子类: Buffer常用API Buffer中的重要概念 NIO核心之通道 FileChannel 类 FileChannel常用方法 NIO核心之选择器 概述 应用 NIO非阻塞原理分析 服务端流程 客户端…

【Java8】线程问题排查分析

文章目录 thread dump简介JDK 工具jstackjattachjvisualvm Java程序CPU消耗较高,怎么快速看出是那个线程导致的呢?我们可以使用命令 jstack/jattach来快速定位问题 thread dump简介 thread dump 是 Java 进程的所有线程状态的快照。每个线程的状态都通过…

java基础-第1章-走进java世界

一、计算机基础知识 常用的DOS命令 二、计算机语言介绍 三、Java语言概述 四、Java环境的搭建 JDK安装图解 环境变量的配置 配置环境变量意义 配置环境变量步骤 五、第一个Java程序 编写Java源程序 编译Java源文件 运行Java程序 六、Java语言运行机制 核心机制—Java虚拟机 核…

【LeetCode高频SQL50题-基础版】打卡第2天:第11-15题

文章目录 【LeetCode高频SQL50题-基础版】打卡第2天:第11-15题⛅前言 员工奖金🔒题目🔑题解 学生们参加各科测试的次数🔒题目🔑题解 至少有5名直接下属的经理🔒题目🔑题解 确认率🔒题…

tcpdump(二)命令行参数讲解(一)

一 tcpdump实战详解 1、我们做抓包,一般都需要指定条件,保证对系统的CPU、内存、磁盘资源不会产生过大的响应备注: 遇到过tcpdump持续抓包导致系统挂了2、条件:1) tcpdump的 基础命令选项参数2) 真正的 过滤条件 ① 参数学习思路 思路:…

Window Anaconda 安装pytorch 启用cuda 终究手段

1.首先你的电脑要有NVIDIA 的显卡.没有就走吧,你如果不是window ,也走吧,不一定教程管用。 2.然后要明白,有两种CUDA版本,一个叫运行时api,一个是驱动api 2.1 运行时cuda 版本查看 (是你跑深度学习模型或其…

关于 Vue-iClient-MapboxGL 的使用注意事项

官网:https://iclient.supermap.io/web/apis/vue/zh/api/guide/installation.html 关于图的使用,其余的引入步骤不再赘述,仅说注意事项。 推荐使用的是全局引入,也就是完整引入 因为单独引入我踩了不少坑,比如说 cs…

swoole进行性能查看火焰图tideways_xhprof xhgui

D:\dnmp\services\php\Dockerfile D:\dnmp\services\php\php.ini 在php的配置文件里面增加tideways_xhprof拓展: [xhprof] ;xhprof.output_dir /var/log/php/xhprof.logextensiontideways_xhprof.so在php配置文件里面加上xhgui的header: 这样就能开启…

golang 编译器 汉化

1、找到左上角file选项,点击选中settings进行单机 2、找到settings中找到plugins选中进行点击 3、再框中输入chinese进行搜索,出结果后找到如下图所示,点击进行安装 4、安装完成后进行重启ide,完美解决

Docker linux 安装

sudo yum update sudo yum clean all sudo yum makecache#安装依赖 sudo yum install -y yum-utils device-mapper-persistent-data lvm2 #添加官方存储库 sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo#安装-跳过一些异常依赖…

计算机视觉: 基于隐式BRDF自编码器的文生三维技术

论文链接: MATLABER: Material-Aware Text-to-3D via LAtent BRDF auto-EncodeR 背景 得益扩散模型和大量的text - image 成对的图片, 现在文生2D的模型已经比较成熟的框架和模型,主流的技术比如说stable diffusion 和 midjourney 以及工业领域runway 等…

Idea下面git的使用:变基、合并、优选、还原提交、重置、回滚、补丁

多分支和分支切换 变基和合并 变基是把本项目的所有提交都列出来按顺序一个个提交到目标分支上去 而合并是把两个分支合并起来,但是旧的分支还是可以启动其他分支,在旧的分支上继续开发 master: A -- B -- C -- M/ feature: D -- Emaster: A -…

2023全新小红书图集和视频解析去水印网站源码

2023全新小红书图集和视频解析去水印网站源码 小红书视频图集解析网站源码,在红书看到好看的图片以及好看的头像,但是直接下载又有水印就非常难受,这个可以一键解析去除水印,支持统计解析次数,本地接口。 源码下载&a…

大厂秋招真题【BFS+DP】华为20230921秋招T3-PCB印刷电路板布线(留学生专场)

华为20230921秋招T3-PCB印刷电路板布线(留学生专场) 题目描述与示例 题目描述 在PCB印刷电路板设计中,器件之间的连线,要避免线路的阻抗值增大,而且器件之间还有别的器任和别的干扰源,在布线时我们希望受…

深度学习入门:基于Python的理论与实现【笔记】

深度学习入门:基于Python的理论与实现这本数的阅读笔记 根据自己的情况总结的,可能有些简单的就没做笔记。 目录 NumPyMatplotlib感知机NumPy 在深度学习的实现中,经常出现数组和矩阵的计算。NumPy的数组类(numpy.array)中提供了很多便捷的方法,在实现深度学习时,我们将使…

力扣 -- 516. 最长回文子序列

解题步骤&#xff1a; 参考代码&#xff1a; class Solution { public:int longestPalindromeSubseq(string s) {int ns.size();vector<vector<int>> dp(n,vector<int>(n));//记得从下往上填表for(int in-1;i>0;i--){//记得i是小于等于j的for(int ji;j&l…