gpt4 book ai didi

java - 加密 - 使用 AES/BlowFish/DESede 和 Enum 解密

转载 作者:行者123 更新时间:2023-11-29 05:41:18 25 4
gpt4 key购买 nike

首先我要说声谢谢...

我写了一个程序,用枚举来加密和解密。枚举有 AES、BlowFish、DESede。我的程序将支持这 3 种加密算法。

然后我想用SecretKeyFactory生成一个SecretKey。但是我想,我在生成 key 时犯了一个错误。 (显然我在代码中放松了自己。我不知道我能做什么...)

我的代码如下。 这个程序的目的是

  • 用户将编写加密和解密方法参数。 (文本,加密算法)
  • 算法类型将在枚举类型中选择。 (枚举有3种算法格式)
  • 根据输入的加密类型,程序将对输入的文本进行加密。

我知道我的代码真的很糟糕。它有很多不必要的声明和逻辑错误。

代码有时运行良好,有时会崩溃。

EDIT = 问题是我的代码并不总是有效。有时会报错。 错误为 = javax.crypto.BadPaddingException:给定的最终 block 未正确填充

感谢您的回答

import java.security.SecureRandom;
import java.security.spec.KeySpec;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;

public class SymetricAlgorithms {

private static enum algorithms { //Enum declaration 3 encryption types here

AES, BlowFish, DESede;

}

private static String data = "HOWCANISOLVETHIS"; //this will be encrypt and decrypt

public static void main(String[] args) throws Throwable {

SecretKey kgen = GenerateKey(); // Create a key.
String encrypText = encrypt(kgen, data, algorithms.AES); //encrypt method calling here.
String decrypText = dencypt(kgen, encrypText, algorithms.AES);//decrypt method calling here.
System.out.println("plaintext = " + data + " key = " + kgen
+ "\nEncryptedText = " + encrypText
+ "\nDecryptedText = " + decrypText);

}

public static String dencypt(SecretKey inKey, String text, algorithms eValue)throws Throwable {//decryption
try {
byte[] text2 = text.getBytes(); //convert from parameters TEXT to Bytes
Cipher cipher = Cipher.getInstance("AES"); //Cipher initialize and choose encryption method (AES)
cipher.init(Cipher.DECRYPT_MODE, inKey); //cipher process
byte plainTextByte[] = new byte[20]; //Creating byte array
plainTextByte =cipher.doFinal(text2);//using byte array to assign ciphers result
System.out.println(plainTextByte);
return new String(plainTextByte);
} catch (Exception e) {
System.err.println("Data Cant Decrypted !");
e.printStackTrace();
}
return null;


}

public static String encrypt(SecretKey inKey, String text, algorithms eValue)
throws Throwable {
try {
Cipher cipher = null; //cipher declaration
switch (eValue) {//Enum. 3 types here and control structure for Users choosing encryption type is acceptable
case AES:cipher = Cipher.getInstance("AES");
break;
case BlowFish:Cipher cipher2 = Cipher.getInstance("BlowFish");
cipher = cipher2;
break;
case DESede:Cipher cipher3 = Cipher.getInstance("DESede");
cipher=cipher3;
break;
default:
System.out.println("Unexpectable value input.");
break;

}
System.out.println(inKey);
//Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, inKey);
byte[] ciphertext = cipher.doFinal(text.getBytes("UTF-8"));//cipher result is assign to byte array
System.out.println(ciphertext);
return new String(ciphertext);
} catch (Exception e) {
System.err.println("Unexpectable algorithm type !");
e.printStackTrace();
}
return null;

}

public static SecretKey GenerateKey() throws Throwable {//Generate a key for using crypt
//could sb explain these? =D I loose myself. I combined codes from finding internet...Failed...
try {
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
SecureRandom prng = SecureRandom.getInstance("SHA1PRNG");
byte bytes[] = new byte[20];
prng.nextBytes(bytes);
String passwordTemp = prng.toString();
String saltTemp = passwordTemp;
char[] password = passwordTemp.toCharArray();
byte[] salt = saltTemp.getBytes();
KeySpec spec = new PBEKeySpec(password, salt, 65536, 128);
SecretKey tmp = factory.generateSecret(spec);
SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");
return secret;
} catch (Exception e) {
System.err.println("Key cant be generated !");
e.printStackTrace();
}
return null;

}

}

最佳答案

问题的主题是对字符串和字节之间关系的误解。在加密方法的最后,你认为这两行是做什么的:

byte[] ciphertext = cipher.doFinal(...
return new String(ciphertext);

最后一行采用加密的字节,几乎可以是任何东西,并且尝试将这些字节解释为对字符串的某些字符进行编码。使用什么编码?不带字符编码参数的字符串构造函数使用系统默认编码,这取决于 JVM/OS/Locale。假设它是 UTF-8。您是否保证加密字节实际上某些字符?答:没有。当您获取结果字符串并调用 .getBytes("UTF-8") 时,您会得到相同的字节吗?答:不,有多个字节序列编码相同的字符,因此 new String(bytes, "UTF-8").getBytes("UTF-8") 不能保证返回您开始的字节。

总而言之,不要试图将任意字节解释为字符串。使您的加密方法返回 byte[],并且您的解密方法采用字节数组进行解码——然后它将起作用。

没有必要让你的程序运行,但如果你必须将加密的字节表示为字符串,请考虑 base64 编码或十六进制编码——这些编码唯一地将每个可能的字节(或字节序列)映射到一个字符串.

更新:这里有一个更简洁的 generateKey() 方法。它允许您将密码作为参数传递。

public static SecretKey generateKey(String password) {
try {
SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
byte saltBytes[] = new byte[20];
secureRandom.nextBytes(saltBytes);

KeySpec spec = new PBEKeySpec(password.toCharArray(), saltBytes, 65536, 128);
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
SecretKey secretKey = factory.generateSecret(spec);

return new SecretKeySpec(secretKey.getEncoded(), "AES");
} catch (Exception e) {
throw new IllegalStateException("Key cant be generated !");
}
}

关于java - 加密 - 使用 AES/BlowFish/DESede 和 Enum 解密,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17472684/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com