Chcę zaszyfrować ciąg przy użyciu AES z własnym kluczem. Ale mam problem z długością klucza. Czy możesz przejrzeć mój kod i zobaczyć, co muszę poprawić / zmienić.
public static void main(String[] args) throws Exception {
String username = "[email protected]";
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));
}
W tej chwili pojawia się wyjątek „ Nieprawidłowa długość klucza AES: 86 bajtów ”. Czy muszę wprowadzić swój klucz? Jak mam to zrobić?
Czy muszę też cokolwiek ustawiać dla EBC lub CBC?
Dzięki
Odpowiedzi:
Edytować:
Jak napisano w komentarzach, stary kod nie jest „najlepszą praktyką”. Należy użyć algorytmu generowania kluczy, takiego jak PBKDF2, z dużą liczbą iteracji. Powinieneś także użyć przynajmniej częściowo niestatycznej (to znaczy dla każdej „wyłącznie tożsamości”) soli. Jeśli to możliwe, generowane losowo i przechowywane razem z szyfrogramem.
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);
===========
Stara odpowiedź
Powinieneś użyć SHA-1, aby wygenerować skrót z klucza i przyciąć wynik do 128 bitów (16 bajtów).
Dodatkowo nie generuj tablic bajtowych ze Strings przez getBytes () , używa domyślnego zestawu znaków platformy. Zatem hasło „blaöä” skutkuje inną tablicą bajtów na różnych platformach.
byte[] key = (SALT2 + username + password).getBytes("UTF-8"); MessageDigest sha = MessageDigest.getInstance("SHA-1"); key = sha.digest(key); key = Arrays.copyOf(key, 16); // use only first 128 bit SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
Edycja: jeśli potrzebujesz klucza o rozmiarze 256 bitów, musisz pobrać łącze do pobierania Oracle „Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files” , użyj SHA-256 jako skrótu i usuń wiersz Arrays.copyOf . „ECB” to domyślny tryb szyfrowania, a „PKCS5Padding” to domyślne wypełnienie. Możesz użyć różnych trybów szyfrowania i trybów dopełnienia za pomocą ciągu Cipher.getInstance przy użyciu następującego formatu: „Cipher / Mode / Padding”
W przypadku AES używających CTS i PKCS5Padding ciąg to: „AES / CTS / PKCS5Padding”
źródło
Do wygenerowania klucza należy użyć KeyGeneratora,
Klucze AES mają długość 128, 192 i 256 bitów, w zależności od szyfru, którego chcesz użyć.
Spójrz na samouczek tutaj
Oto kod do szyfrowania opartego na haśle, jest to hasło wprowadzane przez System. Możesz to zmienić, aby użyć zapisanego hasła, jeśli chcesz.
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);
źródło
SecretKeyFactory
uzyskać bardziej aktualne szyfrowanie.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); } }
źródło
keyValue
tablicy bajtów? Widzę, że jest używany do tworzenia klucza, dlaczego? Czy można coś zrobić, używającSecretKey
zamiast tego? Jeśli tak to jak?To zadziała.
public class CryptoUtils { private final String TRANSFORMATION = "AES"; private final String encodekey = "1234543444555666"; public String encrypt(String inputFile) throws CryptoException { return doEncrypt(encodekey, inputFile); } public String decrypt(String input) throws CryptoException { // return doCrypto(Cipher.DECRYPT_MODE, key, inputFile); return doDecrypt(encodekey,input); } private String doEncrypt(String encodekey, String inputStr) throws CryptoException { try { Cipher cipher = Cipher.getInstance(TRANSFORMATION); byte[] key = encodekey.getBytes("UTF-8"); MessageDigest sha = MessageDigest.getInstance("SHA-1"); key = sha.digest(key); key = Arrays.copyOf(key, 16); // use only first 128 bit SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES"); cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec); byte[] inputBytes = inputStr.getBytes(); byte[] outputBytes = cipher.doFinal(inputBytes); return Base64Utils.encodeToString(outputBytes); } catch (NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeyException | BadPaddingException | IllegalBlockSizeException | IOException ex) { throw new CryptoException("Error encrypting/decrypting file", ex); } } public String doDecrypt(String encodekey,String encrptedStr) { try { Cipher dcipher = Cipher.getInstance(TRANSFORMATION); dcipher = Cipher.getInstance("AES"); byte[] key = encodekey.getBytes("UTF-8"); MessageDigest sha = MessageDigest.getInstance("SHA-1"); key = sha.digest(key); key = Arrays.copyOf(key, 16); // use only first 128 bit SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES"); dcipher.init(Cipher.DECRYPT_MODE, secretKeySpec); // decode with base64 to get bytes byte[] dec = Base64Utils.decode(encrptedStr.getBytes()); byte[] utf8 = dcipher.doFinal(dec); // create new string based on the specified charset return new String(utf8, "UTF8"); } catch (Exception e) { e.printStackTrace(); } return null; } }
źródło
MD5, AES, bez wypełnienia
import static javax.crypto.Cipher.DECRYPT_MODE; import static javax.crypto.Cipher.ENCRYPT_MODE; import static org.apache.commons.io.Charsets.UTF_8; import java.security.InvalidKeyException; import java.security.Key; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Base64; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import javax.crypto.spec.SecretKeySpec; public class PasswordUtils { private PasswordUtils() {} public static String encrypt(String text, String pass) { try { MessageDigest messageDigest = MessageDigest.getInstance("MD5"); Key key = new SecretKeySpec(messageDigest.digest(pass.getBytes(UTF_8)), "AES"); Cipher cipher = Cipher.getInstance("AES"); cipher.init(ENCRYPT_MODE, key); byte[] encrypted = cipher.doFinal(text.getBytes(UTF_8)); byte[] encoded = Base64.getEncoder().encode(encrypted); return new String(encoded, UTF_8); } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) { throw new RuntimeException("Cannot encrypt", e); } } public static String decrypt(String text, String pass) { try { MessageDigest messageDigest = MessageDigest.getInstance("MD5"); Key key = new SecretKeySpec(messageDigest.digest(pass.getBytes(UTF_8)), "AES"); Cipher cipher = Cipher.getInstance("AES"); cipher.init(DECRYPT_MODE, key); byte[] decoded = Base64.getDecoder().decode(text.getBytes(UTF_8)); byte[] decrypted = cipher.doFinal(decoded); return new String(decrypted, UTF_8); } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) { throw new RuntimeException("Cannot decrypt", e); } } }
źródło
byte[] seed = (SALT2 + username + password).getBytes(); SecureRandom random = new SecureRandom(seed); KeyGenerator generator; generator = KeyGenerator.getInstance("AES"); generator.init(random); generator.init(256); Key keyObj = generator.generateKey();
źródło