Java AES提高安全性,keystring需要多长

Java AES improve safety, how long does the keystring need to be

Java中的加密和解密对我来说还是很难理解。我一直在使用以下 class 和方法。我想知道如何提高安全性以及密钥字符串 (schlüssel) 需要多长?

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

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

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

public class AES
{
public static SecretKeySpec makeKey(String schlüssel) throws NoSuchAlgorithmException, UnsupportedEncodingException
{
    byte[] key = (schlüssel).getBytes("UTF-8");
    MessageDigest sha = MessageDigest.getInstance("SHA");
    key = sha.digest(key);
    key = Arrays.copyOf(key, 16);
    return new SecretKeySpec(key, "AES");
}


public static String encryptString(String text, SecretKeySpec schlüssel) throws Exception
{
    Cipher cipher = Cipher.getInstance("AES");
    cipher.init(Cipher.ENCRYPT_MODE, schlüssel);
    byte[] encrypted = cipher.doFinal(text.getBytes());

    BASE64Encoder myEncoder = new BASE64Encoder();
    return myEncoder.encode(encrypted);
}


public static String decryptString(String text, SecretKeySpec schlüssel) throws Exception
{    
    BASE64Decoder myDecoder2 = new BASE64Decoder();
    byte[] crypted2 = myDecoder2.decodeBuffer(text);

    Cipher cipher2 = Cipher.getInstance("AES");
    cipher2.init(Cipher.DECRYPT_MODE, schlüssel);
    byte[] cipherData2 = cipher2.doFinal(crypted2);
    return new String(cipherData2);
}
}

我一直在阅读有关该主题的内容。但是我不明白如何将这些想法转化为我的代码。感谢任何帮助,请善待加密初学者。谢谢。

这个class有很多错误。

  • class 使用密码散列而不是密码散列 - 例如 PBKDF2 - 从密码中导出 密钥;
  • 您正在使用 ECB 模式加密(默认),您至少需要使用 CBC,以及一个初始化向量 (IV);
  • 你的 class 没有添加任何完整性保护,换句话说密文是 malleable;

是否需要完整性保护取决于用例。因此,我会将您指向 this question,以获取有关基于密码的加密 (PBE) 的更多信息。请注意,答案可能仍会提供可延展的密文。

此外 class 包含以下 Java 错误:

  • 它不区分运行时相关异常(缺失算法)和输入相关异常;
  • 它使用明文的默认平台编码;
  • 它正在使用 Sun 内部 class 来执行 Base 64 encoding/decoding。

请注意,人们可能会向您指出您使用的是 128 位 AES 加密。然而,这是非常强大的,而且 - 当然在这个时间点 - 你最不担心的。升级到 192 或 256 位 AES 不会显着提高安全性。

参考 Maarten Bodewes 代码,我尝试将他的代码带入我正在使用的形式。

import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;

public class AESplus 
{
public static SecretKeySpec makeKey(String password) throws NoSuchAlgorithmException, UnsupportedEncodingException
{
password = String.format("%040x", new BigInteger(1,password.getBytes(Charset.forName("UTF-8"))));
    password = password.substring(password.length()-32, password.length());
    final byte[] symKeyData = DatatypeConverter.parseHexBinary(password);
    return new SecretKeySpec(symKeyData, "AES");
}


public static String encryptString(String text, SecretKeySpec key) throws NoSuchAlgorithmException, NoSuchPaddingException, 
                    InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException
{
    final byte[] encodedMessage = text.getBytes(Charset.forName("UTF-8"));

    final Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    final int blockSize = cipher.getBlockSize();

    // generate random IV using block size
    final byte[] ivData = new byte[blockSize];
    final SecureRandom rnd = SecureRandom.getInstance("SHA1PRNG");
    rnd.nextBytes(ivData);
    final IvParameterSpec iv = new IvParameterSpec(ivData);

    cipher.init(Cipher.ENCRYPT_MODE, key, iv);
    final byte[] encryptedMessage = cipher.doFinal(encodedMessage);

    // concatenate IV and encrypted message
    final byte[] ivAndEncryptedMessage = new byte[ivData.length + encryptedMessage.length];
    System.arraycopy(ivData, 0, ivAndEncryptedMessage, 0, blockSize);
    System.arraycopy(encryptedMessage, 0, ivAndEncryptedMessage, blockSize, encryptedMessage.length);
    return DatatypeConverter.printBase64Binary(ivAndEncryptedMessage);
}


public static String decrytString(String crypttext, SecretKeySpec key) throws NoSuchAlgorithmException, NoSuchPaddingException, 
                        InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException 
{    
    final byte[] ivAndEncryptedMessage = DatatypeConverter.parseBase64Binary(crypttext);

    final Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    final int blockSize = cipher.getBlockSize();

    // retrieve random IV from start of the received message
    final byte[] ivData = new byte[blockSize];
    System.arraycopy(ivAndEncryptedMessage, 0, ivData, 0, blockSize);
    final IvParameterSpec iv = new IvParameterSpec(ivData);

    // retrieve the encrypted message itself
    final byte[] encryptedMessage = new byte[ivAndEncryptedMessage.length - blockSize];
    System.arraycopy(ivAndEncryptedMessage, blockSize, encryptedMessage, 0, encryptedMessage.length);

    cipher.init(Cipher.DECRYPT_MODE, key, iv);
    final byte[] encodedMessage = cipher.doFinal(encryptedMessage);

    // concatenate IV and encrypted message
    final String message = new String(encodedMessage,Charset.forName("UTF-8"));

    return message;
}

}