问题:后端将cryptography.py模块生成的公钥base64编码后传到前端,前端使用jsencrypt.js进行加密。加密后将密文传回后端,后端解密报错Ciphertext length must be equal to key size.
Traceback (most recent call last):
File "D:\Python3.12\Lib\site-packages\django\core\handlers\exception.py", line 55, in inner
response = get_response(request)
^^^^^^^^^^^^^^^^^^^^^
File "D:\Python3.12\Lib\site-packages\django\core\handlers\base.py", line 197, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "D:\Python3.12\Lib\site-packages\django\views\decorators\csrf.py", line 65, in _view_wrapper
return view_func(request, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "D:\xxx\xxx\django_demo\login\views.py", line 85, in register
a = encryption.decryption_from_rsa(request.session.get('private_key'), username)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "D:\xxx\xxx\django_demo\utils\encryption.py", line 44, in decryption_from_rsa
decrypted_data = private_key.decrypt(
^^^^^^^^^^^^^^^^^^^^
ValueError: Ciphertext length must be equal to key size.
疑问:将生成的私钥、前端base64解码后的公钥使用在线加密/解密平台进行解密是可以正常解密的,为什么使用cryptography.py进行解密就会报错???
相关Python代码
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import padding, rsa
def get_key() -> dict:
""" 获取公钥和私钥 """
private_key = rsa.generate_private_key(public_exponent=65537, key_size=2048, backend=default_backend())
public_key = private_key.public_key()
private_key_pem = private_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.PKCS8,
encryption_algorithm=serialization.NoEncryption()
).decode()
public_key_pem = public_key.public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo
).decode()
return {'private_key': private_key_pem, 'public_key': public_key_pem}
def decryption_from_rsa(private_key, encrypted_data) -> dict:
""" 数据解密 """
private_key = serialization.load_pem_private_key(private_key.encode(), password=None, backend=default_backend())
decrypted_data = private_key.decrypt(
encrypted_data,
padding.OAEP(mgf=padding.MGF1(algorithm=hashes.SHA256()), algorithm=hashes.SHA256(), label=None)
)
return {'decrypted_data': decrypted_data}
Django中views部分代码
from urllib.parse import unquote
def get_public(request):
""" 前端获取公钥的方法 """
encrypt_keys = encryption.get_key()
request.session.set_expiry(300)
request.session['private_key'] = encrypt_keys.get('private_key')
public_key = base64.b64encode(encrypt_keys.get('public_key').encode('utf-8'))
return HttpResponse(public_key)
def register(request):
""" 获取前端上传密文并解密 """
password = encryption.decryption_from_rsa(request.session.get('private_key'), unquote(base64.b64decode(request.POST.get('password'))).encode())
return HttpResponse(password)
HTML中的JS代码
function registerSubmit(){
$.ajax({
url: "/getPublic/",
type: "GET",
success: function (res) {
let password = hex_md5($('#password').val())
let encrypt = new JSEncrypt();
let public_key = decodeURIComponent(window.atob(res));
encrypt.setPublicKey(public_key);
password = window.btoa(encodeURIComponent(encrypt.encrypt(password)));
$.ajax({
url: "/register/",
type: "POST",
async: false,
data: { "password": password},
success: function(res){
console.log(res);
}
});
}
});
}
HTML代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script src="{% static "/js/jquery-3.5.1.min.js" %}"></script>
<script src="{% static "/plugins/jsencrypt/bin/jsencrypt.min.js" %}"></script>
<script src="{% static "/js/md5.js" %}"></script>
<title>Title</title>
</head>
<body>
密码:<label for="password"><input type="password" id="password" name="password"></label>
<button type="button" id="submit" onclick="registerSubmit()">注册</button>
</body>
</html>