首页 > 编程语言 >基于OpenSSL(GMSSL)的国密算法的应用

基于OpenSSL(GMSSL)的国密算法的应用

时间:2023-06-08 12:12:48浏览次数:58  
标签:return plaintext bytes OpenSSL GMSSL 国密 key SM2 def

===
基于OpenSSL(GMSSL)的国密算法的应用

1.gmssl介绍

GmSSL是一个开源的加密包的python实现,支持SM2/SM3/SM4等国密(国家商用密码)算法、项目采用对商业应用友好的类BSD开源许可证,开源且可以用于闭源的商业应用。

2.安装gmssl包

相关包网址:https://pypi.org/project/gmssl/
在终端输入:pip install gmssl进行安装

3.国密算法调用实现

3.1sm2test.py

import sys
import os
import base64
import binascii
import sm2
import random
import string
import math
import sys
import os
import binascii
import struct
encoding = 'utf-8'

def SM2_enc(plaintext, pk,sk):
    sm2_crypt = sm2.CryptSM2(public_key=pk, private_key=sk)
    ciphertext=sm2_crypt.encrypt(plaintext)
    return ciphertext

# SM2 decryption


def SM2_dec(ciphertext, sk,pk):
    sm2_crypt = sm2.CryptSM2(public_key=pk, private_key=sk)
    plaintext = sm2_crypt.decrypt(ciphertext)
    return plaintext

# SM2 experiment with string

#密钥生成
# key generation


def SM2_Mulyipoint(k, P, a, p):  # 多倍点运算
	k_b = bin(k).replace('0b', '')  # 按2^i分层逐层运算
	i = len(k_b)-1
	R = P
	if i > 0:
		k = k-2**i
		while i > 0:
			R = SM2_Pluspoint(R, R, a, p)
			i -= 1
		if k > 0:
			R = SM2_Pluspoint(R, SM2_Mulyipoint(k, P, a, p), a, p)
	return R


def SM2_Pluspoint(P, Q, a, p):  # 双倍点运算
	if (math.isinf(P[0]) or math.isinf(P[1])) and (~math.isinf(Q[0]) and ~math.isinf(Q[1])):  # OP = P
		R = Q
	elif (~math.isinf(P[0]) and ~math.isinf(P[1])) and (math.isinf(Q[0]) or math.isinf(Q[1])):  # PO = P
		R = P
	elif (math.isinf(P[0]) or math.isinf(P[1])) and (math.isinf(Q[0]) or math.isinf(Q[1])):  # OO = O
		R = [float('inf'), float('inf')]
	else:
		if P != Q:
			l = SM2__Mod_Decimal(Q[1]-P[1], Q[0]-P[0], p)
		else:
			l = SM2__Mod_Decimal(3*P[0]**2+a, 2*P[1], p)
		x = SM2_Mod(l**2-P[0]-Q[0], p)
		y = SM2_Mod(l*(P[0]-x)-P[1], p)
		R = [x, y]
	return R


def SM2_Mod(a, b):  # 摸运算
	if math.isinf(a):
		return float('inf')
	else:
		return a % b


def SM2__Mod_Decimal(n, d, b):  # 小数的模运算
	if d == 0:
		x = float('inf')
	elif n == 0:
		x = 0
	else:
		a = bin(b-2).replace('0b', '')
		y = 1
		i = 0
		while i < len(a):  # n/d = x mod b => x = n*d^(b-2) mod b
			y = (y**2) % b  # 快速指数运算
			if a[i] == '1':
				y = (y*d) % b
			i += 1
		x = (y*n) % b
	return x


def key_gen(a, p, n, G):  # SM2密钥对的生成

    sk = random.randint(1, n-2)
    pk = SM2_Mulyipoint(sk, G, a, p)
    return sk, pk


def write_key():
    p = 0xFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF
    a = 0xFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC
    b = 0x28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93
    n = 0xFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123
    Gx = 0x32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7
    Gy = 0xBC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0
    G = [Gx, Gy]
    [sk, pk] = key_gen(a, p, n, G)
    fw = open("sm2d.txt", 'w')
    fw.write("%X" % sk)

    fw = open("sm2p.txt", 'w')
    fw.write("%X%X" % (pk[0], pk[1]))

def bytes2hex(bytesData):
    hex = binascii.hexlify(bytesData) 
    
    return hex.decode()

def exp_SM2_str(plaintext):
    plaintext_bytes = bytes(plaintext,encoding='utf-8')
    return plaintext_bytes


def sm2e(emm):
    write_key()
    sf = open("sm2d.txt", encoding='utf-8')
    sk = (sf.read())
    print("puba为:", sk)
    f = open("sm2p.txt", encoding='utf-8')
    pk = (f.read())
    print("pria为:", pk)

    sm2_crypt = sm2.CryptSM2(public_key=pk, private_key=sk)
    plaintext_bytes = exp_SM2_str(emm)
    ciphertext = SM2_enc(plaintext_bytes, pk,sk)
    return ciphertext


def sm2ee(emm):
    sf = open("sm2d.txt", encoding='utf-8')
    sk = (sf.read())
    f = open("sm2p.txt", encoding='utf-8')
    pk = (f.read())

    sm2_crypt = sm2.CryptSM2(public_key=pk, private_key=sk)
    plaintext_bytes = exp_SM2_str(emm)
    ciphertext = SM2_enc(plaintext_bytes, pk, sk)
    return ciphertext


def sm2d(ecm):
    sf = open("sm2d.txt", encoding='utf-8')
    sk =sf.read()
    print("puba为:", sk)
    f = open("sm2p.txt", encoding='utf-8')
    pk = (f.read())
    print("pria为:", pk)

    sm2_crypt = sm2.CryptSM2(public_key=pk, private_key=sk)
    plaintext = SM2_dec(ecm, sk,pk)
    return plaintext

3.2 sm3test.py

import sm3

def sm3_hash(message:bytes):
    """
    国密sm3加密
    :param message: 消息值,bytes类型
    :return: 哈希值
    """
    
    msg_list = [i for i in message]
    hash_hex = sm3.sm3_hash(msg_list)
    print(hash_hex)

    # bytes2hex(hash_hex);

    hash_bytes = bytes.fromhex(hash_hex)
    print(hash_bytes)

    # return bytes.hash
    # return hash

3.3sm4test.py


import string
import random
from sm4 import CryptSM4, SM4_ENCRYPT, SM4_DECRYPT
import func


crypt_sm4 = CryptSM4()


def gen_key(bits):
    #key = random.randbytes(15)
    #key = random.sample('zyxwvutsrqponmlkjihgfedcba1234567890', 5)
    num_set = [chr(i) for i in range(48, 58)]
    char_set = [chr(i) for i in range(97, 123)]
    total_set = num_set + char_set
    key = "".join(random.sample(total_set, bits))
    #key = ''.join(random.sample(string.ascii_letters + string.digits, 15))
    return key


def iv_gen(bits):
    num_set = [chr(i) for i in range(48, 58)]
    char_set = [chr(i) for i in range(97, 123)]
    total_set = num_set + char_set
    iv = "".join(random.sample(total_set, bits))
    #iv = ''.join(random.sample(string.ascii_letters + string.digits, 15))
    return iv


def SM4_ecb_enc(plaintext, key):
    crypt_sm4.set_key(key, SM4_ENCRYPT)
    ciphertext_bytes = crypt_sm4.crypt_ecb(plaintext)

    return ciphertext_bytes


def SM4_ecb_dec(ciphertext, key):
    crypt_sm4 = CryptSM4()
    crypt_sm4.set_key(key, SM4_DECRYPT)
    plaintext_bytes = crypt_sm4.crypt_ecb(ciphertext)

    return plaintext_bytes


def SM4_cbc_enc(plaintext, iv, key):
    crypt_sm4.set_key(key, SM4_ENCRYPT)
    ciphertext_bytes = crypt_sm4.crypt_cbc(iv, plaintext)  # bytes类型

    return ciphertext_bytes


def SM4_cbc_dec(ciphertext, iv, key):
    crypt_sm4.set_key(key, SM4_DECRYPT)
    plaintext_bytes = crypt_sm4.crypt_cbc(iv, ciphertext)

    return plaintext_bytes


def exp_SM4_str(plaintext):
    plaintext_bytes = bytes(plaintext, encoding="utf8")
    return plaintext_bytes


def exp_SM4_file(filename):
    with open(filename, "rb") as f:
        plaintext_bytes = f.read()
    f.close()
    return plaintext_bytes

def get_key():
    key = gen_key(16)
    key_bytes = bytes(key, encoding="utf8")
    with open('key_bytes.txt', 'wb') as f:
        f.truncate()
        f.write(key_bytes)
    f.close
    print("key为:", key)
    return key_bytes
def get_iv():
    iv = iv_gen(16)
    iv_bytes = bytes(iv, encoding="utf8")    
    return iv_bytes

4.功能设计

1.用户注册时,系统随机生成一个salt值,将salt与用户输入的口令拼接后利用sm3算法计算hash值,将salt、hash、用户名存储在数据库中。

2.用户登录时,客户端将用户输入的用户名传到服务端,服务端根据用户名检索数据库,取出对应的salt和hash。

3.服务端利用sm4算法生成对称密钥SK,用SK给salt加密得到密文ECM,再将ECM和SK一起用sm2客户端公钥进行加密得到密文EMM并传给客户端。

4.客户端用自己的sm2私钥解密后得到ECM和SK,再用SK解密ECM得到salt。

5.客户端用salt和用户输入的口令拼接后利用sm3算法计算新hash值,并将新hash值传给服务端。

6.服务端将两个hash值进行比较,将结果返回给客户端。

7.若两个hash值相同,说明用户输入口令正确,可以登录;反之,说明用户输入口令不正确,提示用户重新输入口令。

5.项目代码

由于本项目主要研究gmssl的应用,客户端、服务端、数据库的搭建并不是重点,因此本项目暂时没有实现这几个功能,选择用本地文件模拟数据库的存取。
项目代码已发至码云:https://gitee.com/yu-yingpeng/gmssl/

6.运行示例

6.1注册

6.2登录成功

6.3登录失败

7.参考文献:

1.在Python中运行gmssl(https://www.cnblogs.com/rocedu/p/15518988.html)
2.国密算法在 CAS 系统中的应用探讨 朱泽智 冯燕强 冯智明 桂广网技专栏

标签:return,plaintext,bytes,OpenSSL,GMSSL,国密,key,SM2,def
From: https://www.cnblogs.com/quicci/p/17465741.html

相关文章

  • 虚拟机上安装nginx、openssl、pcre、zlib步骤
    1、下载相关组件:wget http://nginx.org/download/nginx-1.10.2.tar.gzopenssl是一个开源的实现加解密和证书的专业系统。wget http://www.openssl.org/source/openssl-fips-2.0.10.tar.gzopenssl是一个开源的实现加解密和证书的专业系统。wgethttp://downloads.sourcefo......
  • openssl编译 windows
    由于需要使用rsa非对称加密开发一个注册机功能,所以需要使用openssl1下载openssl源码,github搜索一下2安装perl3安装nasm并设置为环境变量4使用vsdev命令提示符,加载64位的编译环境5配置openssl6nmake编译7nmaketest7nmakeinstallhttps://github.com/open......
  • 实验一 密码引擎-1-OpenEuler-OpenSSL编译
    一、任务详情安装Ubuntu和OpenEuler虚拟机下载最新的OpenSSL源码(1.1版本)用自己的8位学号建立一个文件夹,cd你的学号,用pwd获得绝对路径参考https://www.cnblogs.com/rocedu/p/5087623.html先在Ubuntu中完成OpenSSL编译安装,然后在OpenEuler中重现./config--prefix=..(......
  • 实验一 密码引擎-1-OpenEuler-OpenSSL编译
    安装Ubuntu和OpenEuler虚拟机下载最新的OpenSSL源码(1.1版本)用自己的8位学号建立一个文件夹,cd你的学号,用pwd获得绝对路径参考https://www.cnblogs.com/rocedu/p/5087623.html先在Ubuntu中完成OpenSSL编译安装,然后在OpenEuler中重现./config--prefix=..(学号目录的绝对路......
  • OpenSSL-SM2
    任务详情在openEuler(推荐)或Ubuntu或Windows(不推荐)中完成下面任务编译运行 https://github.com/greendow/SM2-signature-creation-and-verification 中的代码,提交运行结果与截图,(7‘)编译运行 https://github.com/greendow/SM2-encrypt-and-decrypt 中的代码提交运行结果......
  • OpenSSL-SM2
    OpenSSL-SM2在openEuler(推荐)或Ubuntu或Windows(不推荐)中完成下面任务编译运行https://github.com/greendow/SM2-signature-creation-and-verification中的代码,提交运行结果与截图,(7‘)编译运行https://github.com/greendow/SM2-encrypt-and-decrypt中的代码提交运行结果与......
  • OpenSSL-SM2
    任务详情在openEuler(推荐)或Ubuntu或Windows(不推荐)中完成下面任务编译运行https://github.com/greendow/SM2-signature-creation-and-verification中的代码,提交运行结果与截图,(7‘)编译运行https://github.com/greendow/SM2-encrypt-and-decrypt中的代码提交运行结果与截......
  • OpenSSL-SM2
    任务详情在openEuler(推荐)或Ubuntu或Windows(不推荐)中完成下面任务编译运行https://github.com/greendow/SM2-signature-creation-and-verification中的代码,提交运行结果与截图,(7‘)编译运行https://github.com/greendow/SM2-encrypt-and-decrypt中的代码提交运行结果与截......
  • 关于使用openssl命令-同时生成私钥与CSR-Certificate Signing Request的方法记录
    这里笔者主要讲述如何生成一个CSR证书签名请求文件,方法过程可能有多种笔者这里将使用一种最为简单简洁的方式进行讲解,使用到的环境与软件如下:操作系统:RedHatEnterpriseLinuxrelease8.7(Ootpa)openssl软件包版本:openssl-1.1.1k-9.el8_7.x86_64 1、创建私钥的同时,也就同......
  • OpenSSL-SM2
    在openEuler(推荐)或Ubuntu或Windows(不推荐)中完成下面任务编译运行https://github.com/greendow/SM2-signature-creation-and-verification中的代码,提交运行结果与截图,(7‘)编译运行https://github.com/greendow/SM2-encrypt-and-decrypt中的代码提交运行结果与截图(8’)用Ope......