利用Django写一个sm2加密算法
时间: 2025-07-10 11:50:31 浏览: 18
<think>我们参考引用内容,特别是引用[4]提到了GmSSL库,它是支持国密SM2/SM3/SM4算法的OpenSSL分支。因此,在Django中实现SM2加密算法,我们可以使用GmSSL库(或者python的gmssl包)来提供SM2加密功能。步骤:1.安装gmssl包:使用pip安装gmssl库。2.在Django项目中,我们可以创建一个工具模块(例如crypto_utils.py)来实现SM2加密解密功能。3.在需要的地方调用这个工具模块。注意:SM2是非对称加密算法,需要生成密钥对。通常,公钥用于加密,私钥用于解密。示例代码:首先,安装gmssl包:```bashpipinstallgmssl```然后,在Django项目中创建一个crypto_utils.py文件,实现SM2加密解密:```pythonfromgmsslimportsm2,funcclassSM2Crypto:def__init__(self,private_key=None,public_key=None):#如果提供了私钥和公钥,则使用提供的密钥,否则生成新的密钥对ifprivate_keyisNoneorpublic_keyisNone:self.private_key,self.public_key=self.generate_key_pair()else:self.private_key=private_keyself.public_key=public_keyself.sm2_crypt=sm2.CryptSM2(public_key=self.public_key,private_key=self.private_key)@staticmethoddefgenerate_key_pair():"""生成SM2密钥对"""private_key=func.random_hex(sm2.KEY_LEN)#生成私钥public_key=sm2.CryptSM2(private_key=private_key).get_public_key()#根据私钥计算公钥returnprivate_key,public_keydefencrypt(self,data):"""使用公钥加密数据"""#注意:gmssl的sm2加密需要将数据转换为bytesdata_bytes=data.encode('utf-8')enc_data=self.sm2_crypt.encrypt(data_bytes)returnenc_data.hex()#返回十六进制字符串,方便存储defdecrypt(self,enc_data_hex):"""使用私钥解密数据"""#将十六进制字符串转换为bytesenc_data_bytes=bytes.fromhex(enc_data_hex)dec_data_bytes=self.sm2_crypt.decrypt(enc_data_bytes)returndec_data_bytes.decode('utf-8')#示例使用if__name__=='__main__':#实例化SM2Crypto,如果没有传入密钥,则自动生成sm2_crypto=SM2Crypto()print("私钥:",sm2_crypto.private_key)print("公钥:",sm2_crypto.public_key)#加密data="Hello,SM2加密!"enc_data=sm2_crypto.encrypt(data)print("加密结果:",enc_data)#解密dec_data=sm2_crypto.decrypt(enc_data)print("解密结果:",dec_data)```在Django中,我们可以将密钥对存储在安全的地方(比如环境变量或配置文件中),然后在需要加密解密的地方使用。例如,在视图函数中:```pythonfromdjango.httpimportJsonResponsefrom.crypto_utilsimportSM2Crypto#假设我们已经配置了公钥和私钥(这里从环境变量获取)importosprivate_key=os.getenv('SM2_PRIVATE_KEY')public_key=os.getenv('SM2_PUBLIC_KEY')sm2_crypto=SM2Crypto(private_key=private_key,public_key=public_key)defencrypt_view(request):ifrequest.method=='POST':data=request.POST.get('data')ifdata:enc_data=sm2_crypto.encrypt(data)returnJsonResponse({'encrypted_data':enc_data})else:returnJsonResponse({'error':'Nodataprovided'},status=400)else:returnJsonResponse({'error':'Methodnotallowed'},status=405)defdecrypt_view(request):ifrequest.method=='POST':enc_data=request.POST.get('encrypted_data')ifenc_data:try:dec_data=sm2_crypto.decrypt(enc_data)returnJsonResponse({'decrypted_data':dec_data})exceptExceptionase:returnJsonResponse({'error':str(e)},status=400)else:returnJsonResponse({'error':'Noencrypteddataprovided'},status=400)else:returnJsonResponse({'error':'Methodnotallowed'},status=405)```注意:在实际应用中,私钥必须严格保密,不能泄露。公钥可以公开。另外,引用[5]提到了公文管理中的解密操作,我们可以参考上述方法实现公文内容的加密存储和解密读取。安全建议:1.私钥的存储:使用环境变量或密钥管理服务(如Vault)存储私钥,避免硬编码在代码中。2.加密数据存储:将加密后的数据(十六进制字符串)存储在数据库中。以上就是在Django中实现SM2加密算法的基本方法。§§相关问题§§1.如何在Django中安全地存储SM2的私钥?2.除了SM2,国密算法还有哪些?在Django中如何实现?3.SM2加密算法的性能如何?在大量数据加密时需要注意什么?</think>### 在Django中实现SM2加密算法
在Django项目中实现国密SM2加密算法,推荐使用`GmSSL`库(引用[4]中提到的国密算法实现)。以下是完整实现步骤和示例代码:
#### 1. 安装依赖库
```bash
pip install gmssl pycryptodome
```
#### 2. 创建SM2工具类
在Django项目中创建`utils/crypto.py`文件:
```python
from gmssl import sm2, func
from Crypto.PublicKey import ECC
import base64
class SM2Crypto:
def __init__(self, private_key=None, public_key=None):
# 生成密钥对(若未提供)
if not private_key or not public_key:
key = ECC.generate(curve='SM2')
private_key = key.export_key(format='PEM')
public_key = key.public_key().export_key(format='PEM')
self.private_key = private_key
self.public_key = public_key
self.crypt_sm2 = sm2.CryptSM2(
private_key=self.extract_hex(private_key),
public_key=self.extract_hex(public_key)
)
@staticmethod
def extract_hex(pem_key):
"""从PEM格式提取16进制密钥"""
return ''.join(pem_key.split('\n')[1:-2])
def encrypt(self, plaintext):
"""SM2加密"""
ciphertext = self.crypt_sm2.encrypt(plaintext.encode())
return base64.b64encode(ciphertext).decode()
def decrypt(self, ciphertext):
"""SM2解密"""
cipher_bytes = base64.b64decode(ciphertext)
return self.crypt_sm2.decrypt(cipher_bytes).decode()
def sign(self, message):
"""生成数字签名"""
random_hex_str = func.random_hex(sm2.KEY_LEN)
signature = self.crypt_sm2.sign(message.encode(), random_hex_str)
return base64.b64encode(signature).decode()
def verify(self, message, signature):
"""验证数字签名"""
sig_bytes = base64.b64decode(signature)
return self.crypt_sm2.verify(sig_bytes, message.encode())
```
#### 3. 在Django视图中使用
在视图文件(如`views.py`)中:
```python
from django.http import JsonResponse
from .utils.crypto import SM2Crypto
# 初始化加密对象(实际项目中应从安全存储获取密钥)
sm2 = SM2Crypto()
def encrypt_data(request):
if request.method == 'POST':
data = request.POST.get('data')
encrypted = sm2.encrypt(data)
signature = sm2.sign(data)
return JsonResponse({
'encrypted': encrypted,
'signature': signature
})
def decrypt_data(request):
if request.method == 'POST':
encrypted = request.POST.get('encrypted')
signature = request.POST.get('signature')
plaintext = sm2.decrypt(encrypted)
# 验证签名(引用[5]公文管理需求)
if sm2.verify(plaintext, signature):
return JsonResponse({'decrypted': plaintext})
return JsonResponse({'error': '签名验证失败'}, status=400)
```
#### 4. 密钥管理建议
1. **安全存储**(引用[4]):
```python
# 从环境变量获取密钥
import os
private_key = os.getenv('SM2_PRIVATE_KEY')
public_key = os.getenv('SM2_PUBLIC_KEY')
sm2 = SM2Crypto(private_key, public_key)
```
2. **数据库加密**(引用[5]公文管理):
```python
from django.db import models
from .utils.crypto import SM2Crypto
class Document(models.Model):
content = models.TextField() # 存储加密文本
signature = models.CharField(max_length=255) # 存储签名
def set_encrypted_content(self, plaintext):
sm2 = SM2Crypto()
self.content = sm2.encrypt(plaintext)
self.signature = sm2.sign(plaintext)
def get_decrypted_content(self):
sm2 = SM2Crypto()
plaintext = sm2.decrypt(self.content)
if sm2.verify(plaintext, self.signature):
return plaintext
raise ValueError("公文签名无效")
```
#### 5. HTTPS配置(引用[3])
```bash
# 启动HTTPS服务
python manage.py runsslserver \
--certificate path/to/cert.crt \
--key path/to/private.key
```
### 关键注意事项
1. **密钥长度**:SM2密钥固定为256位(32字节)
2. **加密限制**:单次加密最大长度约200字节,长数据需分段处理
3. **性能优化**:频繁加密操作建议使用连接池
4. **合规性**:确保符合《密码法》要求,商用系统需使用认证硬件
> 实际部署时建议使用硬件加密模块(HSM)管理密钥[^4]
阅读全文
相关推荐

















