【问题标题】:RSA encrypt with PKCS1-V1_5 (JavaScript)使用 PKCS1-V1_5 (JavaScript) 进行 RSA 加密
【发布时间】:2017-09-28 11:13:12
【问题描述】:

我想使用带有 PKCS1-1.5 填充的 RSA 格式的公钥加密我的密码。目前我尝试使用来自https://github.com/digitalbazaar/forgeforge 库。部分解决方案使用 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');

提供的指数 - 10001 似乎在 BigInteger() 中被正确解析,因为它返回单个项目数组 - 65537。

然而,当我推模量9bedc7ad20bdacf930f1471d0c2a9f7f1895e24d73957b145b621e7800589ec14a3122df556fae94cc45df7b1f5003062df5681a18d8165377a6dece1a8c36e0af6ce13e89890b6813eb94135bd8c4b2b743ef6d24cfc09cbd59a8105c3f31d56a0224b1db14c2e6396493571ef83d664c5b6169a1b42f988cfc3f7d39d50aa9 P>

BigInteger() 结果有些奇怪: modulus screenshot

因此,稍后在代码中创建的 RSA 密钥对是错误的。谁能指出我正确的方向?更令人沮丧的是,我有工作的 .py 脚本并且无法将其转换为 JS。我不能在这里使用任何服务器端编程。 (顺便说一句,我知道 JS 密码加密的问题/风险)。

更新

这是工作的 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)

看起来 JS 应该做同样的事情,但是当在两个脚本中提供相同的模指数时,加密的密码是不同的(看起来相似但不相等)

更新: 有趣的是,如果我使用硬编码的 n、e 和密码运行 JS 脚本,我每次都会得到相同的加密数据。当我对 Python 脚本执行相同操作时,我总是得到不同的结果。所以 Crypto 库中可能还有更多内容。

更新 2: 问题位于完全不同的地方。感谢 Maarten Bodewes 的评论,事实证明填充库已损坏(每次都没有生成新字符串)。对于这部分,我将 forger lib 更改为 JSencrypt,效果很好。浏览 pem 文件,但这可能会在未来进行更改以获得更好的性能:

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

【问题讨论】:

  • 你可以试试forge.pki.setRsaPublicKey(modulus, exponent); 吗?
  • 我认为它没有帮助.. BigInteger() 数组应该是十六进制模数的十进制表示,只是拆分?换句话说,有没有办法检查 bigInteger() 的模数是否正确?
  • BigInteger 在内部当然会以较小的整数存储;您的 CPU 不能在内部使用大型 bigintegers。将这些较小的大整数表示为十进制当然只是一个调试器设置。
  • 您可以通过在一个运行时加密并在另一个运行时解密来检查模数是否正确。如果加密产生相同的值,那么要么您使用的是“原始/教科书”RSA(似乎不是那样),PKCS#1 填充已损坏,要么存在 seriously 错误JS中的随机数生成器。例如,如果您使用未连接到系统 RNG 的 VM,则可能会发生这种情况。
  • 我检查了 RNG 问题,幸运地 看来 RNG 工作正常。我已将填充更改为 RSA-OAEP,并且每次在本地和服务器上都得到不同的加密十六进制

标签: javascript encryption rsa


【解决方案1】:

我相信您构建模数的方式是正确的。问题可能是由于您使用字符串进行加密并且伪造需要缓冲区。试试这个:

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

如果您打算使用 RSA 加密来发送密码,我建议您通过 SSL/TLS 通道使用更安全的RSA-OAEPRSA_PKCS1-V1_5RSA-OAEP 是非确定性的,每次都会生成不同的密文。比较消息是否正确的正确方法是解密它

【讨论】:

【解决方案2】:

我需要为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

您的问题对我帮助很大,希望我的问题也对您有所帮助。 :)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-23
    • 1970-01-01
    • 2020-01-08
    相关资源
    最近更新 更多