Come implementare il sistema di crittografia / decrittografia tramite IV tra app mobile e servizio web

3

Nella mia app invieremo dati crittografati al servizio web. Sto usando il seguente codice per crittografare e decrittografare i dati -

public class DecEn {
    private static final String password = "test";
    private static String salt;
    private static int pswdIterations = 65536;
    private static int keySize = 256;
    private byte[] ivBytes;

    public String encrypt(String plainText) throws Exception {

        //get salt
        salt = generateSalt();
        byte[] saltBytes = salt.getBytes("UTF-8");

        // Derive the key
        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
        PBEKeySpec spec = new PBEKeySpec(
                password.toCharArray(),
                saltBytes,
                pswdIterations,
                keySize
        );

        SecretKey secretKey = factory.generateSecret(spec);
        SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");

        //encrypt the message
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, secret);
        AlgorithmParameters params = cipher.getParameters();
        ivBytes = params.getParameterSpec(IvParameterSpec.class).getIV();
        byte[] encryptedTextBytes = cipher.doFinal(plainText.getBytes("UTF-8"));
        return new Base64().encodeAsString(encryptedTextBytes);
//      return Base64.encodeBase64String(encryptedTextBytes);
//      return Hex.encodeHexString(encryptedTextBytes);
    }

    @SuppressWarnings("static-access")
    public String decrypt(String encryptedText) throws Exception {

        byte[] saltBytes = salt.getBytes("UTF-8");
        byte[] encryptedTextBytes = new Base64().decodeBase64(encryptedText);
//      byte[] encryptedTextBytes = Base64.decodeBase64(encryptedText);
//      byte[] encryptedTextBytes = Hex.decodeHex(encryptedText.toCharArray());

        // Derive the key
        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
        PBEKeySpec spec = new PBEKeySpec(
                password.toCharArray(),
                saltBytes,
                pswdIterations,
                keySize
        );

        SecretKey secretKey = factory.generateSecret(spec);
        SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");

        // Decrypt the message
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(ivBytes));


        byte[] decryptedTextBytes = null;
        try {
            decryptedTextBytes = cipher.doFinal(encryptedTextBytes);
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        }

        return new String(decryptedTextBytes);
    }

    public String generateSalt() {
        SecureRandom random = new SecureRandom();
        byte bytes[] = new byte[20];
        random.nextBytes(bytes);
        String s = new String(bytes);
        return s;
    }
}

Il codice sopra memorizza IV e sale dopo che sono stati generati e li riutilizza per decodificare i dati. Questo non sarà vero in caso di collaborazione tra app e servizio web.

Quello di cui sono veramente confuso è che IV e sale vengono generati di nuovo ogni volta che i dati vengono crittografati, che è la procedura consigliata per quanto ho potuto capire dal mio googlare Google, ma dato che questi dati vengono inviati a un servizio web, la IV e il sale deve essere disponibile lì, il che significa che dovrò inviarlo insieme ai miei dati. Questo non sconfigge lo scopo della crittografia? Come rende le informazioni disponibili all'attaccante.

O l'altro modo sembra essere l'uso di statica IV e sale che rende di nuovo la crittografia suscettibile agli attacchi. Quella crittografia viene utilizzata con successo in tutto il mondo indica che la mia comprensione del soggetto è carente da qualche parte.

Per favore aiutami chiarendo i miei dubbi.

    
posta Opax Web 07.07.2015 - 06:34
fonte

1 risposta

3

I vettori di inizializzazione non sono intesi per essere privati. L'obiettivo di una flebo non è quello di rafforzare la chiave, ma assicurarsi che nessun testo identico (o simile) chiaro risulterà nello stesso (o simile) testo cifrato.

Funziona così: AES (insieme alla maggior parte - ma non a tutti - l'algoritmo di crittografia moderno) è un codice a blocchi . Funziona solo su una quantità fissa di dati (nel caso AES, 128 bit ). Quindi, per ottenere identici blocchi di dati all'interno dei dati di origine (ad esempio utilizzando la stessa chiave), è normale specificare una modalità di operazioni che introducono qualche forma di modifica tra due blocchi di dati.

Nel tuo caso, hai selezionato CBC che fondamentalmente XOR è il testo chiaro del bloccare N con il testo cifrato del blocco N-1 prima di crittarlo.

Funziona bene tranne per il primo blocco: non esiste un blocco precedente con cui mischiarlo e quindi, se non si fa qualcosa al riguardo, se il testo in chiaro inizia con gli stessi 128 bit sarà simile se lo stesso la chiave è utilizzata per la crittografia. Questo è un problema reale perché è abbastanza frequente che due messaggi abbiano gli stessi primi 128 bit. Inoltre, a seconda dell'applicazione, è possibile dedurre il significato del messaggio senza nemmeno decodificarlo (si pensi alle risposte "sì" e "no", per le istanze).

Questo è ciò che l'IV è per: fa in modo che, finché non si riutilizza l'IV, non ci si debba preoccupare di due messaggi che restituiscono un testo chiaro identico.

Un altro punto che vale la pena di fare è che si potrebbe fare lo stesso cambiando la chiave. Ci sono due problemi qui:

  • Le chiavi sono spesso raccolte al volo e quindi solo statisticamente uniche (il che non è un problema).
  • Le chiavi sono costose da cambiare: nella migliore delle ipotesi, è necessario ri-negoziare una chiave (ad esempio, con DH ). Vale la pena, è necessario ricreare una nuova chiave e scambiarla attraverso un canale sicuro.
risposta data 07.07.2015 - 10:02
fonte

Leggi altre domande sui tag