python的第三方库实现SM2
时间: 2023-12-25 20:20:39 浏览: 267
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`为签名结果。
阅读全文