繁体   English   中英

使用 RSA 私钥解密 Base64 字符串

[英]Decrypt Base64 string with RSA private key

我有一个带有 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 crypto中的代码吗?

这是解密的详细信息..

算法 RSA (Rivest–Shamir–Adleman) Mode ECB (Electronic Codebook) Padding OAEPWithSHA-1AndMGF1Padding

Meta:我很惊讶这不是骗子,但我找不到。

首先,如果你的数据实际上是在与原和加密,即Java代码应该工作。 PKCS1Padding在Java中(和大多数其他地方)是专门PKCSv1.5填充,现在retronymed RSAES-PKCS1-v1_5进行加密(和RSASSA-PKCS1-v1_5的签名,在这里不适用)。 尽管 OAEP 也在 PKCS1v2.0 中定义,但在 Java 中,您应该仅指定OAEPPadding作为默认值(即 SHA-1),或为非默认值OAEPwith{hash}andMGF1Paddingjavax.crypto.spec.OAEPParameterSpec类型的第三个 init 参数指定javax.crypto.spec.OAEPParameterSpec

其次,您展示的 base64 私钥是 PKCS8 未加密格式(又名编码),而不是 PKCS1 格式。 如果你从 Java 得到它,这是意料之中的; Java 加密对所有算法使用 PKCS8 格式的PrivateKey (以及PublicKey “X.509”格式)。 这被记录在一个不太明显的地方, 超级接口Key PKCS8 未加密的正确PEM 类型是PRIVATE KEY -- 而不是 PKCS1 的RSA PRIVATE KEY

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

最后,一旦你有了 PEM 格式,就不要对它进行 base64 解码。 这将包括解码中的 BEGIN 和 END 行,完全破坏结果。 nodejs 加密的这部分(和其他几个)传统上接受与 OpenSSL 相同的 PEM 格式 根据文档 11.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')
````````

暂无
暂无

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

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