python实现sm2加解密算法,不使用库
时间: 2023-11-11 22:21:51 浏览: 116
实现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'))
```
需要注意的是,这里生成的私钥和公钥都是随机生成的,加密和解密的明文和密文都是字节串。
阅读全文