Шифрование / расшифровка изображений с использованием симметричных блочных шифров AES256
Есть ли какой-нибудь хороший пример того, как зашифровать и расшифровать изображения и другие файлы с помощью AES на Android?
Переведено автоматически
Ответ 1
Предупреждение: Этот ответ содержит код, который вы не должны использовать, поскольку он небезопасен (используя SHA1PRNG для получения ключа и используя AES в режиме ECB)
Вместо этого (по состоянию на 2016 год) используйте PBKDF2WithHmacSHA1 для получения ключа и AES в режиме CBC или GCM (GCM обеспечивает конфиденциальность и целостность)
Вы могли бы использовать подобные функции:
private static byte[] encrypt(byte[] raw, byte[] clear) throws Exception {
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted = cipher.doFinal(clear);
return encrypted;
}
private static byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception {
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
byte[] decrypted = cipher.doFinal(encrypted);
return decrypted;
}
И вызываем их следующим образом:
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.PNG, 100, baos); // bm is the bitmap object
byte[] b = baos.toByteArray();
byte[] keyStart = "this is a key".getBytes();
KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
sr.setSeed(keyStart);
kgen.init(128, sr); // 192 and 256 bits may not be available
SecretKey skey = kgen.generateKey();
byte[] key = skey.getEncoded();
// encrypt
byte[] encryptedData = encrypt(key,b);
// decrypt
byte[] decryptedData = decrypt(key,encryptedData);
Это должно сработать, я использую аналогичный код в проекте прямо сейчас.
Ответ 2
Как упоминал Начо.Используется деривация L PBKDF2WithHmacSHA1, поскольку она более защищена.
import android.util.Base64;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
public class AESEncyption {
private static final int pswdIterations = 10;
private static final int keySize = 128;
private static final String cypherInstance = "AES/CBC/PKCS5Padding";
private static final String secretKeyInstance = "PBKDF2WithHmacSHA1";
private static final String plainText = "sampleText";
private static final String AESSalt = "exampleSalt";
private static final String initializationVector = "8119745113154120";
public static String encrypt(String textToEncrypt) throws Exception {
SecretKeySpec skeySpec = new SecretKeySpec(getRaw(plainText, AESSalt), "AES");
Cipher cipher = Cipher.getInstance(cypherInstance);
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, new IvParameterSpec(initializationVector.getBytes()));
byte[] encrypted = cipher.doFinal(textToEncrypt.getBytes());
return Base64.encodeToString(encrypted, Base64.DEFAULT);
}
public static String decrypt(String textToDecrypt) throws Exception {
byte[] encryted_bytes = Base64.decode(textToDecrypt, Base64.DEFAULT);
SecretKeySpec skeySpec = new SecretKeySpec(getRaw(plainText, AESSalt), "AES");
Cipher cipher = Cipher.getInstance(cypherInstance);
cipher.init(Cipher.DECRYPT_MODE, skeySpec, new IvParameterSpec(initializationVector.getBytes()));
byte[] decrypted = cipher.doFinal(encryted_bytes);
return new String(decrypted, "UTF-8");
}
private static byte[] getRaw(String plainText, String salt) {
try {
SecretKeyFactory factory = SecretKeyFactory.getInstance(secretKeyInstance);
KeySpec spec = new PBEKeySpec(plainText.toCharArray(), salt.getBytes(), pswdIterations, keySize);
return factory.generateSecret(spec).getEncoded();
} catch (InvalidKeySpecException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return new byte[0];
}
}
Ответ 3
import java.security.AlgorithmParameters;
import java.security.SecureRandom;
import java.security.spec.KeySpec;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
class SecurityUtils {
private static final byte[] salt = { (byte) 0xA4, (byte) 0x0B, (byte) 0xC8,
(byte) 0x34, (byte) 0xD6, (byte) 0x95, (byte) 0xF3, (byte) 0x13 };
private static int BLOCKS = 128;
public static byte[] encryptAES(String seed, String cleartext)
throws Exception {
byte[] rawKey = getRawKey(seed.getBytes("UTF8"));
SecretKeySpec skeySpec = new SecretKeySpec(rawKey, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
return cipher.doFinal(cleartext.getBytes("UTF8"));
}
public static byte[] decryptAES(String seed, byte[] data) throws Exception {
byte[] rawKey = getRawKey(seed.getBytes("UTF8"));
SecretKeySpec skeySpec = new SecretKeySpec(rawKey, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
return cipher.doFinal(data);
}
private static byte[] getRawKey(byte[] seed) throws Exception {
KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
sr.setSeed(seed);
kgen.init(BLOCKS, sr); // 192 and 256 bits may not be available
SecretKey skey = kgen.generateKey();
byte[] raw = skey.getEncoded();
return raw;
}
private static byte[] pad(byte[] seed) {
byte[] nseed = new byte[BLOCKS / 8];
for (int i = 0; i < BLOCKS / 8; i++)
nseed[i] = 0;
for (int i = 0; i < seed.length; i++)
nseed[i] = seed[i];
return nseed;
}
public static byte[] encryptPBE(String password, String cleartext)
throws Exception {
SecretKeyFactory factory = SecretKeyFactory
.getInstance("PBKDF2WithHmacSHA1");
KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 1024, 256);
SecretKey tmp = factory.generateSecret(spec);
SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secret);
AlgorithmParameters params = cipher.getParameters();
byte[] iv = params.getParameterSpec(IvParameterSpec.class).getIV();
return cipher.doFinal(cleartext.getBytes("UTF-8"));
}
public static String decryptPBE(SecretKey secret, String ciphertext,
byte[] iv) throws Exception {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv));
return new String(cipher.doFinal(ciphertext.getBytes()), "UTF-8");
}
}
Ответ 4
Для шифрования / дешифрования AES / CBC / PKCS7 просто скопируйте и вставьте следующий код и замените SecretKey
и IV
своим собственным.
import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import android.util.Base64;
public class CryptoHandler {
String SecretKey = "xxxxxxxxxxxxxxxxxxxx";
String IV = "xxxxxxxxxxxxxxxx";
private static CryptoHandler instance = null;
public static CryptoHandler getInstance() {
if (instance == null) {
instance = new CryptoHandler();
}
return instance;
}
public String encrypt(String message) throws NoSuchAlgorithmException,
NoSuchPaddingException, IllegalBlockSizeException,
BadPaddingException, InvalidKeyException,
UnsupportedEncodingException, InvalidAlgorithmParameterException {
byte[] srcBuff = message.getBytes("UTF8");
//here using substring because AES takes only 16 or 24 or 32 byte of key
SecretKeySpec skeySpec = new
SecretKeySpec(SecretKey.substring(0,32).getBytes(), "AES");
IvParameterSpec ivSpec = new
IvParameterSpec(IV.substring(0,16).getBytes());
Cipher ecipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
ecipher.init(Cipher.ENCRYPT_MODE, skeySpec, ivSpec);
byte[] dstBuff = ecipher.doFinal(srcBuff);
String base64 = Base64.encodeToString(dstBuff, Base64.DEFAULT);
return base64;
}
public String decrypt(String encrypted) throws NoSuchAlgorithmException,
NoSuchPaddingException, InvalidKeyException,
InvalidAlgorithmParameterException, IllegalBlockSizeException,
BadPaddingException, UnsupportedEncodingException {
SecretKeySpec skeySpec = new
SecretKeySpec(SecretKey.substring(0,32).getBytes(), "AES");
IvParameterSpec ivSpec = new
IvParameterSpec(IV.substring(0,16).getBytes());
Cipher ecipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
ecipher.init(Cipher.DECRYPT_MODE, skeySpec, ivSpec);
byte[] raw = Base64.decode(encrypted, Base64.DEFAULT);
byte[] originalBytes = ecipher.doFinal(raw);
String original = new String(originalBytes, "UTF8");
return original;
}
}