0

I'm trying to find the similar java code for the below Node JS code,

Node JS Code:

     var crypto = require('crypto');

     var mykey = crypto.createCipher('aes-128-ecb', 'XXXXXXXX00000000');
     var mystr = mykey.update('HelloWorld', 'utf8', 'hex')
     mystr += mykey.final('hex');

      console.log(mystr);

Encryption Result: ce25d577457cf8113fa4d9eb16379529

Java Code:

 public static String toHex(String arg) throws UnsupportedEncodingException {
              return String.format("%x", new BigInteger(1, arg.getBytes("UTF-8")));
        }

 public static void main(String args[]) throws Exception{
 
    byte[] key = "XXXXXXXX".getBytes();
    String message = "HelloWorld";
        
    try {
        key = Arrays.copyOf(key, 16); 
        SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec);         
        byte encstr[] = cipher.update(message.getBytes());
        String encData = new String(encstr, "UTF-8");
        encData = toHex(encData);
        byte encstr2[] = cipher.doFinal();
        String encData2 = new String(encstr2);
        encData  = encData + toHex(encData2);           
        System.out.println(encData);
    } catch (NoSuchAlgorithmException nsae) {
        throw new Exception("Invalid Java Version");
    } catch (NoSuchPaddingException nse) {
        throw new Exception("Invalid Key");
    }
    
}

Encryption Result: 056efbfbdefbfbd7c7760efbfbdefbfbdefbfbd39262cefbfbdefbfbd5166

4
  • 1
    You are using the crypto.createCipher(algorithm, password[, options]) version, hence the key you specify is handled as password and the actual key should be MD5(password) according to the node.js crypt documentation. On Java side you just use the string bytes as key without MD5 (which is insecure as well as using ECB mode). Commented Aug 5, 2020 at 10:46
  • 1
    You shouldn't convert the ciphertext to a Utf8 string. This corrupts the data. Instead, you should hex encode it directly. For this, a toHex implementation that directly expects a byte[] would be more useful (by the way, the current toHex omits leading 0-values). Also, the update call isn't necessary, the plaintext can be passed directly to doFinal. The encoding of the plaintext should be specified explicitly. Commented Aug 5, 2020 at 12:05
  • By the way, if you want to derive the key via a password according to createCipher, you need a Java implementation of the (relatively insecure) key derivation function EVP_BytesToKey. An alternative is createCipheriv, see the NodeJS documentation. Commented Aug 5, 2020 at 12:17
  • In particular all those efbfbd in the Java output are places where parts of your ciphertext that weren't valid UTF8 were discarded and changed to U+FFFD REPLACEMENT CHARACTER. For nodejs createCipher to Java dupe stackoverflow.com/questions/48047155 stackoverflow.com/questions/33391533 and since it is a copy of (pre-1.1.0 unsalted) openssl enc also stackoverflow.com/questions/8357941 stackoverflow.com/questions/31947256 Commented Aug 5, 2020 at 12:50

1 Answer 1

0

Taking up the comments of @Robert and @Topaco I wrote a simple decryption program that is working for the given password 'XXXXXXXX00000000'.

Please keep in mind that this progrsm is using UNSECURE AES ECB mode and UNSECURE MD5 hash algorithm. The program does NOT provide any proper exception handling.

This is the result:

ciphertext Java:   ce25d577457cf8113fa4d9eb16379529
ciphertext NodeJS: ce25d577457cf8113fa4d9eb16379529

My code:

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class MainSo {
    public static void main(String[] args) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
        System.out.println("https://stackoverflow.com/questions/63263081/node-js-encryption-code-to-java-encryption-code");

        String plaintext = "HelloWorld";
        String keyString =  "XXXXXXXX00000000"; // 16 chars
        byte[] key = keyString.getBytes(StandardCharsets.UTF_8);
        // md5 hashing is unsecure !!
        MessageDigest md = MessageDigest.getInstance("MD5");
        byte[] keyMd5 = md.digest(key);
        // aes ecb mode encryption is unsecure
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        SecretKeySpec secretKeySpec = new SecretKeySpec(keyMd5, "AES");
        cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
        byte[] ciphertext = cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8));
        System.out.println("ciphertext Java:   " + bytesToHex(ciphertext));
        System.out.println("ciphertext NodeJS: " + "ce25d577457cf8113fa4d9eb16379529");
    }
    private static String bytesToHex(byte[] bytes) {
        // service method for displaying a byte array as hex string
        StringBuffer result = new StringBuffer();
        for (byte b : bytes) result.append(Integer.toString((b & 0xff) + 0x100, 16).substring(1));
        return result.toString();
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

@user3834008: I'm glad to hear that it is working, Can you plase mark the answer as accepted ?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.