一、rsa模块
# -*- coding: utf-8 -*-
import rsa
(pubkey, privkey) = rsa.newkeys(1024)
# 生成公钥
pub = pubkey.save_pkcs1()
pubfile = open('public.pem', 'wb')
pubfile.write(pub)
pubfile.close()
# 生成私钥
pri = privkey.save_pkcs1()
prifile = open('private.pem', 'wb')
prifile.write(pri)
prifile.close()
二、Crypto模块
from Crypto import Random
from Crypto.PublicKey import RSA
def private_public():
"""
获得公钥与私钥
param :无
return : 私钥与公钥
"""
# 生成私钥
random_generator = Random.new().read
rsa = RSA.generate(3072, random_generator)
private_key = rsa.exportKey() # bytes类型
# 生成公钥
public_key = rsa.publickey().exportKey() #bytes类型
return private_key.decode('utf-8'), public_key.decode('utf-8')
三、Win64OpenSSL
步骤一:在windows操作系统上安装Win64OpenSSL软件; 步骤二:打开Win64OpenSSL软件,首先生成私钥,命令为:ecparam -genkey -name SM2 -out priv.key;
步骤三:再通过生成的私钥生成公钥,命令为:ec -in priv.key -pubout -out pub.key。
验证SM2生成的公私钥 步骤一:首先创建一个file.txt文件(示例放在公私钥同级目录下);
步骤二:打开Win64OpenSSL软件,首先根据私钥生成签名,命令为:dgst -sign priv.key -sha1 -out sha1_sm2_file.sign file.txt
步骤三:再根据公钥去验证生成的签名,如果公钥和私钥相互匹配,那么生成SM2公私钥成功,命令为:dgst -verify pub.key -sha1 -signature sha1_sm2_file.sign file.txt
OpenSSL> ecparam -genkey -name SM2 -out priv.key
ecparam: Can't open "priv.key" for writing, Permission denied
error in ecparam
OpenSSL> ecparam -genkey -name SM2 -out d:/priv.key
OpenSSL> ec -in d:/priv.key -pubout -out d:/pub.key
read EC key
writing EC key
OpenSSL> dgst -sign d:/priv.key -sha1 -out d:/sha1_sm2_file.sign d:/file.txt
d:/file.txt: No such file or directory
error in dgst
OpenSSL> dgst -sign d:/priv.key -sha1 -out d:/sha1_sm2_file.sign d:/file.txt
OpenSSL> dgst -verify d:/pub.key -sha1 -signature d:/sha1_sm2_file.sign d:/file.txt
Verified OK
文件地址需要修改.上述直接放在d盘中,最后为.key 或者.pem
四、gmssl
Download (GmSSL-master.zip), uncompress it and go to the source code folder. On Linux and OS X, run the following commands:
$ ./config
$ make
$ sudo make install
安装后,输入gmssl version,报错:
gmssl: error ``while` `loading shared libraries: libssl.so.1.1: cannot ``open` `shared object ``file``: No such ``file` `or directory
添加两条软连接:
ln -s /usr/local/lib64/libssl.so.1.1 /usr/lib64/libssl.so.1.1
ln -s /usr/local/lib64/libcrypto.so.1.1 /usr/lib64/libcrypto.so.1.1
生成私钥
$ gmssl sm2 -genkey -out skey.pem
生成公钥
$ gmssl sm2 -pubout -in skey.pem -out vkey.pem
参考(https://github.com/guanzhi/GmSSL)
五、 支付宝开放平台开发助手

六、自定义代码
上面生成的公私钥都没法给gmss sm2使用,可以进行加密解密,但是结果是错的
from random import SystemRandom
class CurveFp:
def __init__(self, A, B, P, N, Gx, Gy, name):
self.A = A
self.B = B
self.P = P
self.N = N
self.Gx = Gx
self.Gy = Gy
self.name = name
sm2p256v1 = CurveFp(
name="sm2p256v1",
A=0xFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC,
B=0x28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93,
P=0xFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF,
N=0xFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123,
Gx=0x32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7,
Gy=0xBC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0
)
def multiply(a, n, N, A, P):
return fromJacobian(jacobianMultiply(toJacobian(a), n, N, A, P), P)
def add(a, b, A, P):
return fromJacobian(jacobianAdd(toJacobian(a), toJacobian(b), A, P), P)
def inv(a, n):
if a == 0:
return 0
lm, hm = 1, 0
low, high = a % n, n
while low > 1:
r = high//low
nm, new = hm-lm*r, high-low*r
lm, low, hm, high = nm, new, lm, low
return lm % n
def toJacobian(Xp_Yp):
Xp, Yp = Xp_Yp
return (Xp, Yp, 1)
def fromJacobian(Xp_Yp_Zp, P):
Xp, Yp, Zp = Xp_Yp_Zp
z = inv(Zp, P)
return ((Xp * z**2) % P, (Yp * z**3) % P)
def jacobianDouble(Xp_Yp_Zp, A, P):
Xp, Yp, Zp = Xp_Yp_Zp
if not Yp:
return (0, 0, 0)
ysq = (Yp ** 2) % P
S = (4 * Xp * ysq) % P
M = (3 * Xp ** 2 + A * Zp ** 4) % P
nx = (M**2 - 2 * S) % P
ny = (M * (S - nx) - 8 * ysq ** 2) % P
nz = (2 * Yp * Zp) % P
return (nx, ny, nz)
def jacobianAdd(Xp_Yp_Zp, Xq_Yq_Zq, A, P):
Xp, Yp, Zp = Xp_Yp_Zp
Xq, Yq, Zq = Xq_Yq_Zq
if not Yp:
return (Xq, Yq, Zq)
if not Yq:
return (Xp, Yp, Zp)
U1 = (Xp * Zq ** 2) % P
U2 = (Xq * Zp ** 2) % P
S1 = (Yp * Zq ** 3) % P
S2 = (Yq * Zp ** 3) % P
if U1 == U2:
if S1 != S2:
return (0, 0, 1)
return jacobianDouble((Xp, Yp, Zp), A, P)
H = U2 - U1
R = S2 - S1
H2 = (H * H) % P
H3 = (H * H2) % P
U1H2 = (U1 * H2) % P
nx = (R ** 2 - H3 - 2 * U1H2) % P
ny = (R * (U1H2 - nx) - S1 * H3) % P
nz = (H * Zp * Zq) % P
return (nx, ny, nz)
def jacobianMultiply(Xp_Yp_Zp, n, N, A, P):
Xp, Yp, Zp = Xp_Yp_Zp
if Yp == 0 or n == 0:
return (0, 0, 1)
if n == 1:
return (Xp, Yp, Zp)
if n < 0 or n >= N:
return jacobianMultiply((Xp, Yp, Zp), n % N, N, A, P)
if (n % 2) == 0:
return jacobianDouble(jacobianMultiply((Xp, Yp, Zp), n // 2, N, A, P), A, P)
if (n % 2) == 1:
return jacobianAdd(jacobianDouble(jacobianMultiply((Xp, Yp, Zp), n // 2, N, A, P), A, P), (Xp, Yp, Zp), A, P)
class PrivateKey:
def __init__(self, curve=sm2p256v1, secret=None):
self.curve = curve
self.secret = secret or SystemRandom().randrange(1, curve.N)
def publicKey(self):
curve = self.curve
xPublicKey, yPublicKey = multiply((curve.Gx, curve.Gy), self.secret, A=curve.A, P=curve.P, N=curve.N)
return PublicKey(xPublicKey, yPublicKey, curve)
def toString(self):
return "{}".format(str(hex(self.secret))[2:].zfill(64))
class PublicKey:
def __init__(self, x, y, curve):
self.x = x
self.y = y
self.curve = curve
def toString(self, compressed=True):
return {
True: str(hex(self.x))[2:],
False: "{}{}".format(str(hex(self.x))[2:].zfill(64), str(hex(self.y))[2:].zfill(64))
}.get(compressed)
if __name__ == "__main__":
priKey = PrivateKey()
pubKey = priKey.publicKey()
print(priKey.toString())
print(pubKey.toString(compressed = False))
七、base64转16进制
由于提供的公私钥为base64格式,故要进行转码.
import base64
# base64解码
def base64_decode(base64_data):
temp = base64.b64decode(base64_data).hex()
return temp
data = "qgEeAGBFRQAAZEIAAFhCAAAAAAAAE0LFEAVqAAAHZhbn9rs="
tem = base64_decode(data)
print(tem)
四、其他格式互转
# 16进制转bytes
byte_arr = bytes.fromhex("1f2f3f4f")
# bytes转16进制
byte_arr.hex()
# bytes转base64,输入输出都是bytes
import base64
base64.b64encode(byte_arr)
# base64转bytes
base64.b64decode(base64_byte_arr)
# 字符串转bytes
"xxxxx".encode("UTF-8")
bytes(data,encoding='utf-8')
# bytes转字符串
str(data,encoding='utf-8')
data.decode('utf-8')
八、字符串与base64互转
字符串与base64不能直接转,需要先转到bytes
def strToBase64(s):
'''
将字符串转换为base64字符串
:param s:
:return:
'''
strEncode = base64.b64encode(s.encode('utf8')) # 转为base64, base64也是bytes
return strEncode.decode("utf")
def base64ToStr(s):
'''
将base64字符串转换为字符串
:param s:
:return:
'''
strDecode = base64.b64decode(bytes(s, encoding="utf8"))
网友评论