【问题标题】:How to convert crypto from java to nodejs如何将加密从 java 转换为 nodejs
【发布时间】:2019-09-17 01:18:12
【问题描述】:

我在 Java 中有以下代码。

KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
secureRandom.setSeed(password.getBytes());
kgen.init(INIT_LENGTH, secureRandom);
SecretKey secretKey = kgen.generateKey();
byte[] enCodeFormat = secretKey.getEncoded();
SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
Cipher cipher = Cipher.getInstance("AES"); 
byte[] byteContent = content.getBytes("utf-8");
cipher.init(Cipher.ENCRYPT_MODE, key);  
byte[] result = cipher.doFinal(byteContent);
return result; 

我需要在 JavaScript/Node.js 中实现它 我不知道如何在 JavaScript 中实现它从 secretString 到 KeyGenerator 生成的密钥

来自评论部分:

这是我的代码:

function encodeDesCBC( textToEncode, keyString, ivString ) {
    const key = Buffer.from(keyString.substring(0, 8), 'utf8') 
    const iv = Buffer.from(ivString.substring(0, 8), 'utf8') 
    const cipher = crypto.createCipheriv('aes-128-cbc', key, iv) 
    let c = cipher.update(textToEncode, 'utf8', 'base64') 
    c += cipher.final('base64') 
    return base64url.escape(c) 
}

我的问题是secureRandomKeyGenerator。我不知道如何在nodejs中实现它

【问题讨论】:

  • 您已经想通了要使用cryptojs 并且您被secretString 和密钥生成所困扰。也许您应该进一步搜索如何使用 cryptojs 或在此处发布您尝试的代码,并准确告诉我们您不了解的内容。现在你的问题看起来你甚至没有尝试任何东西(请证明我们错了)。
  • 不要把它当作私人的!只是看不出你在那里付出的努力。很抱歉我不能帮助你,但也许你对这个网站感兴趣 :asecuritysite.com/encryption/js10 在那里你可以选择你喜欢的加密类型,它会向你展示它的外观示例如何实现它。希望对你有帮助!
  • 感谢@GameDroids。下次我会更小心的

标签: java node.js encryption aes cryptojs


【解决方案1】:

我不懂 Java,但你的用法看起来有点弱,有一些算法,如 PBKDF2(现在已过时且不鼓励使用)和 scrypt,它们在将人类密码转换为密钥材料方面做得更好。我也不确定你的 IV 在你的 Java 代码中来自哪里。准确复制 Java 代码会有些困难,因为您需要知道您的 Java 版本是如何实现的,因此传递给 setSeed 的字节实际上是如何变成密钥的。

据我所知,Node 的Crypto 模块假设您知道密钥应该有多长。对于 CBC 模式下的 AES 128,密钥和 IV 都是 128 位(即 16 字节)。

假设您想使用 Crypto 模块中内置的东西(如果您可以放宽此限制,建议您使用 argon2),那么您将执行以下操作:

const crypto = require('crypto');

const password = 'passw0rd';

const scrypt_salt = crypto.randomBytes(16);
const key = crypto.scryptSync(password, scrypt_salt, 16);

这将为您在key 中留下一个合适的值,然后您将使用:

const plaintext = 'the plain text to encode';

const iv = crypto.randomBytes(16);
const cipher = crypto.createCipheriv('aes-128-cbc', key, iv);

const ciphertext = Buffer.concat([
    cipher.update(plaintext),
    cipher.final(),
]);

您可以使用 ciphertext.toString('base64') 编码为 Base64。

请注意,要能够对此进行解密,您需要 scrypt_saltivciphertext

【讨论】:

    【解决方案2】:

    当您使用 AES 加密某些东西时,总会有一种“模式”在起作用。在您的 Java 代码中,您没有明确指定模式 - Cipher.getInstance("AES")。当您不指定模式时,Java 中的默认模式是“ECB”,无论如何这是最不安全的模式。

    在您的 NodeJs 代码中,您使用的是“CBC”模式,这是一种完全不同的模式。

    “ECB”和“CBC”都不够安全。到今天为止,通常推荐的模式是 GCM 模式。

    要从密码生成密钥,理想情况下应该使用“密钥派生函数”。 OWASP 推荐的 4 个密钥派生函数是:PBKDF2、Scrypt、Bcrypt 和 Argon2。

    在您的 Java 代码中,密码用作伪随机数生成器类 SecureRandom 的种子。这有点奇怪,因为即使您为函数提供相同的密码,它也会在不同的运行中产生不同的密钥。是的,SecureRandom 也用于生成密钥。但是,如果需要从密码生成密钥,则应该使用如上所述的密钥派生函数。这两种方法都显示在以下 StackOverflow 答案中,并附有详细说明。但是,它使用“GCM”模式。但只要您了解这些概念,就可以使用您选择的任何模式。

    https://stackoverflow.com/a/53015144/1235935

    同样,您会在以下 StackOverflow 答案中找到 NodeJs 中的相同实现:

    https://stackoverflow.com/a/53573115/1235935

    要进一步了解 AES,您可能需要阅读以下 StackOverflow 答案:

    https://stackoverflow.com/a/43779197/1235935

    【讨论】:

    • 我不想使用 java 代码。但是我必须将供应商集成到我的系统中。他们给我 javacode 然后我必须用它来编码参数并将 API 调用到他们的服务器。所以我需要在 JavaScript/Node.js 中实现它,因为我的系统使用 nodejs 作为后端
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-05-11
    • 1970-01-01
    • 2021-01-30
    • 2011-02-26
    • 2022-01-12
    • 1970-01-01
    • 2021-06-09
    相关资源
    最近更新 更多