vernam numeros encriptar desencriptar descifrar como codigo cifrar cifrado java android cryptography public-key-encryption elliptic-curve

numeros - Usando ECC Curve25519 para cifrar/descifrar datos en Java



encriptar y desencriptar rsa en java (1)

La clave para encriptar archivos en un dispositivo Android es nunca almacenar la clave. A esto, ha agregado la restricción de que el cifrado de imágenes no debería requerir una contraseña. Finalmente, debido a que el cifrado asimétrico es lento, necesitaría AES para hacer el trabajo pesado.

Esto funciona con RSA o cualquier otro algoritmo asimétrico.

Ejecución inicial

  1. En la primera ejecución, genere un par de llaves y solicite al usuario que ingrese una contraseña.
  2. Almacene la clave pública en claro. Encripte la clave privada usando una clave AES generada a partir de la contraseña.

Cifrado

  1. Genere una clave AES diferente para cada imagen y encripte la imagen con ella. Encripte la clave AES con la clave pública y guárdela junto a la imagen.

Descifrado

  1. Haga que el usuario ingrese la contraseña. Genera la primera clave AES de ella. Úselo para descifrar la clave privada. Descifre la tecla AES para esta imagen usando la clave privada. Use la tecla AES para descifrar el archivo y mostrarlo.

(En realidad tenemos 4 claves. Necesitamos el par de claves que nos permita cifrar sin una contraseña. Necesitamos la primera clave AES para almacenar la clave privada de forma segura. Necesitamos la segunda y cambiar la clave AES para cifrar el archivo).

Creo que esto debería ser seguro, a excepción de ataques como el registro de claves. El código de Java debería ser muy sencillo. Espero que esto esté claro.

=============================================== ====================

Ejemplo completo usando AES y RSA. Para Curve, cambie solo el código RSA, aunque no se admite de fábrica, por lo que necesitará una biblioteca externa. Además, en aras del tiempo y la brevedad, el código es menos seguro de lo que debería ser. Por ejemplo, utilicé ECB y no 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; } }

}

Intento utilizar Curve25519 en mi aplicación Android para encriptar / descifrar localmente la clave de encriptación AES. No necesito ningún intercambio de claves, acuerdo clave o firma. ¿Por qué necesito usar esa curva particular? Porque necesito poder proporcionar la clave privada y ser capaz de calcular su clave pública coincidente. Así que hasta donde tengo, solo Curve25519 hace esto. Por favor, corríjame si estoy equivocado.

Todas las implementaciones de Curve25519 solo hacen generación de claves, intercambio de claves y firma / verificación.

¿Es posible hacer cifrado / descifrado de datos después de obtener las claves privadas / públicas Curve25519 o tal vez puede sugerirme cualquier curva alternativa que coincida con mis criterios?

Editar

Entonces, ¿por qué necesito esto? Explicaré más atentamente. Mi aplicación está haciendo encriptación local de archivos, particularmente fotos. Mi objetivo es que el usuario pueda tomar una foto sin ingresar una contraseña y luego ingresar la contraseña para verla. Para esto necesito poder crear un par de llaves público / privado a partir de la contraseña y poder recrear en el momento el mismo par de llaves siempre que se proporcione la misma contraseña. Así que en la primera ejecución genero el par de llaves ECC desde la contraseña y almaceno la clave pública en el dispositivo. Cuando el usuario quiera tomar una nueva aplicación de fotos, cifra la foto con una clave AES aleatoria de 256 bits y luego encripta esa clave con la clave pública almacenada. Cuando el usuario quiere ver una foto, proporciona la contraseña correcta, obtengo el mismo par de claves ECC y descifro la clave AES con mi clave privada y luego puedo descifrar la fotografía usando AES 256.

Entonces, en cuanto obtengo Curve25519 puedo darme esta habilidad o hay otras alternativas. ¡Los ejemplos de código en Java son bienvenidos!