Genere y almacene de forma segura claves públicas / privadas en Android

6

Estoy creando una aplicación web que distribuye datos cifrados con las claves públicas de sus clientes. En este momento esto está funcionando para dispositivos dedicados que yo mismo distribuyo. Antes de que se envíen, coloco el par de llaves pública / privada en el firmware del dispositivo.

Sin embargo, como esto es 2017, también quise hacer una aplicación de Android para hacer que cualquier dispositivo Android actúe como uno de los dispositivos que vendo, ya que es más fácil para los clientes. El único cuello de botella que estoy experimentando es la distribución de las claves.

Al iniciar la aplicación, puedo generar un par de llaves públicas / privadas en el dispositivo Android, y almacenarlas de manera segura en el almacenamiento interno, pero necesito encontrar una manera de enviar la clave pública generada del dispositivo Android a mi servidor, por lo que mi servidor puede cifrar los datos con él.

La razón por la que no puedo simplemente enviar la clave pública como una solicitud HTTP a mi servidor es que no quiero que alguien con una computadora pueda generar un par de claves público / privado y enviarla a mi servidor para que también sea capaz de recibir los datos como. Es muy fácil descompilar las aplicaciones de Android o utilizar wireshark para averiguar la URL utilizada para registrar nuevas claves.

Si tuviera que usar esta forma, ¿cómo verificaría en mis servidores que la solicitud se origina en un dispositivo Android legítimo?

    
pregunta CryptoGuy51 02.02.2017 - 21:18
fuente

2 respuestas

4

Exactamente como estados Limit, y gracias a esta respuesta, la forma correcta sería:

  1. Genere un par de llaves para cifrar en su servidor dev

    openssl genrsa -des3 -out private.pem 2048

    openssl rsa -in private.pem -outform PEM -pubout -out public.pem

  2. Almacene la clave pública en el código de la aplicación, no importa dónde. Esto se utilizará en la función en el paso 5. Tal vez ofusque el código para evitar la alteración del mecanismo de cifrado. (el cifrado solo evitará la manipulación en tránsito con algo como burp proxy. smali skills any?)

  3. Genera un par de llaves en el dispositivo (mencionaste que tenías esto abajo, pero en caso de que alguien se pregunte)

    public static KeyPair getKeyPair() {
    KeyPair kp = null;
    try {
        KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
        kpg.initialize(2048);
        kp = kpg.generateKeyPair();
    } catch (Exception e) {
        e.printStackTrace();
    }
    
    return kp; 
    }
    
  4. Aísle las claves públicas y guárdelas donde desee. Almacene la clave privada en la tienda segura.

    KeyPair clientKeys = getKeyPair();
    publicKey = clientKeys.getPublic();
    
  5. Cifre la clave pública del cliente con la clave pública dev integrada para que pueda enviarla a casa.

    public static String encryptToRSAString(String clearText, String publicKey) {
        String encryptedBase64 = "";
        try {
            KeyFactory keyFac = KeyFactory.getInstance("RSA");
            KeySpec keySpec = new X509EncodedKeySpec(Base64.decode(publicKey.trim().getBytes(), Base64.DEFAULT));
            Key key = keyFac.generatePublic(keySpec);
            // get an RSA cipher object and print the provider
            final Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING");
            // encrypt the plain text using the public key
            cipher.init(Cipher.ENCRYPT_MODE, key);
            byte[] encryptedBytes = cipher.doFinal(clearText.getBytes("UTF-8"));
            encryptedBase64 = new String(Base64.encode(encryptedBytes, Base64.DEFAULT));
        } catch (Exception e) {
            e.printStackTrace();
        }
            return encryptedBase64.replaceAll("(\r|\n)", "");
    }
    
respondido por el J.A.K. 03.02.2017 - 01:27
fuente
0

¿Puede ser que desee recibir claves solo de usuarios registrados? La autenticación requerirá al final algún secreto compartido entre su servidor y el usuario registrado. Con este secreto, puede intentar intercambiar claves utilizando un buen protocolo de intercambio de claves, por ejemplo, EKE o un protocolo similar. enlace

Pero, si tiene el certificado SSL del servidor (y supongo que lo tiene), cuando establezca la conexión con un usuario registrado, puede enviarle su par público en este canal, porque ya está encriptado. También se considera una mejor práctica para no desarrollar / implementar protocolos de seguridad propios o incluso conocidos, por lo que esta opción es probablemente mejor.

Por el certificado SSL del servidor, me refiero a un certificado firmado por una autoridad competente de CA

    
respondido por el stackoverflower 03.02.2017 - 02:04
fuente

Lea otras preguntas en las etiquetas