python实现sm2加解密算法,不使用库

时间: 2023-11-11 19:21:51 浏览: 32
实现SM2算法需要用到椭圆曲线加密算法和哈希算法,这里我们使用Python内置的`hashlib`和`cryptomath`模块来实现。 首先,我们需要定义椭圆曲线的参数和基点: ```python P = 0xFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF A = 0xFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC B = 0x28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93 N = 0xFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123 Gx = 0x32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE171BEEB6E3A9D4F5B Gy = 0xBC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A ``` 然后,我们需要实现点加和点倍运算: ```python def add(p1, p2): if p1 is None: return p2 if p2 is None: return p1 x1, y1 = p1 x2, y2 = p2 if x1 == x2 and y1 != y2: return None if x1 == x2: m = (3 * x1 * x1 + A) * cryptomath.invmod(2 * y1, P) % P else: m = (y1 - y2) * cryptomath.invmod(x1 - x2, P) % P x3 = (m * m - x1 - x2) % P y3 = (m * (x1 - x3) - y1) % P return (x3, y3) def mul(k, p): if k == 0 or p is None: return None if k == 1: return p if k % 2 == 0: return mul(k // 2, add(p, p)) else: return add(p, mul(k - 1, p)) ``` 接下来,我们需要实现签名和验签的函数: ```python def sign(msg, d): e = int(hashlib.sha256(msg).hexdigest(), 16) k = func.random_int_range(1, N) while True: x, y = mul(k, (Gx, Gy)) r = (e + x) % N if r == 0 or k >= N: k = func.random_int_range(1, N) continue s = (cryptomath.invmod(k, N) * (d * r + k * e)) % N if s != 0: break k = func.random_int_range(1, N) return r, s def verify(msg, q, r, s): e = int(hashlib.sha256(msg).hexdigest(), 16) if r <= 0 or r >= N or s <= 0 or s >= N: return False t = (r + s) % N if t == 0: return False x, y = add(mul(s, (Gx, Gy)), mul(t, q)) if x is None or y is None: return False if (r + x) % N == e: return True else: return False ``` 最后,我们可以用以下代码来测试SM2算法的加解密: ```python d = func.random_int_range(1, N) q = mul(d, (Gx, Gy)) msg = b'Hello, world!' # 签名和验签 r, s = sign(msg, d) if verify(msg, q, r, s): print('Signature verified.') else: print('Signature verification failed.') # 加密和解密 plaintext = b'Hello, world!' k = func.random_int_range(1, N) x1, y1 = mul(k, (Gx, Gy)) c1 = hex(x1)[2:].rjust(64, '0') + hex(y1)[2:].rjust(64, '0') s = mul(N - d, add((int(c1[:64], 16), int(c1[64:], 16)), mul(k, plaintext))) c2 = hex(s[0])[2:].rjust(64, '0') + hex(s[1])[2:].rjust(64, '0') ciphertext = bytes.fromhex(c1 + c2) x2, y2 = mul(d, (int(ciphertext[:64], 16), int(ciphertext[64:128], 16))) decrypted_text = (s[1] - y2) // x2 print(decrypted_text.to_bytes((decrypted_text.bit_length() + 7) // 8, 'big')) ``` 需要注意的是,这里生成的私钥和公钥都是随机生成的,加密和解密的明文和密文都是字节串。

相关推荐

SM2算法是一种国密算法,用于椭圆曲线数字签名算法(ECDSA)和密钥交换协议(ECDH)。下面是一个用Python实现SM2算法的示例代码。 首先,我们需要导入一些工具库,如pycryptodome和ecc库,这两个库可以通过pip安装: python !pip install pycryptodome !pip install ecc 然后,我们就可以开始编写SM2算法了: python from Crypto.Cipher import AES from Crypto.Util.Padding import pad, unpad from Crypto.Util.number import bytes_to_long, long_to_bytes from ecc.curves import Curve, Point from ecc.key import find_curve_by_name, gen_keypair # 定义SM2算法用到的常量 a = 0xFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC b = 0x28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93 p = 0xFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF n = 0xFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123 # 定义SM2算法用到的椭圆曲线 curve = Curve(a, b, p, 1, 2, n, Point(0x4A96B5688EF573284664698968C38BB913CBFC82B9329B0F72EB7CBD7C3C3D63, 0x23A628553168947D59DCC912042351377AC5FB32F9C31F63B8F25C9A7FDC32A0)) # 生成随机的SM2密钥对 private_key, public_key = gen_keypair(curve) # 定义SM2算法用到的哈希函数 def sm3_hash(msg): from hashlib import sha256 from sm3 import sm3_kdf # 先进行SHA-256哈希 h = sha256() h.update(msg) msg_hash = h.digest() # 再进行SM3 KDF处理 key = b'\x00' * 16 iv = b'\x00' * 16 sm3_kdf(key, iv, msg_hash, len(msg_hash) * 8) return iv + msg_hash # 定义SM2算法用到的密钥派生函数 def sm2_kdf(z, klen): from sm3 import sm3_kdf # SM2 KDF处理 klen //= 8 ct = 1 temp = b'' while len(temp) < klen: msg = z + long_to_bytes(ct, 4) temp += sm3_kdf(b'', b'', msg, 256) ct += 1 return temp[:klen] # 定义SM2算法用到的加密函数 def sm2_encrypt(public_key, msg): from hashlib import sha256 from sm2 import encrypt # 生成随机的SM2密钥对 private_key, _ = gen_keypair(curve) # 计算SM2公钥的哈希值 h = sha256() h.update(public_key.export()) z = h.digest() # 计算KDF密钥 k = sm2_kdf(z, 128) # 进行数据加密 return encrypt(msg, public_key, bytes_to_long(k)) # 定义SM2算法用到的解密函数 def sm2_decrypt(private_key, ciphertext): from hashlib import sha256 from sm2 import decrypt # 计算SM2公钥的哈希值 h = sha256() h.update(private_key.public_key.export()) z = h.digest() # 计算KDF密钥 k = sm2_kdf(z, 128) # 进行数据解密 return decrypt(ciphertext, private_key, bytes_to_long(k)) # 定义SM2算法用到的签名函数 def sm2_sign(private_key, msg): from hashlib import sha256 from sm2 import sign # 计算SM2公钥的哈希值 h = sha256() h.update(private_key.public_key.export()) z = h.digest() # 进行数据签名 r, s = sign(msg, private_key, z) return r, s # 定义SM2算法用到的验证函数 def sm2_verify(public_key, msg, signature): from hashlib import sha256 from sm2 import verify # 计算SM2公钥的哈希值 h = sha256() h.update(public_key.export()) z = h.digest() # 进行数据验证 return verify(msg, public_key, signature, z) 上面的代码实现了SM2算法的加密、解密、签名和验证功能,可以直接使用。其中,加密和解密使用了AES算法,需要安装pycryptodome库;签名和验证使用了ecc库。 使用示例: python # 加密示例 msg = b"Hello, SM2!" ciphertext = sm2_encrypt(public_key, msg) print("Ciphertext:", ciphertext.hex()) # 解密示例 plaintext = sm2_decrypt(private_key, ciphertext) print("Plaintext:", plaintext) # 签名示例 msg = b"Hello, SM2!" r, s = sm2_sign(private_key, msg) print("Signature:", (r, s)) # 验证示例 msg = b"Hello, SM2!" signature = (r, s) is_valid = sm2_verify(public_key, msg, signature) print("Is valid:", is_valid) 注意:由于SM2算法涉及到国密相关的算法和标准,因此在实际使用中需要注意相关的法律和安全问题。
SM2是一种国家密码算法,其标准由中国国家密码管理局发布。Python的第三方库中,PyCryptodome库可以实现SM2算法。 以下是一个使用PyCryptodome库的例子: python from Crypto.PublicKey import ECC from Crypto.Cipher import AES from Crypto.Util.Padding import pad, unpad from Crypto.Hash import SHA256, SHA512, SM3 from Crypto.Signature import DSS from Crypto.Util.asn1 import DerSequence from Crypto.Util import asn1 from base64 import b64decode, b64encode # 生成SM2公私钥对 key = ECC.generate(curve='sm2p256v1') private_key = key.export_key(format='DER', use_pkcs8=True) public_key = key.public_key().export_key(format='DER') # SM2加密 def sm2_encrypt(plain_text, public_key): cipher_text = '' try: recipient_key = ECC.import_key(public_key) aes_key = SHA256.new(plain_text.encode('utf-8')).digest() cipher = AES.new(aes_key, AES.MODE_ECB) k = SM3.new().digest() c1 = recipient_key.pointQ * int.from_bytes(k, 'big') c1 = b'\x04' + c1.x.to_bytes(32, 'big') + c1.y.to_bytes(32, 'big') t = SM3.new(c1).digest() x1, y1 = recipient_key.pointQ.x, recipient_key.pointQ.y x2, y2 = (int.from_bytes(t, 'big') ^ int.from_bytes(k, 'big')).to_bytes(32, 'big'), \ (int.from_bytes(SM3.new(plain_text.encode('utf-8')).digest(), 'big') ^ int.from_bytes(k, 'big')).to_bytes(32, 'big') c2 = cipher.encrypt(pad(plain_text.encode('utf-8'), AES.block_size)) c3 = SM3.new((x2 + y2 + c2)).digest() cipher_text = b64encode(c1 + c2 + c3).decode('utf-8') except Exception as e: print(e) return cipher_text # SM2解密 def sm2_decrypt(cipher_text, private_key): plain_text = '' try: recipient_key = ECC.import_key(private_key) cipher_text = b64decode(cipher_text.encode('utf-8')) c1 = cipher_text[:65] c2 = cipher_text[65:-32] c3 = cipher_text[-32:] t = SM3.new(c1).digest() x2, y2 = int.from_bytes(c1[1:33], 'big'), int.from_bytes(c1[33:], 'big') x1, y1 = recipient_key.pointQ.x, recipient_key.pointQ.y u = (y2 * x1 - y1 * x2) v = x2 - x1 z = recipient_key.d * u // v k = (SM3.new(z.to_bytes(32, 'big')).digest()) ^ t aes_key = SHA256.new(k).digest() cipher = AES.new(aes_key, AES.MODE_ECB) plain_text = unpad(cipher.decrypt(c2), AES.block_size).decode('utf-8') except Exception as e: print(e) return plain_text # SM2签名 def sm2_sign(data, private_key): signature = '' try: key = ECC.import_key(private_key) h = SHA256.new(data.encode('utf-8')) k = int.from_bytes(SM3.new().digest(), 'big') r, s = DSS.new(key, 'fips-186-3').sign(h) sig = asn1.DerSequence([r, s]) signature = b64encode(sig.encode()).decode('utf-8') except Exception as e: print(e) return signature # SM2验签 def sm2_verify(data, signature, public_key): result = False try: key = ECC.import_key(public_key) h = SHA256.new(data.encode('utf-8')) sig = DerSequence(b64decode(signature.encode('utf-8'))) r, s = sig[0], sig[1] verifier = DSS.new(key, 'fips-186-3') verifier.verify(h, (r, s)) result = True except Exception as e: print(e) return result 以上代码中,sm2_encrypt函数用于SM2加密,sm2_decrypt函数用于SM2解密,sm2_sign函数用于SM2签名,sm2_verify函数用于SM2验签。其中,public_key和private_key分别为SM2公钥和私钥,plain_text为明文,cipher_text为密文,data为要签名的数据,signature为签名结果。
以下是使用Python语言实现SM2的加解密代码(需要使用pycryptodomex库): python from Crypto.Cipher import AES from Crypto.Util.Padding import pad, unpad from Crypto.PublicKey import ECC from Crypto.Cipher import PKCS1_v1_5 from Crypto.PublicKey import RSA from Crypto.Signature import pkcs1_15 from Crypto.Hash import SHA256 import binascii def sm2_encrypt(data, public_key): # 将公钥转换为ECC类型 ecc_public_key = ECC.import_key(public_key) # 获取公钥的xy坐标 x, y = ecc_public_key.pointQ.x, ecc_public_key.pointQ.y # 将数据进行填充 padded_data = pad(data.encode(), AES.block_size) # 生成随机数k k = ECC.generate(curve='sm2p256v1').d # 计算椭圆曲线点C1 C1 = k * ecc_public_key.generator C1_x_bytes = C1.x.to_bytes(32, 'big') C1_y_bytes = C1.y.to_bytes(32, 'big') # 计算C3 hashed_data = SHA256.new(padded_data) C3 = hashed_data.digest() # 计算C2 # 将公钥的xy坐标拼接成一个字节数组 xy_bytes = x.to_bytes(32, 'big') + y.to_bytes(32, 'big') # 计算SM3哈希值 hashed_xy_data = sm3_hash(xy_bytes) # 计算加密密钥 kdf_key = hashed_xy_data + b'\x01' # 将随机数k转换为字节数组 k_bytes = k.to_bytes(32, 'big') # 计算加密因子u u = sm3_kdf(k_bytes, 32, kdf_key) # 将加密因子u转换为整数 u_int = int.from_bytes(u, 'big') # 将填充后的数据分组 groups = [padded_data[i:i + 16] for i in range(0, len(padded_data), 16)] # 计算加密后的数据 C2 = b'' for group in groups: m_int = int.from_bytes(group, 'big') c_int = (m_int + u_int) % ecc_public_key.order C2 += c_int.to_bytes(16, 'big') # 将加密结果拼接成一个字节数组 encrypted_data = C1_x_bytes + C1_y_bytes + C3 + C2 # 将加密结果进行BASE64编码 encrypted_data_base64 = base64.b64encode(encrypted_data).decode() return encrypted_data_base64 def sm2_decrypt(data, private_key): # 将私钥转换为ECC类型 ecc_private_key = ECC.import_key(private_key) # 将加密数据进行BASE64解码 encrypted_data = base64.b64decode(data) # 分离出C1、C3和C2 C1_x_bytes = encrypted_data[0:32] C1_y_bytes = encrypted_data[32:64] C3 = encrypted_data[64:96] C2 = encrypted_data[96:] # 计算椭圆曲线点C1 C1_x = int.from_bytes(C1_x_bytes, 'big') C1_y = int.from_bytes(C1_y_bytes, 'big') C1 = ECC.EccPoint(C1_x, C1_y, curve='sm2p256v1') # 计算SM3哈希值 hashed_xy_data = sm3_hash(private_key.public_key().export_key(format='DER')[31:]) # 计算加密密钥 kdf_key = hashed_xy_data + b'\x01' # 计算加密因子u u = sm3_kdf(C1_x_bytes + C1_y_bytes, 32, kdf_key) # 将加密因子u转换为整数 u_int = int.from_bytes(u, 'big') # 计算填充后的数据 padded_data = b'' for i in range(0, len(C2), 16): c_int = int.from_bytes(C2[i:i + 16], 'big') m_int = (c_int - u_int) % ecc_private_key.order padded_data += m_int.to_bytes(16, 'big') # 将填充后的数据进行解填充 original_data = unpad(padded_data, AES.block_size).decode() return original_data 其中,sm3_hash和sm3_kdf是SM3哈希算法和密钥派生函数的实现,可以参考SM3算法的标准文档进行实现。另外,这里使用了AES算法对数据进行填充和解填充。
国密(SM2、SM3、SM4)是中国自主研发的密码算法标准。以下是一个使用Python进行国密加密解密的示例代码: 首先,需要安装gmssl库,它提供了国密算法的实现。你可以使用以下命令来安装它: pip install gmssl 接下来,我们将给出一个使用SM2进行加密解密的示例代码: python from gmssl import sm2, func # 生成SM2密钥对 private_key = '7B8D92E5C6C8B0F9A2CFD2E3E4E6E8EA9FA4A7A9BDC0D3D6D9DCDEE1E4E7EA' public_key = '04A7F4427940CFF9AFFF07FCFF8414D20B186C9F94A181E16AD7F6A26F320BCE4C8C22CDB8ACF5EE5AA42F9C7CE6A6BA31D1D32B8F3A9A60A489C8972FCA5C0E' # 加密 def encrypt(message): sm2_crypt = sm2.CryptSM2(public_key=public_key, private_key=private_key) enc_data = sm2_crypt.encrypt(message.encode()) return enc_data.hex() # 解密 def decrypt(encrypted_data): sm2_crypt = sm2.CryptSM2(public_key=public_key, private_key=private_key) dec_data = sm2_crypt.decrypt(bytes.fromhex(encrypted_data)) return dec_data.decode() # 测试加密解密 message = 'Hello, World!' encrypted_message = encrypt(message) decrypted_message = decrypt(encrypted_message) print('加密后的消息:', encrypted_message) print('解密后的消息:', decrypted_message) 在上面的代码中,我们首先生成了一个SM2密钥对,然后定义了encrypt和decrypt函数来进行加密和解密。encrypt函数使用公钥对消息进行加密,返回加密后的十六进制字符串。decrypt函数使用私钥对加密数据进行解密,返回解密后的原始消息。 请注意,示例代码中使用的密钥对是固定的,你可能需要根据实际情况替换为自己的密钥对。 希望这能帮助到你!如果还有其他问题,请随时提问。

最新推荐

基于Springboot的网上宠物店系统的设计与实现论文-java-文档-基于Springboot网上宠物店系统的设计与实现文档

基于Springboot的网上宠物店系统的设计与实现论文-java-文档-基于Springboot网上宠物店系统的设计与实现文档论文: !!!本文档只是论文参考文档! 需要项目源码、数据库sql、开发文档、毕设咨询等,请私信联系~ ① 系统环境:Windows/Mac ② 开发语言:Java ③ 框架:SpringBoot ④ 架构:B/S、MVC ⑤ 开发环境:IDEA、JDK、Maven、Mysql ⑥ JDK版本:JDK1.8 ⑦ Maven包:Maven3.6 ⑧ 数据库:mysql 5.7 ⑨ 服务平台:Tomcat 8.0/9.0 ⑩ 数据库工具:SQLyog/Navicat ⑪ 开发软件:eclipse/myeclipse/idea ⑫ 浏览器:谷歌浏览器/微软edge/火狐 ⑬ 技术栈:Java、Mysql、Maven、Springboot、Mybatis、Ajax、Vue等 最新计算机软件毕业设计选题大全 https://blog.csdn.net/weixin_45630258/article/details/135901374 摘 要 目 录 第1章

面向6G的编码调制和波形技术.docx

面向6G的编码调制和波形技术.docx

管理建模和仿真的文件

管理Boualem Benatallah引用此版本:布阿利姆·贝纳塔拉。管理建模和仿真。约瑟夫-傅立叶大学-格勒诺布尔第一大学,1996年。法语。NNT:电话:00345357HAL ID:电话:00345357https://theses.hal.science/tel-003453572008年12月9日提交HAL是一个多学科的开放存取档案馆,用于存放和传播科学研究论文,无论它们是否被公开。论文可以来自法国或国外的教学和研究机构,也可以来自公共或私人研究中心。L’archive ouverte pluridisciplinaire

Power BI中的数据导入技巧

# 1. Power BI简介 ## 1.1 Power BI概述 Power BI是由微软公司推出的一款业界领先的商业智能工具,通过强大的数据分析和可视化功能,帮助用户快速理解数据,并从中获取商业见解。它包括 Power BI Desktop、Power BI Service 以及 Power BI Mobile 等应用程序。 ## 1.2 Power BI的优势 - 基于云端的数据存储和分享 - 丰富的数据连接选项和转换功能 - 强大的数据可视化能力 - 内置的人工智能分析功能 - 完善的安全性和合规性 ## 1.3 Power BI在数据处理中的应用 Power BI在数据处

建立关于x1,x2 和x1x2 的 Logistic 回归方程.

假设我们有一个包含两个特征(x1和x2)和一个二元目标变量(y)的数据集。我们可以使用逻辑回归模型来建立x1、x2和x1x2对y的影响关系。 逻辑回归模型的一般形式是: p(y=1|x1,x2) = σ(β0 + β1x1 + β2x2 + β3x1x2) 其中,σ是sigmoid函数,β0、β1、β2和β3是需要估计的系数。 这个方程表达的是当x1、x2和x1x2的值给定时,y等于1的概率。我们可以通过最大化似然函数来估计模型参数,或者使用梯度下降等优化算法来最小化成本函数来实现此目的。

智能网联汽车技术期末考试卷B.docx

。。。

"互动学习:行动中的多样性与论文攻读经历"

多样性她- 事实上SCI NCES你的时间表ECOLEDO C Tora SC和NCESPOUR l’Ingén学习互动,互动学习以行动为中心的强化学习学会互动,互动学习,以行动为中心的强化学习计算机科学博士论文于2021年9月28日在Villeneuve d'Asq公开支持马修·瑟林评审团主席法布里斯·勒菲弗尔阿维尼翁大学教授论文指导奥利维尔·皮耶昆谷歌研究教授:智囊团论文联合主任菲利普·普雷教授,大学。里尔/CRISTAL/因里亚报告员奥利维耶·西格德索邦大学报告员卢多维奇·德诺耶教授,Facebook /索邦大学审查员越南圣迈IMT Atlantic高级讲师邀请弗洛里安·斯特鲁布博士,Deepmind对于那些及时看到自己错误的人...3谢谢你首先,我要感谢我的两位博士生导师Olivier和Philippe。奥利维尔,"站在巨人的肩膀上"这句话对你来说完全有意义了。从科学上讲,你知道在这篇论文的(许多)错误中,你是我可以依

数据可视化:Pandas与Matplotlib的结合应用

# 1. 数据可视化的重要性 1.1 数据可视化在数据分析中的作用 1.2 Pandas与Matplotlib的概述 **1.1 数据可视化在数据分析中的作用** 数据可视化在数据分析中扮演着至关重要的角色,通过图表、图形和地图等形式,将抽象的数据转化为直观、易于理解的可视化图像,有助于人们更直观地认识数据,发现数据之间的关联和规律。在数据分析过程中,数据可视化不仅可以帮助我们发现问题和趋势,更重要的是能够向他人有效传达数据分析的结果,帮助决策者做出更明智的决策。 **1.2 Pandas与Matplotlib的概述** Pandas是Python中一个提供数据

1. IP数据分组的片偏移计算,MF标识符怎么设置。

IP数据分组是将较长的IP数据报拆分成多个较小的IP数据报进行传输的过程。在拆分的过程中,每个数据分组都会设置片偏移和MF标识符来指示该分组在原始报文中的位置和是否为最后一个分组。 片偏移的计算方式为:将IP数据报的总长度除以8,再乘以当前分组的编号,即可得到该分组在原始报文中的字节偏移量。例如,若原始报文总长度为1200字节,每个数据分组的最大长度为500字节,那么第一个分组的片偏移为0,第二个分组的片偏移为500/8=62.5,向下取整为62,即第二个分组的片偏移为62*8=496字节。 MF标识符是指“更多的分组”标识符,用于标识是否还有后续分组。若该标识位为1,则表示还有后续分组;

8个案例详解教会你ThreadLocal.docx

通常情况下,我们创建的成员变量都是线程不安全的。因为他可能被多个线程同时修改,此变量对于多个线程之间彼此并不独立,是共享变量。而使用ThreadLocal创建的变量只能被当前线程访问,其他线程无法访问和修改。也就是说:将线程公有化变成线程私有化。