Я хочу зашифровать строку с помощью 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));
}
Сейчас я получаю исключение « Недопустимая длина ключа AES: 86 байт ». Мне нужно набить ключ? как мне это сделать?
Также мне нужно что-то установить для ECB или CBC?
Благодарность
Ответы:
Редактировать:
Как написано в комментариях, старый код не является «лучшей практикой». Вы должны использовать алгоритм генерации ключей, такой как PBKDF2, с большим количеством итераций. Вы также должны использовать, по крайней мере, частично нестатическую (то есть для каждой исключительной "идентичности") соль. Если возможно, генерируется случайным образом и сохраняется вместе с зашифрованным текстом.
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);
===========
Старый ответ
Вы должны использовать SHA-1, чтобы сгенерировать хэш из вашего ключа и обрезать результат до 128 бит (16 байт).
Кроме того, не создавайте байтовые массивы из строк через getBytes (), он использует кодировку по умолчанию для платформы. Таким образом, пароль «blaöä» приводит к разному массиву байтов на разных платформах.
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");
Изменить: если вам нужен размер ключа 256 бит, вам необходимо загрузить ссылку для загрузки Oracle "Файлы политики юрисдикции неограниченной надежности Java Cryptography Extension (JCE)" , используйте SHA-256 в качестве хэша и удалите строку Arrays.copyOf . «ECB» - это режим шифрования по умолчанию, а «PKCS5Padding» - заполнение по умолчанию. Вы можете использовать различные режимы шифрования и режимы заполнения через строку Cipher.getInstance, используя следующий формат: «Cipher / Mode / Padding»
Для AES с использованием CTS и PKCS5Padding строка выглядит так: «AES / CTS / PKCS5Padding»
источник
Вы должны использовать 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);
источник
SecretKeyFactory
для более современного шифрования.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); } }
источник
keyValue
с байтовым массивом? Я вижу, что его используют для изготовления Ключа, почему? Можно ли что-то сделать, используя подобноеSecretKey
? Если да, то как?Это будет работать.
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; } }
источник
MD5, AES, без заполнения
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); } } }
источник
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();
источник