1

I have following code in 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; 

I need to implement it in JavaScript/Node.js I don't know how to implement it in JavaScript from secretString to key generated by KeyGenerator

from the comment section:

This is my code:

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) 
}

My problem is secureRandom and KeyGenerator. I do not know how to implement it in nodejs

Saptarshi Basu
  • 8,640
  • 4
  • 39
  • 58
  • You already figured out that you want to use `cryptojs` and you are stuck with the secretString and the key generation. Maybe you should either search further on how to use cryptojs or post the code of your attempts here and tell us exactly what you don't understand. Right now your question looks like you didn't even try anything (please prove us wrong). – GameDroids Sep 16 '19 at 10:22
  • Don't take it personal ! It is just not evident to see the effort you put in there. I am sorry that I can't help you there, but maybe this site is of interest for you :https://asecuritysite.com/encryption/js10 There you can choose the type of encryption you like and it shows you examples on how it looks like *and* **how to implement it**. I hope it helps! – GameDroids Sep 16 '19 at 11:43
  • Thank @GameDroids. I'll be more careful next time – Nguyễn Tuấn Sep 17 '19 at 02:50

2 Answers2

1

I don't know Java, but your usage looks somewhat weak, there are algorithms like PBKDF2 (which is old and discouraged now) and scrypt which do a much better job at turning human passwords into keying material. I'm also not sure where your IV is coming from in your Java code. Exactly replicating the Java code would be somewhat difficult as you'd need to know how your version of Java was implemented, and hence how the bytes passed to setSeed actually get turned into a key.

Node's Crypto module, as far as I can tell, assumes you know how long the keys are supposed to be. In the case of AES 128 in CBC mode, this would be 128 bits (i.e. 16 bytes) for both the key and IV.

Assuming you wanted to use things built into the Crypto module (argon2 would be recommended if you could relax this restriction) then you'd do something like:

const crypto = require('crypto');

const password = 'passw0rd';

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

which would leave you with a suitable value in key, then you'd encrypt with:

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(),
]);

and you could encode to Base64 with ciphertext.toString('base64').

Note that to be able to decrypt this, you'd need the scrypt_salt, iv, and ciphertext.

Sam Mason
  • 15,216
  • 1
  • 41
  • 60
0

When you encrypt something using AES, there is always a "mode" in play. In your Java code you don't specify a mode explicitly - Cipher.getInstance("AES"). When you do not specify a mode, the default mode in Java is "ECB" which is the most insecured mode anyway.

In your NodeJs code, you're using "CBC" mode which is a altogether different mode.

Neither "ECB", nor "CBC" are considered secured enough. As of today, usually, the recommended mode is the GCM mode.

To generate a key from a password, ideally a "key derivation function" should be used. The 4 key derivation functions recommended by OWASP are: PBKDF2, Scrypt, Bcrypt and Argon2.

In your Java code, the password is used as a seed for the pseudo random number generator class SecureRandom. That's a little bit bizarre because even if you give the same password to your function, it will produce different key in different run. Yes, SecureRandom is also used to generate key. But if the requirement is to generate a key from a password, a key derivation function, as mentioned above, shoul be used. Both the approaches are shown in the following StackOverflow answer with detailed explanation. However, it uses "GCM" mode. But as long as you understand the concepts, you can use any mode of your choice.

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

Similarly, you'll find the same implementation in NodeJs in the following StackOverflow answer:

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

To further understand AES in general, you may want to go through the following StackOverflow answer:

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

Saptarshi Basu
  • 8,640
  • 4
  • 39
  • 58
  • 1
    I don't want use java code. However i have to integrate a supplier into my system. They give me javacode then I have to use it to encode param and call the API to Their server. So I need to implement it in JavaScript/Node.js because My system is using nodejs for backend – Nguyễn Tuấn Sep 17 '19 at 02:48