如何在cipher.doFinal方法中修复“解密过程”

时间:2019-06-10 11:47:23

标签: java cryptography

要求:

  • 使用AES加密(带有GCMParameterSpec和nonce)对字符串进行加密。
  • 将随机数附加到“加密的字符串”以供以后解密。
  • 通过提取随机数和要解密的字符串来解密字符串。

我已经按照要求编写了用于加密和解密字符串的代码,但是我面临着“解密标签不匹配时出错!”

有人可以帮助我确定问题所在吗?谢谢!

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

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

public class AES {
    private static SecretKeySpec secretKey;
    private static byte[] key;
    private static final String ENCODING_TYPE = "UTF-8";
    private static final String ALGORITHM = "AES";
    private static final String TRANSFORMATION_VALUE = "AES/GCM/NoPadding";

    public static void setKey(String myKey, String hashingType) {
        MessageDigest sha = null;
        try {
            key = myKey.getBytes(ENCODING_TYPE);
            sha = MessageDigest.getInstance(hashingType);
            key = sha.digest(key);
            key = Arrays.copyOf(key, 16);
            secretKey = new SecretKeySpec(key, ALGORITHM);
        } catch (NoSuchAlgorithmException e) {
            System.out.println("NoSuchAlgorithmException "+e.getMessage());
        } catch (UnsupportedEncodingException e) {
            System.out.println("UnsupportedEncodingException "+e.getMessage());
        } catch (Exception e) {
            System.out.println("Exception Occured! "+e.getMessage());
        }
    }

    public static String encrypt(String strToEncrypt, String secret, String hashingType) {
        String encryptedString = null;
        try {
            byte[] nonce = new byte[12];
            setKey(secret,hashingType);
            SecureRandom random = SecureRandom.getInstanceStrong();
            random.nextBytes(nonce);
            final Cipher encryptCipher = Cipher.getInstance(TRANSFORMATION_VALUE);
            encryptCipher.init(Cipher.ENCRYPT_MODE, secretKey, new GCMParameterSpec(16 * 8, nonce));
            byte[] cipheredString = encryptCipher.doFinal(strToEncrypt.getBytes());
            ByteBuffer byteBuffer = ByteBuffer.allocate(nonce.length + cipheredString.length);
            byteBuffer.put(nonce);
            byteBuffer.put(cipheredString);
            encryptedString = Base64.getEncoder().encodeToString(byteBuffer.array());       //Encoding the ByteArrayOutputStream result object to Base64 format
        } catch (NoSuchAlgorithmException e) {
            System.out.println("NoSuchAlgorithmException "+e.getMessage());
        } catch (Exception e) {
            System.out.println("Error while encrypting "+e.getMessage());
        }
        return encryptedString;
    }

    public static String decrypt(String strToDecrypt, String secret, String hashingType) {
        String decryptedString = null;
        try {
            byte[] nonce = new byte[12];
            setKey(secret,hashingType);
            final Cipher decryptCipher = Cipher.getInstance(TRANSFORMATION_VALUE);
            ByteBuffer byteBuffer = ByteBuffer.wrap(Base64.getDecoder().decode(strToDecrypt));
            byteBuffer.get(nonce);
            byte[] cipheredString = new byte[byteBuffer.remaining()];
            byteBuffer.get(cipheredString);
            decryptCipher.init(Cipher.DECRYPT_MODE, secretKey, new GCMParameterSpec(16 * 8, nonce));
            decryptedString = new String(decryptCipher.doFinal(cipheredString));
        } catch (Exception e) {
            System.out.println("Error while decrypting "+e.getMessage());
        }
        return decryptedString;
    }
}


    public class TestAESEncrypt {

        public static void main(String[] args) {
            final String secretKey = "NEWTEST@Key123";
            String originalString = "Gamer_123.aa01@gmail.com";
            String encryptedString = AESEncryption.encrypt(originalString, secretKey, "SHA-256");
            System.out.println("String to Encrypt : "+originalString);
            System.out.println("Encrypted String : "+encryptedString);
        }
    }


    public class TestAESDecryption {

        public static void main(String[] args) {
            final String secretKey = "NEWTEST@Key123";
            String encryptedData = "ey4E+5zNPx4WLx5q0Srf7d1TN/sAzsdYuVmnihXQoA/yoYoxAO/ygrtuh+Zr9rZQ"; //Paste the encrypted string here
            String decryptedString = AESEncryption.decrypt(encryptedData, secretKey, "SHA-256") ;
            System.out.println("Encrypted String : "+encryptedData);
            System.out.println("Decrypted String: "+decryptedString);
        }
    }

2 个答案:

答案 0 :(得分:0)

这将从不起作用:

encryptedString = new String(cipher.doFinal(strToEncrypt.getBytes()));  //Creating a ciphered string
encryptedString += new String(nonce); //Appending nonce to the encrypted string
encryptedString = new String(Base64.getEncoder().encode(encryptedString.getBytes()));   //Encoding ciphered string to Base64 format

一旦尝试将原始字节转换为字符串,就可能破坏了数据。之后对它进行Base64编码将无法保存您。相反,您必须执行以下操作:

ByteArrayOutputStream result = new ByteArrayOutputStream();
result.write(nonce);
result.write(cipher.doFinal(strToEncrypt.getBytes()));
String encryptedString = Base64.getEncoder().encodeToString(result.toByteArray());

此外,我注意到您的随机数只有8个字节。可能太短了,您应该将其设置为12个字节。

答案 1 :(得分:-1)

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

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

public class AES {
    private static SecretKeySpec secretKey;
    private static byte[] key;
    private static final String ENCODING_TYPE = "UTF-8";
    private static final String ALGORITHM = "AES";
    private static final String TRANSFORMATION_VALUE = "AES/GCM/NoPadding";

    public static void setKey(String myKey, String hashingType) {
        MessageDigest sha = null;
        try {
            key = myKey.getBytes(ENCODING_TYPE);
            sha = MessageDigest.getInstance(hashingType);
            key = sha.digest(key);
            key = Arrays.copyOf(key, 16);
            secretKey = new SecretKeySpec(key, ALGORITHM);
        } catch (NoSuchAlgorithmException e) {
            System.out.println("NoSuchAlgorithmException "+e.getMessage());
        } catch (UnsupportedEncodingException e) {
            System.out.println("UnsupportedEncodingException "+e.getMessage());
        } catch (Exception e) {
            System.out.println("Exception Occured! "+e.getMessage());
        }
    }

    public static String encrypt(String strToEncrypt, String secret, String hashingType) {
        String encryptedString = null;
        try {
            byte[] nonce = new byte[12];
            setKey(secret,hashingType);
            SecureRandom random = SecureRandom.getInstanceStrong();
            random.nextBytes(nonce);
            final Cipher encryptCipher = Cipher.getInstance(TRANSFORMATION_VALUE);
            encryptCipher.init(Cipher.ENCRYPT_MODE, secretKey, new GCMParameterSpec(16 * 8, nonce));
            byte[] cipheredString = encryptCipher.doFinal(strToEncrypt.getBytes());
            ByteBuffer byteBuffer = ByteBuffer.allocate(nonce.length + cipheredString.length);
            byteBuffer.put(nonce);
            byteBuffer.put(cipheredString);
            encryptedString = Base64.getEncoder().encodeToString(byteBuffer.array());       //Encoding the ByteArrayOutputStream result object to Base64 format
        } catch (NoSuchAlgorithmException e) {
            System.out.println("NoSuchAlgorithmException "+e.getMessage());
        } catch (Exception e) {
            System.out.println("Error while encrypting "+e.getMessage());
        }
        return encryptedString;
    }

    public static String decrypt(String strToDecrypt, String secret, String hashingType) {
        String decryptedString = null;
        try {
            byte[] nonce = new byte[12];
            setKey(secret,hashingType);
            final Cipher decryptCipher = Cipher.getInstance(TRANSFORMATION_VALUE);
            ByteBuffer byteBuffer = ByteBuffer.wrap(Base64.getDecoder().decode(strToDecrypt));
            byteBuffer.get(nonce);
            byte[] cipheredString = new byte[byteBuffer.remaining()];
            byteBuffer.get(cipheredString);
            decryptCipher.init(Cipher.DECRYPT_MODE, secretKey, new GCMParameterSpec(16 * 8, nonce));
            decryptedString = new String(decryptCipher.doFinal(cipheredString));
        } catch (Exception e) {
            System.out.println("Error while decrypting "+e.getMessage());
        }
        return decryptedString;
    }
}