简体   繁体   English

使用 PKCS1-V1_5 (JavaScript) 进行 RSA 加密

[英]RSA encrypt with PKCS1-V1_5 (JavaScript)

I would like to encrypt my password using Public Key in RSA format with PKCS1-1.5 padding.我想使用带有 PKCS1-1.5 填充的 RSA 格式的公钥来加密我的密码。 Currently I try to use forge library from https://github.com/digitalbazaar/forge .目前我尝试使用https://github.com/digitalbazaar/forge 中的forge库。 Part of the solution uses Tom Wu's BigInteger() .部分解决方案使用 Tom Wu 的BigInteger()

modulus = new forge.jsbn.BigInteger(modulus,16);
exponent =  new forge.jsbn.BigInteger(exponent, 16);
var text = "Password";
var rsa = forge.pki.rsa;
var publicKey = rsa.setPublicKey(modulus, exponent);
var encryptedData = publicKey.encrypt(text, 'RSAES-PKCS1-V1_5');

provided exponent - 10001 seems to be parsed properly in BigInteger() as it returns single item array - 65537.提供的指数 - 10001 似乎在BigInteger()被正确解析,因为它返回单个项目数组 - 65537。

However when I push modulus 9bedc7ad20bdacf930f1471d0c2a9f7f1895e24d73957b145b621e7800589ec14a3122df556fae94cc45df7b1f5003062df5681a18d8165377a6dece1a8c36e0af6ce13e89890b6813eb94135bd8c4b2b743ef6d24cfc09cbd59a8105c3f31d56a0224b1db14c2e6396493571ef83d664c5b6169a1b42f988cfc3f7d39d50aa9然而,当我推模9bedc7ad20bdacf930f1471d0c2a9f7f1895e24d73957b145b621e7800589ec14a3122df556fae94cc45df7b1f5003062df5681a18d8165377a6dece1a8c36e0af6ce13e89890b6813eb94135bd8c4b2b743ef6d24cfc09cbd59a8105c3f31d56a0224b1db14c2e6396493571ef83d664c5b6169a1b42f988cfc3f7d39d50aa9

I get something strange as BigInteger() results: modulus screenshot我得到一些奇怪的BigInteger()结果:模数屏幕截图

Therefore RSA keypair created later in the code is wrong.因此,稍后在代码中创建的 RSA 密钥对是错误的。 Could anyone point me to the right direction?有人能指出我正确的方向吗? What is even more frustrating is that I have working .py script and cannot convert it to JS.. I cannot use any server side programming here.更令人沮丧的是,我有工作 .py 脚本,但无法将其转换为 JS .. 我无法在这里使用任何服务器端编程。 (I am aware of the issues / risks with JS password encryption btw). (顺便说一下,我知道 JS 密码加密的问题/风险)。

Update更新

Here's the working python Script:这是工作的python脚本:

import binascii
import Crypto
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5
from base64 import b64decode
def assymmetric_encrypt(val, public_key):

     modulusDecoded = long(public_key["n"], 16)
     exponentDecoded = long(public_key["e"], 16)
     keyPub = RSA.construct((modulusDecoded, exponentDecoded))
     print(keyPub)
     # Generate a cypher using the PKCS1.5 standard
     cipher = PKCS1_v1_5.new(keyPub)
     return cipher.encrypt(val)

# Encrypt the password used to login
encryptedPassword = assymmetric_encrypt(password_input,public_key)

It looks that JS should be doing the same but when providing the same modulus exponent in both scripts, the encrypted password is different (looks similar but is not equal)看起来JS应该做同样的事情但是当在两个脚本中提供相同的模指数时,加密的密码是不同的(看起来相似但不相等)

Update: Funny thing is that if I run JS script with hardcoded n, e and password I get the same encrypted data every time.更新:有趣的是,如果我使用硬编码的 n、e 和密码运行 JS 脚本,我每次都会得到相同的加密数据。 When I do the same with Python script I alway get different result.. So there might be something more in the Crypto library..当我用 Python 脚本做同样的事情时,我总是得到不同的结果..所以加密库中可能还有更多的东西..

Update 2: problem was located in completely different place.更新 2:问题位于完全不同的地方。 Thanks to Maarten Bodewes comment, it turned out that padding library was broken (didn't generate new string each time).感谢 Maarten Bodewes 的评论,结果发现 padding 库坏了(每次都没有生成新的字符串)。 I changed forger lib to JSencrypt for this part and it works great.对于这部分,我将伪造库更改为 JSencrypt,效果很好。 Going through pem file but this will be probably altered in the future for better performance:通过 pem 文件,但将来可能会更改此文件以获得更好的性能:

var encrypt = new JSEncrypt();
encrypt.setPublicKey(pem);
var encrypted_jeencrypt= encrypt.encrypt(password);
var encrypted_jeencrypt_hex = base64toHEX(encrypted_jeencrypt);

I believe the way you are building the modulus is correct.我相信您构建模数的方式是正确的。 The problem is probably due you are using a string to encrypt and forge needs a buffer.问题可能是由于您使用字符串进行加密并且伪造需要缓冲区。 Try this:尝试这个:

var buf = forge.util.createBuffer(text, 'utf8');
var encryptedData = publicKey.encrypt(buf, 'RSAES-PKCS1-V1_5');

If you are going to use RSA encryption to send passwords, I suggest you to use the more secure RSA-OAEP via a SSL/TLS channel.如果您打算使用 RSA 加密来发送密码,我建议您通过 SSL/TLS 通道使用更安全的RSA-OAEP RSA_PKCS1-V1_5 and RSA-OAEP are non-deterministic and generate a different ciphertext each time. RSA_PKCS1-V1_5RSA-OAEP是不确定的,每次生成不同的密文。 The correct way to compare if a message is correct is decrypting it比较消息是否正确的正确方法是对其进行解密

I needed to convert python encryption method for javascript.我需要为 javascript 转换 python 加密方法。

import base64
import binascii
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5

def get_hex_rsa_encrypted_data(mod, exp, id, pw):
    mod = int(mod, 16)
    exp = int(exp, 16)

    rsa_key = RSA.construct((mod, exp))
    rsa = PKCS1_v1_5.new(rsa_key)

    raw_encrypted_user_id = rsa.encrypt(str.encode(id))
    raw_encrypted_password = rsa.encrypt(str.encode(pw))

    hex_encrypted_user_id = binascii.hexlify(raw_encrypted_user_id).decode()
    hex_encrypted_password = binascii.hexlify(raw_encrypted_password).decode()

    # print(hex_encrypted_user_id)
    # print(hex_encrypted_password)

    return {'enc_user_id': hex_encrypted_user_id, 'enc_user_pw': hex_encrypted_password}

My Question for this one 我的问题

your question helped me a lot, hope mine helps yours too.你的问题对我帮助很大,希望我的也能帮助你。 :) :)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM