What are the AES parameters used and steps performed internally by crypto-js while encrypting a message with a password?

后端 未结 3 1834
感情败类
感情败类 2020-11-28 12:20

Background: The application that I am working on is supposed to work offline. I should encrypt some text data using a password as a key at the java server

3条回答
  •  -上瘾入骨i
    2020-11-28 13:12

    Following @Artjom B's great answer both on this question and here for python users, I am joining the full java code that helped me decrypt a string that was encrypted this way

    var encrypted = CryptoJS.AES.encrypt(message, password).toString();
    

    This piece of Java code is useful when you only know the password (i.e. salt was not sent with the encrypted string):

    public String decrypt(String encrypted, String password) throws Exception {
        int keySize = 8;
        int ivSize = 4;
        // Start by decoding the encrypted string (Base64)
        // Here I used the Android implementation (other Java implementations might exist)
        byte[] cipherText = Base64.decode(encrypted, Base64.DEFAULT);
        // prefix (first 8 bytes) is not actually useful for decryption, but you should probably check that it is equal to the string "Salted__"
        byte[] prefix = new byte[8];
        System.arraycopy(cipherText, 0, prefix, 0, 8);
        // Check here that prefix is equal to "Salted__"
        // Extract salt (next 8 bytes)
        byte[] salt = new byte[8];
        System.arraycopy(cipherText, 8, salt, 0, 8);
        // Extract the actual cipher text (the rest of the bytes)
        byte[] trueCipherText = new byte[cipherText.length - 16];
        System.arraycopy(cipherText, 16, trueCipherText, 0, cipherText.length - 16);
        byte[] javaKey = new byte[keySize * 4];
        byte[] javaIv = new byte[ivSize * 4];
        evpKDF(password.getBytes("UTF-8"), keySize, ivSize, salt, javaKey, javaIv);
        Cipher aesCipherForEncryption = Cipher.getInstance("AES/CBC/PKCS5Padding");
        IvParameterSpec ivSpec = new IvParameterSpec(javaIv);
        aesCipherForEncryption.init(Cipher.DECRYPT_MODE, new SecretKeySpec(javaKey, "AES"), ivSpec);
    
        byte[] byteMsg = aesCipherForEncryption.doFinal(trueCipherText);
        return new String(byteMsg, "UTF-8");
    }
    
    public  byte[] evpKDF(byte[] password, int keySize, int ivSize, byte[] salt, byte[] resultKey, byte[] resultIv) throws NoSuchAlgorithmException {
        return evpKDF(password, keySize, ivSize, salt, 1, "MD5", resultKey, resultIv);
    }
    
    public  byte[] evpKDF(byte[] password, int keySize, int ivSize, byte[] salt, int iterations, String hashAlgorithm, byte[] resultKey, byte[] resultIv) throws NoSuchAlgorithmException {
        int targetKeySize = keySize + ivSize;
        byte[] derivedBytes = new byte[targetKeySize * 4];
        int numberOfDerivedWords = 0;
        byte[] block = null;
        MessageDigest hasher = MessageDigest.getInstance(hashAlgorithm);
        while (numberOfDerivedWords < targetKeySize) {
            if (block != null) {
                hasher.update(block);
            }
            hasher.update(password);
            block = hasher.digest(salt);
            hasher.reset();
    
            // Iterations
            for (int i = 1; i < iterations; i++) {
                block = hasher.digest(block);
                hasher.reset();
            }
    
            System.arraycopy(block, 0, derivedBytes, numberOfDerivedWords * 4,
                    Math.min(block.length, (targetKeySize - numberOfDerivedWords) * 4));
    
            numberOfDerivedWords += block.length/4;
        }
    
        System.arraycopy(derivedBytes, 0, resultKey, 0, keySize * 4);
        System.arraycopy(derivedBytes, keySize * 4, resultIv, 0, ivSize * 4);
    
        return derivedBytes; // key + iv
    }
    

提交回复
热议问题