Chìa khóa để mã hóa tệp trên thiết bị Android là không bao giờ lưu khóa. Với điều này, bạn đã thêm ràng buộc mã hóa hình ảnh không nên yêu cầu mật khẩu. Cuối cùng, vì mã hóa bất đối xứng chậm, bạn sẽ cần AES để thực hiện việc nâng hạng nặng.
Điều này làm việc với RSA hoặc bất kỳ thuật toán bất đối xứng nào khác.
Initial Run
- On chạy đầu tiên, tạo ra một cặp khóa và yêu cầu người dùng nhập mật khẩu.
- Lưu trữ khóa công khai rõ ràng. Mã hóa khóa riêng bằng khóa AES được tạo từ mật khẩu.
Encryption
- Tạo một khoá AES khác nhau cho mỗi bức ảnh và mã hóa hình ảnh với nó. Mã hóa khóa AES bằng khóa công khai và lưu trữ cùng với hình ảnh.
Decryption
- Có người dùng nhập mật khẩu. Tạo khóa AES đầu tiên từ đó. Sử dụng nó để giải mã khóa riêng. Giải mã khóa AES cho hình ảnh này bằng khóa riêng. Sử dụng phím AES để giải mã tập tin và hiển thị nó.
(Chúng tôi thực sự có 4 khóa.Chúng tôi cần cặp khóa để cho phép chúng tôi mã hóa mà không cần mật khẩu. Chúng tôi cần khóa AES đầu tiên để lưu khóa riêng tư một cách an toàn. Chúng tôi cần khóa AES thứ hai và thay đổi để mã hóa tệp.)
Tôi nghĩ điều này sẽ an toàn, ngoại trừ các cuộc tấn công như ghi nhật ký khóa. Mã Java nên rất đơn giản. Hy vọng điều này là rõ ràng.
============================================== ========================
Ví dụ hoàn chỉnh Sử dụng AES và RSA. Đối với Curve, chỉ chuyển mã RSA, mặc dù nó không được hỗ trợ ra khỏi hộp, vì vậy bạn sẽ cần một thư viện bên ngoài. Ngoài ra, vì lợi ích của thời gian và ngắn gọn, mã này kém an toàn hơn mức cần thiết. Ví dụ, tôi đã sử dụng ECB chứ không phải CBC.
package il.co.falk;
import javax.crypto.*;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.*;
import java.security.spec.KeySpec;
import java.security.spec.PKCS8EncodedKeySpec;
public class SecureFile {
private PublicKey publicKey;
private byte[] privateKeyArray;
private byte[] salt = {1,2,3,4,5,6,7,8};
public static void main(String[] args) {
String password = "PASSWORD";
SecureFile secureFile = new SecureFile(password);
secureFile.test();
}
public void test() {
String password = "PASSWORD";
String imageFile = "348756348975634897562398479623896";
ImageAndKey imageAndKey = encryptImage(imageFile.getBytes());
byte[] decryptedImage = decryptImage(imageAndKey, password);
System.out.println(new String(imageFile));
System.out.println(new String(decryptedImage));
}
public SecureFile(String password) {
try {
generateRSAKeys(password);
} catch (Exception e) {
e.printStackTrace();
}
}
public ImageAndKey encryptImage(byte[] imageBytes) {
try {
byte[] secretKeyBytes = generateAESKey();
byte[] encryptedFile = aesEncrypt(imageBytes, secretKeyBytes);
byte[] encryptedKey = rsaEncrypt(secretKeyBytes);
return new ImageAndKey(encryptedFile, encryptedKey);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public byte[] decryptImage(ImageAndKey imageAndKey, String password) {
try {
byte[] secretKeyBytes = generateAESKey(password);
byte[] decryptedPrivateKey = aesDecrypt(privateKeyArray, secretKeyBytes);
byte[] decryptedKey = rsaDecrypt(imageAndKey.aesKey, decryptedPrivateKey);
SecretKey secretKey = new SecretKeySpec(decryptedKey, "AES");
secretKeyBytes = secretKey.getEncoded();
byte[] decryptedBytes = aesDecrypt(imageAndKey.imageBytes, secretKeyBytes);
return decryptedBytes;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
// RSA
private void generateRSAKeys(String password) throws Exception {
final KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize(512); // TODO: make this 2048 at least
final KeyPair keyPair = keyGen.generateKeyPair();
publicKey = keyPair.getPublic();
PrivateKey privateKey = keyPair.getPrivate();
byte[] secretKeyBytes = generateAESKey(password);
byte[] privateKeyBytes = privateKey.getEncoded();
privateKeyArray = aesEncrypt(privateKeyBytes, secretKeyBytes);
}
public byte[] rsaEncrypt(byte[] plainText) throws Exception {
final Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] cipherText = cipher.doFinal(plainText);
return cipherText;
}
public byte[] rsaDecrypt(byte[] cipherText, byte[] decryptedPrivateKeyArray) throws Exception {
PrivateKey privateKey = KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decryptedPrivateKeyArray));
final Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] plainText = cipher.doFinal(cipherText);
return plainText;
}
// AES
private byte[] aesEncrypt(byte[] plainText, byte[] secretKeyBytes) throws Exception {
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, getSecretKey(secretKeyBytes));
byte[] cipherText = cipher.doFinal(plainText);
return cipherText;
}
public byte[] aesDecrypt(byte[] cipherText, byte[] secretKeyBytes) throws Exception {
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, getSecretKey(secretKeyBytes));
byte[] plainText = cipher.doFinal(cipherText);
return plainText;
}
private byte[] generateAESKey() throws Exception {
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(256);
SecretKey secretKey = keyGen.generateKey();
return secretKey.getEncoded();
}
private byte[] generateAESKey(String password) throws Exception {
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 65536, 256);
SecretKey tmp = factory.generateSecret(spec);
SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");
return secret.getEncoded();
}
private SecretKey getSecretKey(byte[] secretKeyBytes) throws Exception {
SecretKey secretKey = new SecretKeySpec(secretKeyBytes, "AES");
return secretKey;
}
// Classes
class ImageAndKey {
public byte[] imageBytes;
public byte[] aesKey;
public ImageAndKey(byte[] imageBytes, byte[] aesKey) {
this.imageBytes = imageBytes;
this.aesKey = aesKey;
}
}
}
Bạn có thể sử dụng [này] (http://stackoverflow.com/a/30014831/1816580) để nhanh chóng ECIES. –
Thực hiện trao đổi khóa với khóa công khai của người nhận và sử dụng khóa chia sẻ để mã hóa bằng mã hóa đối xứng như XSalsa20Poly1305 hoặc AES-GCM. – CodesInChaos
Có lẽ bạn không hiểu điều đó. Tôi không có bất kỳ bên nhận nào, tất cả mã hóa và giải mã đều là cục bộ. –