How to pan the default encryption methods in CryptoJS DES to java code

117 Views Asked by At

How do I go about implementing CryptoJS.DES.encrypt("123456", "12345678") in js in java. Because the result is still different every time I run it, and the decrypted value is still the same for different results.
this is my test code:

<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js" integrity="sha512-E8QSvWZ0eCLGk4km3hxSsNmGWbLtSCSUcewDQPQWZF6pEU8GlT8a5fF32wOl1i8ftdMhssTrF/OhyGWwonTcXA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script type="text/javascript" src="http://www.osctools.net/js/CryptoJS/components/core-min.js"></script>
<script type="text/javascript">


  // var desstr = CryptoJS.DES.decrypt("U2FsdGVkX19Z3jzZ3NvmJey7mrbU2qhT", "12345678").toString(CryptoJS.enc.Utf8);
  // alert("result:"+desstr);
    
  var encryptResult =CryptoJS.DES.encrypt("123456", "12345678");
  alert("result:"+encryptResult);
  
</script>

I need the equivalent Java implementation of the encryption and decryption code

My util class

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.SecretKeySpec;
import java.util.Arrays;
import java.util.Base64;

public class DESUtil {

    private static final String ALGORITHM = "DES";
    private static final int DES_KEY_SIZE = 8;
    private static final String DES_MODE  = " DES/ECB/PKCS5Padding";

    public static byte[] encrypt(byte[] data, byte[] key) throws Exception {
        DESKeySpec desKeySpec = new DESKeySpec(key);
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM);
        SecretKey secretKey = keyFactory.generateSecret(desKeySpec);
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, secretKey);
        return cipher.doFinal(data);
    }

    public static byte[] decrypt(byte[] data, byte[] key) throws Exception {
        DESKeySpec desKeySpec = new DESKeySpec(key);
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM);
        SecretKey secretKey = keyFactory.generateSecret(desKeySpec);
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, secretKey);
        return cipher.doFinal(data);
    }

    public static String encryptJs(String plainText, String secretKey) throws Exception {
        byte[] keyBytes = Arrays.copyOf(secretKey.getBytes(), DES_KEY_SIZE);
        byte[] plainTextBytes = plainText.getBytes();
        SecretKeySpec desKeySpec = new SecretKeySpec(keyBytes, "DES");
        Cipher desCipher = Cipher.getInstance(DES_MODE);
        desCipher.init(Cipher.ENCRYPT_MODE, desKeySpec);
        byte[] encryptedText = desCipher.doFinal(plainTextBytes);
        String data = Base64.getEncoder().encodeToString(encryptedText);
        return data;
    }

    public static String decryptJs(String cipherText, String secretKey) throws Exception {
        byte[] keyBytes = Arrays.copyOf(secretKey.getBytes(), DES_KEY_SIZE);
        byte[] encryptedTextBytes = Base64.getDecoder().decode(cipherText);
        SecretKeySpec desKeySpec = new SecretKeySpec(keyBytes, "DES");
        Cipher desCipher = Cipher.getInstance(DES_MODE);
        desCipher.init(Cipher.DECRYPT_MODE, desKeySpec);
        String data = new String(desCipher.doFinal(encryptedTextBytes));
        return data;
    }

}
1

There are 1 best solutions below

0
AudioBubble On

CryptoJS uses the key derivation function EVP_BytesToKey() when key is passed as a string. You need an implementation of this function for the Java side, e.g. BouncyCastle (but you can find others on the web).


For encryption CryptoJS generates a random salt during key derivation from which together with the password key and IV are derived. The encryption is done with DES in CBC mode and PKCS#7 padding. Salt and ciphertext are concatenated and prefixed with Salted__.

Example - Encryption with Java:

import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.bouncycastle.crypto.digests.MD5Digest;
import org.bouncycastle.crypto.generators.OpenSSLPBEParametersGenerator;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.ParametersWithIV;

...

// create random salt
SecureRandom secureRandom = new SecureRandom();
byte[] salt = new byte[8];
secureRandom.nextBytes(salt);

// key/IV derivation
OpenSSLPBEParametersGenerator pbeGenerator = new OpenSSLPBEParametersGenerator(new MD5Digest());
pbeGenerator.init("my passphrase".getBytes(StandardCharsets.UTF_8), salt);
ParametersWithIV parameters = (ParametersWithIV)pbeGenerator.generateDerivedParameters(64, 64);
byte[] key = ((KeyParameter)parameters.getParameters()).getKey();
byte[] iv = parameters.getIV();

// encryption
Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "DES"), new IvParameterSpec(iv));
byte[] ciphertext = cipher.doFinal("The quick brown fox jumps over the lazy dog".getBytes(StandardCharsets.UTF_8));

// concatenation
ByteBuffer saltCiphertextBuf = ByteBuffer.allocate(16 + ciphertext.length);
byte[] saltCiphertext = saltCiphertextBuf.put("Salted__".getBytes(StandardCharsets.UTF_8)).put(salt).put(ciphertext).array();
System.out.println(Base64.getEncoder().encodeToString(saltCiphertext)); // e.g. U2FsdGVkX19HEoeGxD/2PAQYTCQM6sTD/vs4QcihRE38g9kr/JCFil3fnmq9wo3bvFdZosDyPCzEbttrZMlC1A==

Test - Decryption with CryptoJS:

var desstr = CryptoJS.DES.decrypt("U2FsdGVkX19HEoeGxD/2PAQYTCQM6sTD/vs4QcihRE38g9kr/JCFil3fnmq9wo3bvFdZosDyPCzEbttrZMlC1A==", "my passphrase").toString(CryptoJS.enc.Utf8);
console.log("result:" + desstr);
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>


For decryption, separate salt and ciphertext, then derive key and IV, and decrypt the ciphertext.
The implementation is pretty much analog apart from separating, and I'll leave it up to you.


Note that DES is insecure (retired for decades) and EVP_BytesToKey() is also considered insecure. More secure alternatives are AES and PBKDF2.