Java 使用RSA私钥解密Base64字符串
我有一个用RSA公钥加密的字符串,我需要用RSA私钥解密一个字符串 我已经有了一个可用的Java代码,但我需要用Node.js库编写一个类似的代码来解密我的消息 这是工作的Java代码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
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代码就不应该工作
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,如果这是一个不合适的问题,请向我道歉-如果是,请让我知道,我会记下此评论)