我有一个用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******.......
并具有如下私钥,
MIIJQgIBADANBgkqhkiG9w0BAQEFAASCC*****............
我无法在带有加密模块的node.js中获得类似的代码。因为我是这个加密模块的新手,所以我不确定我尝试的代码是否正确,
//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加密货币中的代码吗?
这是要解密的详细信息。
算法RSA(Rivest–Shamir–Adleman) 模式ECB(电子密码本) 填充OAEPWithSHA-1AndMGF1Padding
答案 0 :(得分:0)
元:我很惊讶,这不是骗子,但我找不到。
首先,如果您的数据实际上是用OAEP加密的,则Java代码应该不起作用。 Java(及其他大多数地方)中的PKCS1Padding
特别是 PKCSv1.5 填充,现已改名为RSAES-PKCS1-v1_5
进行加密(和RSASSA-PKCS1-v1_5
进行签名,不适用于此处) 。尽管OAEP在PKCS1v2.0及更高版本中也进行了定义,但在Java中,您应该只为默认值(SHA-1)OAEPPadding
或非默认值OAEPwith{hash}andMGF1Padding
或第三个init参数指定javax.crypto.spec.OAEPParameterSpec
输入PrivateKey
。
第二,您显示的一部分的base64'd私钥采用PKCS8非加密格式(也称为编码),而不是PKCS1格式。如果是从Java获得的,那是可以预期的。 Java加密对所有算法使用PublicKey
的PKCS8格式(对于PRIVATE KEY
使用“ X.509”格式)。记录在一个不太明显的位置the superinterface Key
中。未加密的PKCS8的正确 PEM类型为RSA PRIVATE KEY
-而不是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);
,用于PKCS1。
此外, PEM文件不仅是BEGIN行,一个 base64行和END行。它们是BEGIN行,一个或多个base64行(每64个字符中断)和END行。 nodejs使用OpenSSL,其较旧的版本略微放松了此限制;他们每行最多允许76个字符。较新的版本可以提供更多功能,但是仍然存在限制,我相信您的密钥(显然是4096位或接近)可能会超过它,因此,如果未添加至少一些换行符,它将无法正常工作。
最后,一旦您拥有PEM格式,请不使用base64解码。这将在解码中包括BEGIN和END行,从而完全破坏了结果。传统上, nodejs加密的这一部分(以及其他几个部分)接受OpenSSL接受的相同PEM格式;根据doc 11.6.0的规定,可以接受使用OpenSSL的“ DER”格式的替代格式,该格式对应于base64解码实际密钥数据,而不是解码整个PEM(但我没有要测试的新版本)。
因此,这里是一个示例(使用 my 键和数据),两种方法均适用,并假设您正确使用OAEP:
base64encode
答案 1 :(得分:0)
这是上述Java代码中node.js中的等效代码。
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')
````````