Node.js加密密钥和IV匹配Java SecretKeySpec/IvParameterSpec [英] Node.js crypto key and iv to match java SecretKeySpec / IvParameterSpec

查看:831
本文介绍了Node.js加密密钥和IV匹配Java SecretKeySpec/IvParameterSpec的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将Java(简单)加密算法移植到Node JS.我将需要能够解密/加密从Java端加密/解密的内容.

I'm trying to to port a Java (simple) encryption algorythm to Node JS. I will need to be able to decrypt/encrypt stuff encrypted/decrypted from the Java side.

我一开始就被卡住了,密码的初始化.

I'm stuck at the very beginning, the initialization of the cipher.

在Java中,我通过SecretKeySpec获得密钥,并通过IvParameterSpec获得初始化向量:

In Java, I get the key with SecretKeySpec, and the Initialization Vector with IvParameterSpec:

public CryptStuff(String password) throws zillion_exceptions {
    if (password==null) throw new InvalidKeyException("No encryption password is set!");
    key = new SecretKeySpec(password.getBytes("UTF-8"), "AES");
    cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    ivSpec=new IvParameterSpec(new byte[cipher.getBlockSize()]);
    cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);
}

NodeJS需要一个键缓冲区和一个IV缓冲区,但是,我不知道如何从头开始计算它们:

NodeJS requires a Key Buffer and an IV buffer, however, I don't know how to calculate them from scratch:

var mCrypto = require('crypto'),
    key=[0,0,0,0,0,0,.......],
    iv=[0,0,0,0,0,.........];

function init (password) {

    // generate key from password
    // generate IV from blocksize?

    var aesCipher = mCrypto.createCipheriv("aes-????????", (new Buffer(key)), (new Buffer(iv)));
    .
    .
    .
}

此外,AES/CBC/PKCS5Padding的匹配算法字符串是什么?

Also, what's the matching algorithm string for AES/CBC/PKCS5Padding?

推荐答案

假设您具有与Java代码中相同的密码字符串,则可以在node中创建这样的密钥缓冲区:

Assuming you have the same password string as in the Java code, you can create a key buffer like this in node:

var key = new Buffer(password, "utf8");

由于您在Java中使用的是零填充IV(不好!),因此这是节点中的等效代码:

Since you're using a zero filled IV (bad!) in Java, this is the equivalent code in node:

var iv = new Buffer(16); // 16 byte buffer with random data
iv.fill(0); // fill with zeros

由于您在Java中使用CBC模式,因此必须在节点中执行相同的操作.请注意,选择密码字符串时,必须根据密码"长度选择正确的密钥大小:

Since you're using CBC mode in Java, you have to do the same in node. Note that you have to select the correct key size when selecting the cipher string depending on your "password" length:

var aesCipher = mCrypto.createCipheriv("aes-128-cbc", key, iv);
// or
var aesCipher = mCrypto.createCipheriv("aes-192-cbc", key, iv);
// or
var aesCipher = mCrypto.createCipheriv("aes-256-cbc", key, iv);

节点将自动应用PKCS#7填充,该填充与AES的PKCS#5填充相同.

Node will automatically apply PKCS#7 padding which is the same as PKCS#5 padding for AES.

密码通常没有适合用作密钥的长度(有效长度为AES的16字节,24字节和32字节),并且仅由可打印字符组成,这可能会使攻击者更容易进行暴力破解按下键.

A password has usually not the appropriate length to be used as a key (valid lengths are 16 byte, 24 byte and 32 byte for AES) and it is comprised of only printable characters which might make it easier for an attacker to brute force the key.

从密码创建密钥所需的是密钥派生功能.流行的是PBKDF2,bcrypt和scrypt(成本不断增加).

What you would need to create a key from a password is key derivation function. Popular ones are PBKDF2, bcrypt and scrypt (with increasing cost).

您确实应该为产生的每个密文生成一个新的随机IV.如果您使用静态IV,则观察您密文的攻击者可以确定您发送了相同甚至相似的消息.如果使用随机IV,则密文相差太大,攻击者无法确定是否从同一纯文本创建了两个不同的密文.这称为语义安全.

You really should be generating a new random IV for every ciphertext that you produce. If you use a static IV, an attacker that observes your ciphertexts can determine that you sent the same or even similar messages. If you use a random IV, then the ciphertexts differ so much that an attacker cannot determine whether two different ciphertexts where created from the same plaintext or not. This is called semantic security.

随机IV本身不必一定是秘密的,因此您可以轻松地将其添加到密文之前,并在解密之前将其切片.

The random IV itself doesn't have to be secret, so you can easily prepend it to the ciphertext and slice it off before decryption.

您甚至可以将其与密钥派生功能(KDF)结合使用.只需为KDF生成随机盐即可. KDF通常能够派生可变数量的输出字节,因此只需让它派生密钥||即可. IV(串联),然后拆分它们.现在,您只需要在密文前加盐即可.

You can even combine this with the key derivation function (KDF). Simply generate a random salt for the KDF. A KDF is usually able to derive a variable amount of output bytes, so simply let it derive key || IV (concatenation) and then split them. Now, you only need to prepend the salt to the ciphertext.

取决于您的系统,您可能容易受到诸如padding oracle攻击之类的攻击.最好的防御方法是对密文进行身份验证.因此,您可以将加密然后MAC方案与功能强大的MAC(例如HMAC-SHA256)一起使用,也可以将经过身份验证的操作模式(例如GCM或EAX)使用. Java和node都支持GCM,但涉及的工作更多.

Depending on your system, you might be vulnerable to attacks such as the padding oracle attack. The best defense against this is to authenticate the ciphertext. So you can either use an encrypt-then-MAC scheme with a strong MAC such as HMAC-SHA256 or an authenticated mode of operation such as GCM or EAX. Java and node both support GCM, but there is a little more work involved.

这篇关于Node.js加密密钥和IV匹配Java SecretKeySpec/IvParameterSpec的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆