使用AES的Java加密

使用AES的Java加密,java,encryption,Java,Encryption,我正在尝试使用AES类创建加密系统: package Source; import java.security.MessageDigest; import java.util.Arrays; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import javax.crypto.spec.IvParameterSpec; import

我正在尝试使用AES类创建加密系统:

package Source;
import java.security.MessageDigest;
import java.util.Arrays;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import javax.crypto.spec.IvParameterSpec;

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

public class AES {
  static String IV = "AAAAAAAAAAAAAAAA";
  static String plaintext = "test text 123\0\0\0"; /*Note null padding*/
  static String encryptionKey = "H4tch4repratygonetowil5h4kers";
  public static void main(String [] args) {
    try {

      System.out.println("==Java==");
      System.out.println("plain:   " + plaintext);

      byte[] cipher = encrypt(plaintext, encryptionKey);

      System.out.print("cipher:  ");
      for (int i=0; i<cipher.length; i++)
        System.out.print(new Integer(cipher[i])+" ");
      System.out.println("");

      String decrypted = decrypt(cipher, encryptionKey);

      System.out.println("decrypt: " + decrypted);

    } catch (Exception e) {
      e.printStackTrace();
    } 
  }

  public static byte[] encrypt(String plainText, String encryptionKey) throws Exception {
    Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding", "SunJCE");
    SecretKeySpec key = new SecretKeySpec(encryptionKey.getBytes("UTF-8"), "AES");
    cipher.init(Cipher.ENCRYPT_MODE, key,new IvParameterSpec(IV.getBytes("UTF-8")));
    return cipher.doFinal(plainText.getBytes("UTF-8"));
  }

  private static String decrypt(byte[] cipherText, String encryptionKey) throws Exception{
    Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding", "SunJCE");
    SecretKeySpec key = new SecretKeySpec(encryptionKey.getBytes("UTF-8"), "AES");
    cipher.init(Cipher.DECRYPT_MODE, key,new IvParameterSpec(IV.getBytes("UTF-8")));
    return new String(cipher.doFinal(cipherText),"UTF-8");
  }
}
如何使变量'str'实际具有加密文本的值?在运行时,我得到错误和一个空字段。。。可以将字节[]更改为字符串吗

更新错误:

java.lang.IllegalArgumentException:空键 在javax.crypto.spec.SecretKeySpec.(SecretKeySpec.java:96) 在Source.AES.encrypt(AES.java:41) 最初$2.actionPerformed(first.java:62) 在javax.swing.AbstractButton.fireActionPerformed(未知源) 位于javax.swing.AbstractButton$Handler.actionPerformed(未知源) 在javax.swing.DefaultButtonModel.fireActionPerformed(未知源) 位于javax.swing.DefaultButtonModel.setPressed(未知源) 位于javax.swing.plaf.basic.BasicButtonListener.mouseReleased(未知源代码) 位于java.awt.Component.ProcessMouseeEvent(未知源) 位于javax.swing.JComponent.ProcessMouseeEvent(未知源) 位于java.awt.Component.processEvent(未知源) 位于java.awt.Container.processEvent(未知源) 位于java.awt.Component.dispatchEventImpl(未知源) 位于java.awt.Container.dispatchEventImpl(未知源) 位于java.awt.Component.dispatchEvent(未知源) 位于java.awt.LightweightDispatcher.RetargetMouseeEvent(未知源) 位于java.awt.LightweightDispatcher.ProcessMouseeEvent(未知源) 位于java.awt.LightweightDispatcher.dispatchEvent(未知源) 位于java.awt.Container.dispatchEventImpl(未知源) 位于java.awt.Window.dispatchEventImpl(未知源) 位于java.awt.Component.dispatchEvent(未知源) 位于java.awt.EventQueue.dispatchEventImpl(未知源) 位于java.awt.EventQueue.access$500(未知源) 在java.awt.EventQueue$3.run处(未知源) 在java.awt.EventQueue$3.run处(未知源) 位于java.security.AccessController.doPrivileged(本机方法) 位于java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(未知源) 位于java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(未知源) 在java.awt.EventQueue$4.run处(未知源) 在java.awt.EventQueue$4.run处(未知源) 位于java.security.AccessController.doPrivileged(本机方法) 位于java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(未知源) 位于java.awt.EventQueue.dispatchEvent(未知源) 位于java.awt.EventDispatchThread.pumpOneEventForFilters(未知源) 位于java.awt.EventDispatchThread.pumpEventsForFilter(未知源) 位于java.awt.EventDispatchThread.pumpEventsForHierarchy(未知源) 位于java.awt.EventDispatchThread.pumpEvents(未知源) 位于java.awt.EventDispatchThread.pumpEvents(未知源) 位于java.awt.EventDispatchThread.run(未知源)


这里有几个问题

  • 您在javax.crypto.spec.SecretKeySpec中有
    空密钥
    异常,因为您没有输入任何密码

  • 输入密码后,会出现异常,如
    无效AES密钥长度:8字节
    ,因为密钥应为特定长度(请参阅更多信息)

  • 使用哈希生成密钥后,将出现以下异常-
    javax.crypto.IllegalBlockSizeException:输入长度不是16字节的倍数,因为加密模式不使用填充。您可以将其更改为类似于
    AES/CBC/pkcs5pdadding

  • 最后,使用以下“加密”方法,您将得到您想要的:

    public static byte[] encrypt(String plainText, String encryptionKey) throws Exception {
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding", "SunJCE");
        MessageDigest sha = MessageDigest.getInstance("SHA-1");
        byte [] hashedPassword = sha.digest(encryptionKey.getBytes("UTF-8"));
        hashedPassword = Arrays.copyOf(hashedPassword, 16);
        SecretKeySpec key = new SecretKeySpec(hashedPassword, "AES");
        cipher.init(Cipher.ENCRYPT_MODE, key,new IvParameterSpec(IV.getBytes("UTF-8")));
        return cipher.doFinal(plainText.getBytes("UTF-8"));
    }
    

    (*)当然,为了解密消息,您还必须对“decrypt”方法进行类似的更改

    你得到的运行时错误是什么?我已经根据错误更新了我的帖子,似乎
    SecretKeySpec
    Constructor有问题一般建议:请不要使用固定的IV。IV是一个非机密值,在加密过程中新生成时,应该提供语义安全性。因为它不是秘密,所以可以和密文一起发送。一种常见的方法是在加密期间将其预编到密文中,并在解密期间将其切掉。
    public static byte[] encrypt(String plainText, String encryptionKey) throws Exception {
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding", "SunJCE");
        MessageDigest sha = MessageDigest.getInstance("SHA-1");
        byte [] hashedPassword = sha.digest(encryptionKey.getBytes("UTF-8"));
        hashedPassword = Arrays.copyOf(hashedPassword, 16);
        SecretKeySpec key = new SecretKeySpec(hashedPassword, "AES");
        cipher.init(Cipher.ENCRYPT_MODE, key,new IvParameterSpec(IV.getBytes("UTF-8")));
        return cipher.doFinal(plainText.getBytes("UTF-8"));
    }