Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/380.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用RSA私钥解密Base64字符串_Java_Node.js - Fatal编程技术网

Java 使用RSA私钥解密Base64字符串

Java 使用RSA私钥解密Base64字符串,java,node.js,Java,Node.js,我有一个用RSA公钥加密的字符串,我需要用RSA私钥解密一个字符串 我已经有了一个可用的Java代码,但我需要用Node.js库编写一个类似的代码来解密我的消息 这是工作的Java代码 public static String getDecrypted(String data, String Key) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKe

我有一个用RSA公钥加密的字符串,我需要用RSA私钥解密一个字符串

我已经有了一个可用的Java代码,但我需要用Node.js库编写一个类似的代码来解密我的消息

这是工作的Java代码

public static String getDecrypted(String data, String Key) 
      throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
      Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
      PrivateKey pk = KeyFactory.getInstance("RSA").generatePrivate(
          new PKCS8EncodedKeySpec(Base64.getDecoder().decode(Key.getBytes())));
      cipher.init(Cipher.DECRYPT_MODE, pk);
      byte[] encryptedbytes = cipher.doFinal(Base64.getDecoder().decode(data.getBytes()));
      return new String(encryptedbytes);
}
我找不到相应的node.js代码

我有一个Base64编码字符串,如下所示

S+JnXECfe8zHO69Mp0oh6ux*****.

并且具有如下所示的私钥

miijqgibadanbgkqhkig9w0baqefaasc******………

我无法在node.js中使用crypto模块获得类似的代码。因为我是这个加密模块的新手,我不确定我尝试的代码是否正确

//decryption

const crypto = require('crypto');

const PK_HEADER = '\n-----BEGIN RSA PRIVATE KEY-----\n'
const PK_FOOTER = '\n-----END RSA PRIVATE KEY-----\n'

const pkey ='MIIJQgIBADANBgkqhki......'

const privateKey = `${PK_HEADER}${pkey}${PK_FOOTER}`
const privateEncodedKey = Buffer.from(privateKey, 'base64')

const response = "0f8c396c5279a...";
const decrypt = (privateEncodedKey, message) => {
let enc = crypto.privateDecrypt({
key: privateEncodedKey,
padding: crypto.RSA_PKCS1_OAEP_PADDING
}, Buffer.from(message, 'hex'));
return enc.toString();
};

console.log(decrypt(privateEncodedKey, response ))
你能帮我们修改node.js crypto中的代码吗

下面是要解密的详细信息

RSA算法(Rivest–Shamir–Adleman) 模式ECB(电子码本)
用SHA-1和MGF1填充OAEPpadding

梅塔:我很惊讶这不是一个傻瓜,但我找不到

首先,如果您的数据实际上是用OAEP加密的,那么Java代码就不应该工作PKCS1Padding特别是PKCSv1.5填充,现在改名为
RSAES-PKCS1-v1_5
,用于加密(和
RSASSA-PKCS1-v1_5
用于签名,此处不适用)。虽然OAEP也在PKCS1v2.0以上版本中定义,但在Java中,您应该只为默认值(即SHA-1)指定
OAEPPadding
,或者为非默认值
OAEPwith{hash}和mgf1padding
指定第三个init参数,或者指定类型为
javax.crypto.spec.OAEPParameterSpec

其次,您显示的部分base64的私钥是PKCS8未加密格式(也称为编码),而不是PKCS1格式。如果您是从Java获得的,这是意料之中的;Java crypto将PKCS8格式用于所有算法的
PrivateKey
PublicKey
)和“X.509”格式。这是在一个不显眼的地方记录的。PKCS8未加密的正确的PEM类型是
私钥
——而不是用于PKCS1的
RSA私钥

此外,PEM文件不仅仅是开始行、一个base64行和结束行。它们是开始行、每64个字符断开一行或多行base64行和结束行。nodejs使用OpenSSL,较旧版本的OpenSSL稍微放宽了这一限制;他们允许每行最多76个字符。较新的版本允许更多,但仍然有一个限制,我相信您的密钥(显然是4096位或接近)可能会超过它,因此如果不添加至少一些换行符,将无法工作

最后,一旦有了PEM格式,就不要对其进行base64解码。这将包括解码的开始行和结束行,完全破坏了结果。nodejs crypto的这一部分(以及其他几个部分)传统上接受OpenSSL的相同PEM格式;根据Doc11.6.0,up可以接受使用OpenSSL的“DER”格式的替代形式,这与base64解码实际的密钥数据(而不是整个PEM)相对应(但我没有新版本可供测试)

因此,假设您正确使用OAEP,下面是两种方法的示例(使用我的密钥和数据):

const crypto = require('crypto');

const pk8b64 = (
"MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKNwapOQ6rQJHetP"+
"HRlJBIh1OsOsUBiXb3rXXE3xpWAxAha0MH+UPRblOko+5T2JqIb+xKf9Vi3oTM3t"+
"KvffaOPtzKXZauscjq6NGzA3LgeiMy6q19pvkUUOlGYK6+Xfl+B7Xw6+hBMkQuGE"+
"nUS8nkpR5mK4ne7djIyfHFfMu4ptAgMBAAECgYA+s0PPtMq1osG9oi4xoxeAGikf"+
"JB3eMUptP+2DYW7mRibc+ueYKhB9lhcUoKhlQUhL8bUUFVZYakP8xD21thmQqnC4"+
"f63asad0ycteJMLb3r+z26LHuCyOdPg1pyLk3oQ32lVQHBCYathRMcVznxOG16VK"+
"I8BFfstJTaJu0lK/wQJBANYFGusBiZsJQ3utrQMVPpKmloO2++4q1v6ZR4puDQHx"+
"TjLjAIgrkYfwTJBLBRZxec0E7TmuVQ9uJ+wMu/+7zaUCQQDDf2xMnQqYknJoKGq+"+
"oAnyC66UqWC5xAnQS32mlnJ632JXA0pf9pb1SXAYExB1p9Dfqd3VAwQDwBsDDgP6"+
"HD8pAkEA0lscNQZC2TaGtKZk2hXkdcH1SKru/g3vWTkRHxfCAznJUaza1fx0wzdG"+
"GcES1Bdez0tbW4llI5By/skZc2eE3QJAFl6fOskBbGHde3Oce0F+wdZ6XIJhEgCP"+
"iukIcKZoZQzoiMJUoVRrA5gqnmaYDI5uRRl/y57zt6YksR3KcLUIuQJAd242M/WF"+
"6YAZat3q/wEeETeQq1wrooew+8lHl05/Nt0cCpV48RGEhJ83pzBm3mnwHf8lTBJH"+
"x6XroMXsmbnsEw=="
) .replace(/.{64}/g,"$&\n");

const ctxb64 =
"QLiNLbAqDPG024Xdtl80OMWCHfPq4pCIduoXKcVyY0211Ji7n6Cvjp+ATyLg95mX"+
"/xuFdLV6jiR0ayVw1KTb+U3WKwQRsAWzA+gYiDjdfRaCrNxtcCp2Onw92bjdjZke"+
"O7VrmzDj+8ovDvDgb/pXhAPMcJKSCDUVXgCxpZSnVJE=";
const ctxbuf = Buffer.from(ctxb64,'base64');

// the traditional way 
const t1 = crypto.privateDecrypt("-----BEGIN PRIVATE KEY-----\n"+pk8b64+"\n-----END PRIVATE KEY-----\n", ctxbuf);
console.log(t1);

// should work in 11.6.0 (not tested); can add padding: to specify if other than OAEP 
const t2 = crypto.privateDecrypt({key:Buffer.from(pk8b64,'base64'),format:'der',type:'pkcs8'}, ctxbuf);
console.log(t2);

下面是node.js中与上述Java代码完全相同的代码

var crypto = require("crypto");
var path = require("path");
var fs = require("fs");

var encryptStringWithRsaPublicKey = function(toEncrypt, relativeOrAbsolutePathToPublicKey) {
    var absolutePath = path.resolve(relativeOrAbsolutePathToPublicKey);
    var publicKey = fs.readFileSync(absolutePath, "utf8");
    var buffer = Buffer.from(toEncrypt);
    var encrypted = crypto.publicEncrypt(publicKey, buffer);
    return encrypted.toString("base64");
};

var decryptStringWithRsaPrivateKey = function(toDecrypt, relativeOrAbsolutePathtoPrivateKey) {
    var absolutePath = path.resolve(relativeOrAbsolutePathtoPrivateKey);
    var privateKey = fs.readFileSync(absolutePath, "utf8");
    var buffer = Buffer.from(toDecrypt, "base64");
    console.log("PRIVATE_KEY:",privateKey);
    var decrypted = crypto.privateDecrypt({
        key: privateKey,
        padding:crypto.constants.RSA_PKCS1_OAEP_PADDING
    }, buffer);

    return decrypted.toString("utf8");
};`

cipher= '/**Encrypted TEXT/*'

/*private.pem*/
-----BEGIN PRIVATE KEY-----
............................
-----ENDPRIVATE KEY-----
/**/
const decryptedText = decryptStringWithRsaPrivateKey(cipher,'private.pem')
````````

非常感谢你的帮助。您的代码在使用最新的node js时运行良好。但是当我使用私钥和文本执行时,我得到了以下错误。internal/crypto/cipher.js:53返回方法(数据、格式、类型、密码、缓冲区、填充);^错误:错误:0406506C:rsa例程:rsa_ossl_private_decrypt:data大于mod len const t2=crypto.privateDecrypt({key:Buffer.from(pk8b64,“base64”),格式:“der”,类型:“pkcs8”,填充:crypto.rsa_PKCS1_OAEP_padding},ctxbuf);console.log(t2.toString());萨提斯:那么要么你的密钥密码错误(可能在复制或传输过程中损坏),要么你的密码密码密码错误。有效的RSA密文在数字上始终小于密钥中的模值“n”,通常表示为与模长度相同的八位字节字符串,可以十六进制、base64或类似格式进行编码。(签名也是一样。)嗨,戴夫。很抱歉反应太晚。你完全正确,我用的钥匙是错的。您的代码工作正常,但我无法将节点升级到最新版本。所以我尝试了代码。@SathishKumarSundaramoorthy-根据您的评论,我认为这应该被标记为正确答案?@dave_thompson_085谢谢您的回答。你有私人咨询工作吗?(Mods,如果这是一个不合适的问题,请向我道歉-如果是,请让我知道,我会记下此评论)