有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

Angular 4中的AES 128加密和Java中的解密

我在Angular 4中使用CryptoJS(AES)进行加密,代码如下:

const key = CryptoJS.enc.Utf8.parse('7061737323313233');
const iv = CryptoJS.enc.Utf8.parse('7061737323313233');
const encrypted = CryptoJS.AES.encrypt('String to encrypt', key, {
  keySize: 16,
  iv: iv,
  mode: CryptoJS.mode.ECB,
  padding: CryptoJS.pad.Pkcs7
});
console.log('Encrypted :' + encrypted);

下面是使用AES解密的java代码:

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Base64;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;

public class Encryption {

private static SecretKeySpec secretKey;
private static byte[] key;

public static void setKey(String myKey)
{
    MessageDigest sha = null;
    try {
        key = myKey.getBytes("UTF-8");
        sha = MessageDigest.getInstance("SHA-1");
        key = sha.digest(key);
        key = Arrays.copyOf(key, 16);
        secretKey = new SecretKeySpec(key, "AES");
    }
    catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
    catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    }
}

public static String encrypt(String strToEncrypt, String secret)
{
    try
    {
        setKey(secret);
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING");
        cipher.init(Cipher.ENCRYPT_MODE, secretKey);
        return Base64.getEncoder().encodeToString(cipher.doFinal(strToEncrypt.getBytes("UTF-8")));
    }
    catch (Exception e)
    {
        System.out.println("Error while encrypting: " + e.toString());
    }
    return null;
}

public static String decrypt(String strToDecrypt, String secret)
{
    try
    {
        setKey(secret);
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING");
        cipher.init(Cipher.DECRYPT_MODE, secretKey);
        return new String(cipher.doFinal(Base64.getDecoder().decode(strToDecrypt)));
    }
    catch (Exception e)
    {
        System.out.println("Error while decrypting: " + e.toString());
    }
    return null;
}
 }

public class Test {
public static void main(String[] args) {
    final String secretKey = "7061737323313233";
    String originalString = "Response from angular";
    String decryptedString = Encryption.decrypt(originalString, secretKey);
    System.out.println(decryptedString);
}
 }

Angular和java这两个代码都可以很好地工作,如果我独立地运行它进行加密和解密的话。但当我使用angular加密并使用java解密时,会出现错误:

Error while decrypting: javax.crypto.BadPaddingException: Given final block not properly padded

现在我的问题是,angular和java中的填充存在差异。在angular中是Pkcs7,在java中是Pkcs5,但是这个链接Padding 说两者都是一样的,为什么会出现这个错误。请帮帮我


共 (2) 个答案

  1. # 1 楼答案

    我生成密钥的代码在java中生成了坏密钥。所以我把它改成:

     Key key = new SecretKeySpec(key.getBytes("UTF-8"),"AES" );
    

    现在它可以正常工作了

  2. # 2 楼答案

    这是一个小问题,因为Javascript和Java库不同

    请按照下面的代码操作,我成功地用Java加密数据并用Java解密

    import java.security.Key;
    import java.util.Base64;
    import javax.crypto.Cipher;
    import javax.crypto.spec.SecretKeySpec;
    
    public class Crypt {
    
        private static final String ALGO = "AES"; // Default uses ECB PKCS5Padding
    
        public static String encrypt(String Data, String secret) throws Exception {
            Key key = generateKey(secret);
            Cipher c = Cipher.getInstance(ALGO);
            c.init(Cipher.ENCRYPT_MODE, key);
            byte[] encVal = c.doFinal(Data.getBytes());
            String encryptedValue = Base64.getEncoder().encodeToString(encVal);
            return encryptedValue;
        }
    
        public static String decrypt(String strToDecrypt, String secret) {
    
            try {
                Key key = generateKey(secret);
                Cipher cipher = Cipher.getInstance(ALGO);
                cipher.init(Cipher.DECRYPT_MODE, key);
                return new String(cipher.doFinal(Base64.getDecoder().decode(strToDecrypt)));
            } catch (Exception e) {
                System.out.println("Error while decrypting: " + e.toString());
            }
            return null;
        }
    
        private static Key generateKey(String secret) throws Exception {
            byte[] decoded = Base64.getDecoder().decode(secret.getBytes());
            Key key = new SecretKeySpec(decoded, ALGO);
            return key;
        }
    
        public static String decodeKey(String str) {
            byte[] decoded = Base64.getDecoder().decode(str.getBytes());
            return new String(decoded);
        }
    
        public static String encodeKey(String str) {
            byte[] encoded = Base64.getEncoder().encode(str.getBytes());
            return new String(encoded);
        }
    
        public static void main(String a[]) throws Exception {
            /*
             * Secret Key must be in the form of 16 byte like,
             *
             * private static final byte[] secretKey = new byte[] { ‘m’, ‘u’, ‘s’, ‘t’, ‘b’,
             * ‘e’, ‘1’, ‘6’, ‘b’, ‘y’, ‘t’,’e’, ‘s’, ‘k’, ‘e’, ‘y’};
             *
             * below is the direct 16byte string we can use
             */
            String secretKey = "mustbe16byteskey";
            String encodedBase64Key = encodeKey(secretKey);
            System.out.println("EncodedBase64Key = " + encodedBase64Key); // This need to be share between client and server
    
            // To check actual key from encoded base 64 secretKey
            // String toDecodeBase64Key = decodeKey(encodedBase64Key);
            // System.out.println("toDecodeBase64Key = "+toDecodeBase64Key);
            String toEncrypt = "Please encrypt this message!";
            System.out.println("Plain text = " + toEncrypt);
    
            // AES Encryption based on above secretKey
            String encrStr = Crypt.encrypt(toEncrypt, encodedBase64Key);
            System.out.println("Cipher Text: Encryption of str = " + encrStr);
    
            // AES Decryption based on above secretKey
            String decrStr = Crypt.decrypt(encrStr, encodedBase64Key);
            System.out.println("Decryption of str = " + decrStr);
        }
    }
    
    <!DOCTYPE html>
    <html>
    
    <body>
        <h2>Java JavaScript Encryption & Decryption</h2>
        <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9-1/crypto-js.min.js"></script>
        <script type="text/javascript">
            console.log('crypto - js’, CryptoJS);
            var encryptedBase64Key = 'bXVzdGJlMTZieXRlc2tleQ==’;
            var parsedBase64Key = CryptoJS.enc.Base64.parse(encryptedBase64Key);
            var encryptedData = null;
            {
                // Encryption process
                var plaintText = "Please encrypt this message!”;
                // console.log( "plaintText = " + plaintText );
                // this is Base64-encoded encrypted data
                encryptedData = CryptoJS.AES.encrypt(plaintText, parsedBase64Key, {
                    mode: CryptoJS.mode.ECB,
                    padding: CryptoJS.pad.Pkcs7
                });
                console.log("encryptedData = " + encryptedData);
            }
            {
                // Decryption process
                var encryptedCipherText = 'U2WvSc8oTur1KkrB6VGNDmA3XxJb9cC+T9RnqT4kD90=’; // or encryptedData;
                var decryptedData = CryptoJS.AES.decrypt(encryptedCipherText, parsedBase64Key, {
                    mode: CryptoJS.mode.ECB,
                    padding: CryptoJS.pad.Pkcs7
                });
                // console.log( "DecryptedData = " + decryptedData );
                // this is the decrypted data as a string
                var decryptedText = decryptedData.toString(CryptoJS.enc.Utf8);
                console.log("DecryptedText = " + decryptedText);
            }
        </script>
    </body>
    
    </html>