Java AES并使用我自己的密钥

Ber*_*rez 85 java key aes

我想用自己的密钥使用AES加密字符串.但是我遇到了密钥的位长问题.你能查看我的代码,看看我需要修改/改变什么.

public static void main(String[] args) throws Exception {
    String username = "bob@google.org";
    String password = "Password1";
    String secretID = "BlahBlahBlah";
    String SALT2 = "deliciously salty";

    // Get the Key
    byte[] key = (SALT2 + username + password).getBytes();
    System.out.println((SALT2 + username + password).getBytes().length);

    // Need to pad key for AES
    // TODO: Best way?

    // Generate the secret key specs.
    SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");

    // Instantiate the cipher
    Cipher cipher = Cipher.getInstance("AES");
    cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);

    byte[] encrypted = cipher.doFinal((secrectID).getBytes());
    System.out.println("encrypted string: " + asHex(encrypted));

    cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
    byte[] original = cipher.doFinal(encrypted);
    String originalString = new String(original);
    System.out.println("Original string: " + originalString + "\nOriginal string (Hex): " + asHex(original));
}
Run Code Online (Sandbox Code Playgroud)

现在我得到一个例外" 无效的AES密钥长度:86字节 ".我需要填上钥匙吗?我该怎么办?

我还需要为ECB或CBC设置任何内容吗?

谢谢

mkn*_*njc 121

您应该使用SHA-1从密钥生成哈希,并将结果修剪为128位(16字节).

另外,不要通过getBytes()从Strings生成字节数组,它使用平台默认的Charset.因此密码"blaöä"会在不同平台上产生不同的字节数组.

    SecureRandom sr = SecureRandom.getInstanceStrong();
    byte[] salt = new byte[16];
    sr.nextBytes(salt);

    PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 1000, 128 * 8);
    SecretKey key = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1").generateSecret(spec);
    Cipher aes = Cipher.getInstance("AES");
    aes.init(Cipher.ENCRYPT_MODE, key);
Run Code Online (Sandbox Code Playgroud)

编辑:如果您需要256位作为密钥大小,您需要下载"Java密码术扩展(JCE)无限强度管辖权策略文件" Oracle下载链接,使用SHA-256作为哈希并删除Arrays.copyOf行."ECB"是默认的密码模式,"PKCS5Padding"是默认的填充.您可以使用以下格式通过Cipher.getInstance字符串使用不同的密码模式和填充模式:"Cipher/Mode/Padding"

对于使用CTS和PKCS5Padding的AES,字符串为:"AES/CTS/PKCS5Padding"

  • 请注意,此答案不使用良好的密钥派生函数,因此**不如**应该安全.有关稍微过时的密钥派生函数,请参阅[其他答案](http://stackoverflow.com/a/3451823/589259) - 遗憾的是仍然是静态盐. (12认同)
  • 没有更好的方法来生成密钥,因为AES需要128/192/256位密钥.如果你不对哈希值进行哈希处理,只修改输入,那么它只会使用前16/24/32字节.因此,生成哈希是唯一合理的方法. (4认同)
  • 我可能建议删除此答案,因为这是“极端”不当做法。应该使用适当的密钥派生功能-至少为PBKDF2。 (2认同)

Kei*_*osh 14

您应该使用KeyGenerator生成密钥,

AES密钥长度为128,192和256位,具体取决于您要使用的密码.

看看这里的教程

这是基于密码的加密的代码,它具有通过System.in输入的密码.如果需要,您可以将其更改为使用存储的密码.

        PBEKeySpec pbeKeySpec;
        PBEParameterSpec pbeParamSpec;
        SecretKeyFactory keyFac;

        // Salt
        byte[] salt = {
            (byte)0xc7, (byte)0x73, (byte)0x21, (byte)0x8c,
            (byte)0x7e, (byte)0xc8, (byte)0xee, (byte)0x99
        };

        // Iteration count
        int count = 20;

        // Create PBE parameter set
        pbeParamSpec = new PBEParameterSpec(salt, count);

        // Prompt user for encryption password.
        // Collect user password as char array (using the
        // "readPassword" method from above), and convert
        // it into a SecretKey object, using a PBE key
        // factory.
        System.out.print("Enter encryption password:  ");
        System.out.flush();
        pbeKeySpec = new PBEKeySpec(readPassword(System.in));
        keyFac = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
        SecretKey pbeKey = keyFac.generateSecret(pbeKeySpec);

        // Create PBE Cipher
        Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES");

        // Initialize PBE Cipher with key and parameters
        pbeCipher.init(Cipher.ENCRYPT_MODE, pbeKey, pbeParamSpec);

        // Our cleartext
        byte[] cleartext = "This is another example".getBytes();

        // Encrypt the cleartext
        byte[] ciphertext = pbeCipher.doFinal(cleartext);
Run Code Online (Sandbox Code Playgroud)

  • 实际上***在这个答案中所有使用过的加密原语都是过时的***,MD5和DES肯定.谨慎. (12认同)
  • 尝试使用PBEKDF2密钥生成器,使用字符串"PBKDF2WithHmacSHA1"作为"SecretKeyFactory"进行更新的加密. (5认同)
  • 如何使用KeyGenerator生成密码?我想根据密码生成相同的密钥.所以我可以稍后解密字符串. (3认同)

小智 5

import java.security.Key;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import sun.misc.*;
import java.io.BufferedReader;
import java.io.FileReader;

public class AESFile 
{
private static String algorithm = "AES";
private static byte[] keyValue=new byte[] {'0','2','3','4','5','6','7','8','9','1','2','3','4','5','6','7'};// your key

    // Performs Encryption
    public static String encrypt(String plainText) throws Exception 
    {
            Key key = generateKey();
            Cipher chiper = Cipher.getInstance(algorithm);
            chiper.init(Cipher.ENCRYPT_MODE, key);
            byte[] encVal = chiper.doFinal(plainText.getBytes());
            String encryptedValue = new BASE64Encoder().encode(encVal);
            return encryptedValue;
    }

    // Performs decryption
    public static String decrypt(String encryptedText) throws Exception 
    {
            // generate key 
            Key key = generateKey();
            Cipher chiper = Cipher.getInstance(algorithm);
            chiper.init(Cipher.DECRYPT_MODE, key);
            byte[] decordedValue = new BASE64Decoder().decodeBuffer(encryptedText);
            byte[] decValue = chiper.doFinal(decordedValue);
            String decryptedValue = new String(decValue);
            return decryptedValue;
    }

//generateKey() is used to generate a secret key for AES algorithm
    private static Key generateKey() throws Exception 
    {
            Key key = new SecretKeySpec(keyValue, algorithm);
            return key;
    }

    // performs encryption & decryption 
    public static void main(String[] args) throws Exception 
    {
        FileReader file = new FileReader("C://myprograms//plaintext.txt");
        BufferedReader reader = new BufferedReader(file);
        String text = "";
        String line = reader.readLine();
    while(line!= null)
        {
            text += line;
    line = reader.readLine();
        }
        reader.close();
    System.out.println(text);

            String plainText = text;
            String encryptedText = AESFile.encrypt(plainText);
            String decryptedText = AESFile.decrypt(encryptedText);

            System.out.println("Plain Text : " + plainText);
            System.out.println("Encrypted Text : " + encryptedText);
            System.out.println("Decrypted Text : " + decryptedText);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 也许添加更多解释文字. (5认同)
  • 不建议使用硬编码的密钥 (2认同)