使用 RSA 在 JavaScript 中加密并在 Python3 中解密
Use RSA to encrypt in JavaScript and decrypt in Python3
我正在开发一个网站,使用这个 JS 插件来加密一些数据并将其发送到服务器:https://github.com/travist/jsencrypt
我是运行 Python 3 Django,问题是我无法解密服务器上的数据。我的代码是:
JS代码:
pkey = "-----BEGIN PUBLIC KEY-----\
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDeVs9mcWUtTgi93/KXMNA/IF7S\
oQcZAmKQueygoDp9XUM3xnxPb/6XNpJQII85Hxbljqs/xuPVtxo5ovyJ+XXIPV8+\
eG6kSDmr2C3NpBUtfoUeADC/1H1jy44T6stBgXGMwTPokhjvSyEbGpkgMGo74Rpq\
q1vHofh3KcPNoaYH4wIDAQAB\
-----END PUBLIC KEY-----";
var encrypter = new JSEncrypt;
encrypter.setPublicKey(pkey);
encrypter.encrypt('Testing...');
我得到:
"STg7Fnm6Y6cAgMXEt4SxP8rbMb/pFB2X9Y1z8pAOoCNO9y8XuhVmQuG/FRBSqM+3ge43x9kfYMideAUu69RothwEOYmNnVrfwqm7SLm3voEcSXCqst2S7prTmCvYW43WyAAUl0vNxV+7xsm/yciQ4XV+jZSKd3xidbWL1BTTUw8="
Python代码:
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
from base64 import *
def decrypt(key, text):
if type(key) == str:
key = key.encode()
if type(text) == str:
text = text.encode()
rsakey = RSA.importKey(key)
rsakey = PKCS1_OAEP.new(rsakey)
d = rsakey.decrypt(text)
return d
text = "STg7Fnm6Y6cAgMXEt4SxP8rbMb/pFB2X9Y1z8pAOoCNO9y8XuhVmQuG/FRBSqM+3ge43x9kfYMideAUu69RothwEOYmNnVrfwqm7SLm3voEcSXCqst2S7prTmCvYW43WyAAUl0vNxV+7xsm/yciQ4XV+jZSKd3xidbWL1BTTUw8="
text = b64decode(text.encode())
with open('private.pem', 'rb') as f:
key = f.read()
decrypt(key, text)
我得到:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/local/lib/python3.2/dist-packages/Crypto/Cipher/PKCS1_OAEP.py", line 227, in decrypt
raise ValueError("Incorrect decryption.")
ValueError: Incorrect decryption.
我在这个例子中使用的私钥是:
-----BEGIN RSA PRIVATE KEY-----
MIICWwIBAAKBgQCO9YbJ8Z+tW0ucnMdXGNzmcvWaaLRGsx5iUHslbZ1tjec63HDm
6Hr2hv56u5zytyF4Cd/0lBNRC9qf/1XlEFqeSRifsyHZpPfyZn0fbHWYLH8g5FE4
VqrMe79ubSVx2eGWwwaLvEO+yaO1AF/fxWT6Ir8AUikMFFAnX+fBaA3XIwIDAQAB
AoGADxuniQP+CgYR8ZUoA+5eugQALLdQBgC7/0veF9CDyKYsf634SI7dH9yYXEQj
jAsKgHMatfBIMlJ8YlhLrY+S4+r26goNEqygtqetJ6NuePKQQ8xEERP4icsaBpY7
WqeU6AZOMlyq8o+e4DMnuxGpf8UT+lLx1G9AmVJf3+6NONECQQDLX94BmW//48Y6
yg9wnO6TR1msrGd1PFRqyJ9eilj8chI2JxiHkhepiTlBU7eyjUv4aeE7U84mp3Zo
AtPoiKmlAkEAs/OQM9IDttfgdS/yK6vZr1myNAbKOdv1rVId7MAspGHbN//gzb4s
r4mZKsIAi+jaDhpMvYbUxJe9y5HAY3XTJwJAe3hcZEQvRv+WHaMG9KuR/EBZJQgW
V4qlBZ9/gfokRD9M5yudLNF5JCh3Zj3ZTMGT2eEOKOKcScNpk4QD+yzdMQJAQlSM
Gd3WyqXmMav7qwdMVStN2YmLLyqZ80oqh6MKkYkUgh7KYWwxEn84ux8JjojFH5+o
G9BASzrXldrivIaozwJAVAHr9ON/altcDyh/OjkJff/3xXzHB3Zxvy4WykkO/PdF
tOqpAnYso3mCsEQsCcrJCflkFmJuYsvu4+Tm4GiqVg==
-----END RSA PRIVATE KEY-----
如果我尝试在 JS 上解密它,它会按预期工作:
private = "-----BEGIN RSA PRIVATE KEY-----\
MIICWwIBAAKBgQCO9YbJ8Z+tW0ucnMdXGNzmcvWaaLRGsx5iUHslbZ1tjec63HDm\
6Hr2hv56u5zytyF4Cd/0lBNRC9qf/1XlEFqeSRifsyHZpPfyZn0fbHWYLH8g5FE4\
VqrMe79ubSVx2eGWwwaLvEO+yaO1AF/fxWT6Ir8AUikMFFAnX+fBaA3XIwIDAQAB\
AoGADxuniQP+CgYR8ZUoA+5eugQALLdQBgC7/0veF9CDyKYsf634SI7dH9yYXEQj\
jAsKgHMatfBIMlJ8YlhLrY+S4+r26goNEqygtqetJ6NuePKQQ8xEERP4icsaBpY7\
WqeU6AZOMlyq8o+e4DMnuxGpf8UT+lLx1G9AmVJf3+6NONECQQDLX94BmW//48Y6\
yg9wnO6TR1msrGd1PFRqyJ9eilj8chI2JxiHkhepiTlBU7eyjUv4aeE7U84mp3Zo\
AtPoiKmlAkEAs/OQM9IDttfgdS/yK6vZr1myNAbKOdv1rVId7MAspGHbN//gzb4s\
r4mZKsIAi+jaDhpMvYbUxJe9y5HAY3XTJwJAe3hcZEQvRv+WHaMG9KuR/EBZJQgW\
V4qlBZ9/gfokRD9M5yudLNF5JCh3Zj3ZTMGT2eEOKOKcScNpk4QD+yzdMQJAQlSM\
Gd3WyqXmMav7qwdMVStN2YmLLyqZ80oqh6MKkYkUgh7KYWwxEn84ux8JjojFH5+o\
G9BASzrXldrivIaozwJAVAHr9ON/altcDyh/OjkJff/3xXzHB3Zxvy4WykkO/PdF\
tOqpAnYso3mCsEQsCcrJCflkFmJuYsvu4+Tm4GiqVg==\
-----END RSA PRIVATE KEY-----\
"
text = "STg7Fnm6Y6cAgMXEt4SxP8rbMb/pFB2X9Y1z8pAOoCNO9y8XuhVmQuG/FRBSqM+3ge43x9kfYMideAUu69RothwEOYmNnVrfwqm7SLm3voEcSXCqst2S7prTmCvYW43WyAAUl0vNxV+7xsm/yciQ4XV+jZSKd3xidbWL1BTTUw8="
encrypter.setPrivateKey(private);
encrypter.decrypt(text);
我得到:
"Testing"
但我无法让它在 Python 上运行。
我做错了什么?
jsencrypt 依赖于 jsbn 库,它不提供 OAEP,只提供 PKCS#1 v1.5 填充。
您必须在 PyCrypto 提供的 python 中使用相同的内容。只需使用 PKCS1_v1_5
而不是 PKCS1_OAEP
.
请注意,现在不应再使用 PKCS#1 v1.5 填充。我建议您使用 forge library,它提供了带有 OAEP 的 RSA 实现。
使用PKCS1_v1_5:
def decrypt(key, text):
if type(key) == str:
key = key.encode()
if type(text) == str:
text = text.encode()
rsakey = RSA.importKey(key)
rsakey = PKCS1_v1_5.new(rsakey)
d = rsakey.decrypt(text, 'bollox')
return d
>>> decrypt(key, text)
b'Testing'
我一直在使用 JSEncrypt JavaScript 文件来实现 JavaScript 和 Python 之间使用 pycrypto 的对话,但是在 JavaScript 加密期间它在函数中使用随机填充pkcs1pad2 需要删除并开始工作。这是一个 hack,但它成功了。以下是从函数 pkcs1pad2(s,n)
中注释掉的行
while(n > 2) { // random non-zero pad
x[0] = 0;
while(x[0] == 0) rng.nextBytes(x);
ba[--n] = x[0];
}
ba[--n] = 2;
ba[--n] = 0;
我正在开发一个网站,使用这个 JS 插件来加密一些数据并将其发送到服务器:https://github.com/travist/jsencrypt
我是运行 Python 3 Django,问题是我无法解密服务器上的数据。我的代码是:
JS代码:
pkey = "-----BEGIN PUBLIC KEY-----\
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDeVs9mcWUtTgi93/KXMNA/IF7S\
oQcZAmKQueygoDp9XUM3xnxPb/6XNpJQII85Hxbljqs/xuPVtxo5ovyJ+XXIPV8+\
eG6kSDmr2C3NpBUtfoUeADC/1H1jy44T6stBgXGMwTPokhjvSyEbGpkgMGo74Rpq\
q1vHofh3KcPNoaYH4wIDAQAB\
-----END PUBLIC KEY-----";
var encrypter = new JSEncrypt;
encrypter.setPublicKey(pkey);
encrypter.encrypt('Testing...');
我得到:
"STg7Fnm6Y6cAgMXEt4SxP8rbMb/pFB2X9Y1z8pAOoCNO9y8XuhVmQuG/FRBSqM+3ge43x9kfYMideAUu69RothwEOYmNnVrfwqm7SLm3voEcSXCqst2S7prTmCvYW43WyAAUl0vNxV+7xsm/yciQ4XV+jZSKd3xidbWL1BTTUw8="
Python代码:
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
from base64 import *
def decrypt(key, text):
if type(key) == str:
key = key.encode()
if type(text) == str:
text = text.encode()
rsakey = RSA.importKey(key)
rsakey = PKCS1_OAEP.new(rsakey)
d = rsakey.decrypt(text)
return d
text = "STg7Fnm6Y6cAgMXEt4SxP8rbMb/pFB2X9Y1z8pAOoCNO9y8XuhVmQuG/FRBSqM+3ge43x9kfYMideAUu69RothwEOYmNnVrfwqm7SLm3voEcSXCqst2S7prTmCvYW43WyAAUl0vNxV+7xsm/yciQ4XV+jZSKd3xidbWL1BTTUw8="
text = b64decode(text.encode())
with open('private.pem', 'rb') as f:
key = f.read()
decrypt(key, text)
我得到:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/local/lib/python3.2/dist-packages/Crypto/Cipher/PKCS1_OAEP.py", line 227, in decrypt
raise ValueError("Incorrect decryption.")
ValueError: Incorrect decryption.
我在这个例子中使用的私钥是:
-----BEGIN RSA PRIVATE KEY-----
MIICWwIBAAKBgQCO9YbJ8Z+tW0ucnMdXGNzmcvWaaLRGsx5iUHslbZ1tjec63HDm
6Hr2hv56u5zytyF4Cd/0lBNRC9qf/1XlEFqeSRifsyHZpPfyZn0fbHWYLH8g5FE4
VqrMe79ubSVx2eGWwwaLvEO+yaO1AF/fxWT6Ir8AUikMFFAnX+fBaA3XIwIDAQAB
AoGADxuniQP+CgYR8ZUoA+5eugQALLdQBgC7/0veF9CDyKYsf634SI7dH9yYXEQj
jAsKgHMatfBIMlJ8YlhLrY+S4+r26goNEqygtqetJ6NuePKQQ8xEERP4icsaBpY7
WqeU6AZOMlyq8o+e4DMnuxGpf8UT+lLx1G9AmVJf3+6NONECQQDLX94BmW//48Y6
yg9wnO6TR1msrGd1PFRqyJ9eilj8chI2JxiHkhepiTlBU7eyjUv4aeE7U84mp3Zo
AtPoiKmlAkEAs/OQM9IDttfgdS/yK6vZr1myNAbKOdv1rVId7MAspGHbN//gzb4s
r4mZKsIAi+jaDhpMvYbUxJe9y5HAY3XTJwJAe3hcZEQvRv+WHaMG9KuR/EBZJQgW
V4qlBZ9/gfokRD9M5yudLNF5JCh3Zj3ZTMGT2eEOKOKcScNpk4QD+yzdMQJAQlSM
Gd3WyqXmMav7qwdMVStN2YmLLyqZ80oqh6MKkYkUgh7KYWwxEn84ux8JjojFH5+o
G9BASzrXldrivIaozwJAVAHr9ON/altcDyh/OjkJff/3xXzHB3Zxvy4WykkO/PdF
tOqpAnYso3mCsEQsCcrJCflkFmJuYsvu4+Tm4GiqVg==
-----END RSA PRIVATE KEY-----
如果我尝试在 JS 上解密它,它会按预期工作:
private = "-----BEGIN RSA PRIVATE KEY-----\
MIICWwIBAAKBgQCO9YbJ8Z+tW0ucnMdXGNzmcvWaaLRGsx5iUHslbZ1tjec63HDm\
6Hr2hv56u5zytyF4Cd/0lBNRC9qf/1XlEFqeSRifsyHZpPfyZn0fbHWYLH8g5FE4\
VqrMe79ubSVx2eGWwwaLvEO+yaO1AF/fxWT6Ir8AUikMFFAnX+fBaA3XIwIDAQAB\
AoGADxuniQP+CgYR8ZUoA+5eugQALLdQBgC7/0veF9CDyKYsf634SI7dH9yYXEQj\
jAsKgHMatfBIMlJ8YlhLrY+S4+r26goNEqygtqetJ6NuePKQQ8xEERP4icsaBpY7\
WqeU6AZOMlyq8o+e4DMnuxGpf8UT+lLx1G9AmVJf3+6NONECQQDLX94BmW//48Y6\
yg9wnO6TR1msrGd1PFRqyJ9eilj8chI2JxiHkhepiTlBU7eyjUv4aeE7U84mp3Zo\
AtPoiKmlAkEAs/OQM9IDttfgdS/yK6vZr1myNAbKOdv1rVId7MAspGHbN//gzb4s\
r4mZKsIAi+jaDhpMvYbUxJe9y5HAY3XTJwJAe3hcZEQvRv+WHaMG9KuR/EBZJQgW\
V4qlBZ9/gfokRD9M5yudLNF5JCh3Zj3ZTMGT2eEOKOKcScNpk4QD+yzdMQJAQlSM\
Gd3WyqXmMav7qwdMVStN2YmLLyqZ80oqh6MKkYkUgh7KYWwxEn84ux8JjojFH5+o\
G9BASzrXldrivIaozwJAVAHr9ON/altcDyh/OjkJff/3xXzHB3Zxvy4WykkO/PdF\
tOqpAnYso3mCsEQsCcrJCflkFmJuYsvu4+Tm4GiqVg==\
-----END RSA PRIVATE KEY-----\
"
text = "STg7Fnm6Y6cAgMXEt4SxP8rbMb/pFB2X9Y1z8pAOoCNO9y8XuhVmQuG/FRBSqM+3ge43x9kfYMideAUu69RothwEOYmNnVrfwqm7SLm3voEcSXCqst2S7prTmCvYW43WyAAUl0vNxV+7xsm/yciQ4XV+jZSKd3xidbWL1BTTUw8="
encrypter.setPrivateKey(private);
encrypter.decrypt(text);
我得到:
"Testing"
但我无法让它在 Python 上运行。
我做错了什么?
jsencrypt 依赖于 jsbn 库,它不提供 OAEP,只提供 PKCS#1 v1.5 填充。
您必须在 PyCrypto 提供的 python 中使用相同的内容。只需使用 PKCS1_v1_5
而不是 PKCS1_OAEP
.
请注意,现在不应再使用 PKCS#1 v1.5 填充。我建议您使用 forge library,它提供了带有 OAEP 的 RSA 实现。
使用PKCS1_v1_5:
def decrypt(key, text):
if type(key) == str:
key = key.encode()
if type(text) == str:
text = text.encode()
rsakey = RSA.importKey(key)
rsakey = PKCS1_v1_5.new(rsakey)
d = rsakey.decrypt(text, 'bollox')
return d
>>> decrypt(key, text)
b'Testing'
我一直在使用 JSEncrypt JavaScript 文件来实现 JavaScript 和 Python 之间使用 pycrypto 的对话,但是在 JavaScript 加密期间它在函数中使用随机填充pkcs1pad2 需要删除并开始工作。这是一个 hack,但它成功了。以下是从函数 pkcs1pad2(s,n)
中注释掉的行while(n > 2) { // random non-zero pad
x[0] = 0;
while(x[0] == 0) rng.nextBytes(x);
ba[--n] = x[0];
}
ba[--n] = 2;
ba[--n] = 0;