Ale*_*yan 23 java android cryptography elliptic-curve public-key-encryption
我想在我的Android应用程序中使用Curve25519在本地加密/解密AES加密密钥.我不需要任何密钥交换,密钥协议或签名.为什么我需要使用那条特定的曲线?因为我需要能够自己提供私钥并能够计算它匹配的公钥.所以就我而言,只有Curve25519这样做.如果我错了,请纠正我.
所有Curve25519实现都只进行密钥生成,密钥交换和签名/验证.
在获得Curve25519私钥/公钥后,是否可以进行数据加密/解密,或者您可以建议任何符合我标准的替代曲线?
编辑
那我为什么需要这个呢?我会更仔细地解释一下.我的应用正在进行本地文件加密,尤其是照片.我的目标是让用户无需输入密码即可拍照,然后输入密码进行查看.为此,我需要能够从密码创建公钥/私钥对,并且只要提供相同的密码,就能够在运行时重新创建相同的密钥对.所以在第一次运行时,我从密码生成ECC密钥对,并在设备上存储公钥.当用户想要使用新的照片应用程序使用随机256位AES密钥加密照片,然后使用存储的公钥加密该密钥.当用户想要查看照片时,他/她提供正确的密码,我获得相同的ECC密钥对并使用我的私钥解密AES密钥,然后我可以使用AES 256解密照片.
所以,就我而言,Curve25519可以给我这种能力,或者还有其他选择.欢迎使用Java中的代码示例!
在 Android 设备上加密文件的关键是永远不要存储密钥。为此,您添加了加密图片不需要密码的约束。最后,由于非对称加密速度很慢,因此您需要 AES 来完成繁重的工作。
这适用于 RSA 或任何其他非对称算法。
初始运行
加密
解密
(我们实际上有 4 个密钥。我们需要密钥对来允许我们在没有密码的情况下进行加密。我们需要第一个 AES 密钥来安全地存储私钥。我们需要第二个和不断变化的 AES 密钥来加密文件。)
我认为这应该是安全的,除了键盘记录等攻击之外。Java 代码应该非常简单。希望这一点是清楚的。
=================================================== ===================
使用 AES 和 RSA 的完整示例。对于 Curve,仅切换 RSA 代码,但不支持开箱即用,因此您需要一个外部库。此外,为了节省时间和简洁性,代码的安全性低于应有的水平。例如,我使用 ECB 而不是 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;
}
}
Run Code Online (Sandbox Code Playgroud)
}
| 归档时间: |
|
| 查看次数: |
3381 次 |
| 最近记录: |