【问题标题】:rsa encryption with javascrypt decrypt in python在python中使用javascrypt解密的rsa加密
【发布时间】:2021-08-18 16:07:17
【问题描述】:

我正在尝试使用混合加密 js 在 javascript 中使用 Wix-Velo 进行加密, 并使用 PKCS1_v1_5 使用 python 解密,我收到不正确的长度错误。

这是我的 Javascript 代码:

    var Crypt = require('hybrid-crypto-js').Crypt;
    var crypt = new Crypt();

    var publicKey = "publicKey";

    var privateKey = "privateKey";

    var message = 'Hello world!';
    
    // Encryption with one public RSA key
    var encrypted = crypt.encrypt(publicKey, message);

在python中:


def decrypt_rsa(data: bytes, key: str = rsa_key) -> str:
    key = key.replace("-----BEGIN RSA PRIVATE KEY-----", "").replace("-----END RSA PRIVATE KEY-----",
                                                                     "").replace("\n", "")
    key = b64decode(key)
    key = RSA.importKey(key)

    cipher = PKCS1_v1_5.new(key)
    return cipher.decrypt(data, "Error while decrypting".encode('utf-8')).decode('utf-8')

【问题讨论】:

  • hybrid-crypto-js 应用混合加密,即使用 AES/CBC 加密消息,使用 RSA/OAEP 加密 AES 密钥。密文包含加密的 AES 密钥、加密的消息和 IV 等内容。因此,在 Python 代码中,必须首先解密 AES 密钥,然后使用密钥和 IV 解密带有 AES 的消息。目前,仅执行 RSA 解密(不清楚解密了什么数据),其中填充(PKCS#1 v1.5)是错误的。缺少 AES 部分。顺便说一句,PyCryptodome 也接受 PEM 编码的密钥。
  • 嗨。谢谢您的回答。我对python方面有点困惑。你能分享这个问题的代码吗?另外,我已经修复了 javascript 端的数据输入

标签: javascript python encryption velo


【解决方案1】:

解释这一点的最简单方法是举个例子。示例使用以下密钥对:

var publicKey = `-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCfm2uMTvb+gqXRFxWHnfCKcHfH
v7aMN6oiEqTJj0BixtTYBXH89N+xuYgoIBnfMXPXPIg/UNWEOZtAETsOVvya+YBo
ZZTquYJ2I0PaxtpUKkpCiEQ/bTCQIDAeUwHr0l4vUn/fmslD0rZ3+jo4Dsl8nX0O
pwZQ2grQaXLb347RQwIDAQAB
-----END PUBLIC KEY-----`;

var privateKey = `-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQCfm2uMTvb+gqXRFxWHnfCKcHfHv7aMN6oiEqTJj0BixtTYBXH8
9N+xuYgoIBnfMXPXPIg/UNWEOZtAETsOVvya+YBoZZTquYJ2I0PaxtpUKkpCiEQ/
bTCQIDAeUwHr0l4vUn/fmslD0rZ3+jo4Dsl8nX0OpwZQ2grQaXLb347RQwIDAQAB
AoGBAJHi3s/10X/a7TOMFQrLy3TOzj1PN808iA7y2Zq+jIx8z0nQ2FrtfJYXTqPW
i69dpVOkKakt+qwMd6J83W0DB4oyRAQriBPI2BNuTQguzeBmvC3bkrAhbfRU313G
fdlUFprS+LTvb0+KCbAMM8/I0pwQMZm0K1lWSp7ILkW2/ICJAkEAz22+7TN9bx44
0VYm2HunmbuDA5APwDmBl9VmDCCcB9/mHPbHXIuMHAWxaZma+euq2uLeCdCzVdwE
nk3bSNhLFwJBAMT7BeJLuob6iA4BsUyfjxQjdjTMaP4J6JWCfcFQvd2hcwcikm/W
0qcbrKv8yCgMg1C0U9iwV3g+G6RRobbYVrUCQQDLNN1FLRsl33qUAY0+qS0Q2vTH
abs0emGtqB43pT6WLE8Xct7tl7vju+QI6rU7Pxd7JaOWBAGcDFXt66H2ZAZzAkA4
sHmgB+VVpVJ0nX4WLDF0PURuq4ln2xgptxVUBlWuLCG7ovJ751pWp3tJQAWmqPs9
xbf/u7hgrZcs8iVVRuulAkBAoBFO1gN1utEtr97z3lHSHjL150Tqu/w0qXI4lbuH
CaAiwWj6QRUnVkYlVK56Nzl/S3MLc6OT9GN9X/B+1Ebl
-----END RSA PRIVATE KEY-----`

由于空间原因,使用 1024 位密钥。但是请注意,出于安全原因,现在必须在实践中使用大小至少为 2048 位的 RSA 密钥。

使用此密钥对发布的 JavaScript 代码的一个可能输出是:

{
    "v":"hybrid-crypto-js_0.2.4",
    "iv":"qAoNKj6kM0whA07xOdeiPVLF2ntPjKXWXdmy0IhJmF0=",
    "keys":{"e7:de:4a:da:6b:c8:ed:3a:bd:70:4d:87:23:99:9a:23:2a:ad:17:f8":"NvpGk/XyB+m+gC/d/Bzp16xXjxNKIJq4SAsz4y11OWQJa9K42jzjona18CJnsP6OZh/wmF709KgX7ZGYnqVGswQ0Q2PpLpG39t7ipj/N6taqkAy9Mydstt4Agdu5dQ8wLCSBpU3NNrgp6T06nI0Y1ISX2H45kgI47PeQnjYB4gQ="},
    "cipher":"JZIHkdUd1NuKt2aj2OMdLQ=="
}

第一个元素是版本,第二个是 IV,第三个是使用 RSA/OAEP 加密的 AES 密钥,第四个是使用 AES-256/CBC 加密的密文,s。 Hybrid Crypto JS.

要解密密钥,可以使用发布的 Python/PyCryptodome 代码,将填充从 PKCS#1 v1.5 更改为 OAEP,并使用上述 RSA 密钥和密文:

from Crypto.Cipher import PKCS1_OAEP
from Crypto.PublicKey import RSA
import base64

privateKey = """-----BEGIN RSA PRIVATE KEY-----
    MIICXQIBAAKBgQCfm2uMTvb+gqXRFxWHnfCKcHfHv7aMN6oiEqTJj0BixtTYBXH8
    9N+xuYgoIBnfMXPXPIg/UNWEOZtAETsOVvya+YBoZZTquYJ2I0PaxtpUKkpCiEQ/
    bTCQIDAeUwHr0l4vUn/fmslD0rZ3+jo4Dsl8nX0OpwZQ2grQaXLb347RQwIDAQAB
    AoGBAJHi3s/10X/a7TOMFQrLy3TOzj1PN808iA7y2Zq+jIx8z0nQ2FrtfJYXTqPW
    i69dpVOkKakt+qwMd6J83W0DB4oyRAQriBPI2BNuTQguzeBmvC3bkrAhbfRU313G
    fdlUFprS+LTvb0+KCbAMM8/I0pwQMZm0K1lWSp7ILkW2/ICJAkEAz22+7TN9bx44
    0VYm2HunmbuDA5APwDmBl9VmDCCcB9/mHPbHXIuMHAWxaZma+euq2uLeCdCzVdwE
    nk3bSNhLFwJBAMT7BeJLuob6iA4BsUyfjxQjdjTMaP4J6JWCfcFQvd2hcwcikm/W
    0qcbrKv8yCgMg1C0U9iwV3g+G6RRobbYVrUCQQDLNN1FLRsl33qUAY0+qS0Q2vTH
    abs0emGtqB43pT6WLE8Xct7tl7vju+QI6rU7Pxd7JaOWBAGcDFXt66H2ZAZzAkA4
    sHmgB+VVpVJ0nX4WLDF0PURuq4ln2xgptxVUBlWuLCG7ovJ751pWp3tJQAWmqPs9
    xbf/u7hgrZcs8iVVRuulAkBAoBFO1gN1utEtr97z3lHSHjL150Tqu/w0qXI4lbuH
    CaAiwWj6QRUnVkYlVK56Nzl/S3MLc6OT9GN9X/B+1Ebl
    -----END RSA PRIVATE KEY-----"""

ciphertext = base64.b64decode("NvpGk/XyB+m+gC/d/Bzp16xXjxNKIJq4SAsz4y11OWQJa9K42jzjona18CJnsP6OZh/wmF709KgX7ZGYnqVGswQ0Q2PpLpG39t7ipj/N6taqkAy9Mydstt4Agdu5dQ8wLCSBpU3NNrgp6T06nI0Y1ISX2H45kgI47PeQnjYB4gQ=")
key = RSA.importKey(privateKey)
cipher = PKCS1_OAEP.new(key)
message = cipher.decrypt(ciphertext)

print(message.hex()) # 8ec759594b7cc96c44d624f5a58bf736a9f761f3191de2fd0ff1e5c2bb3a8868

现在可以解密实际的密文了:

from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
from base64 import b64decode

iv = b64decode("qAoNKj6kM0whA07xOdeiPVLF2ntPjKXWXdmy0IhJmF0=")[:AES.block_size]
key = bytes.fromhex("8ec759594b7cc96c44d624f5a58bf736a9f761f3191de2fd0ff1e5c2bb3a8868")
ciphertext = b64decode("JZIHkdUd1NuKt2aj2OMdLQ==")
cipher = AES.new(key, AES.MODE_CBC, iv)
decrypted = unpad(cipher.decrypt(ciphertext), AES.block_size)
print(str(len(decrypted)) + " - " + decrypted.decode('utf-8')) # 12 - Hello world!

请注意,IV 的长度为 32 个字节,其中只有前 16 个字节(对应于 AES 块大小)用于 AES。

为了完整起见:JavaScript 代码密文中使用的指纹e7:de...17:f8 是 PKCS#1 格式的公钥的 SHA1 哈希,DER 编码。

【讨论】:

    猜你喜欢
    • 2015-07-15
    • 1970-01-01
    • 1970-01-01
    • 2011-07-04
    • 2013-03-17
    • 2012-03-13
    • 1970-01-01
    • 1970-01-01
    • 2015-03-16
    相关资源
    最近更新 更多