自分のキーでAESを使用して文字列を暗号化します。しかし、キーのビット長に問題があります。コードを確認して、修正/変更する必要があるものを確認してください。
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));
}
今、私は例外を受け取ります "Invalid AES key length:86 bytes"。キーをパディングする必要がありますか?どうすればいいですか?
また、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ビットが必要な場合は、「Java暗号化拡張機能(JCE)無制限強度の管轄ポリシーファイル」 Oracleダウンロードリンク をダウンロードし、SHA-256をハッシュとして使用してArrays.copyOf行。 「ECB」はデフォルトの暗号モードで、「PKCS5Padding」はデフォルトのパディングです。次の形式を使用して、Cipher.getInstance文字列を使用して、異なる暗号モードとパディングモードを使用できます。「Cipher/Mode/Padding」
CTSおよびPKCS5Paddingを使用するAESの場合、文字列は「AES/CTS/PKCS5Padding」です。
KeyGeneratorを使用してキーを生成する必要があります。
AESキーの長さは、使用する暗号に応じて128、192、および256ビットです。
チュートリアルをご覧ください here
パスワードベースの暗号化のコードを次に示します。これには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);
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);
}
}
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);
}
}
}
これは動作します。
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;
}
}
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();