Crittografia AES devo usare una modalità?

3

Attualmente sto lavorando a un programma di crittografia dei file utilizzando Java Cryptography Architecture.

Il mio piano è di avere un numero di file crittografati in cui ogni file ha una chiave AES diversa. Per tenere traccia dei file crittografati, includo anche un file di metadati che memorizza una voce per ogni file crittografato con i seguenti valori: nome file di testo normale, nome file cipher e chiave AES.

Il file di metadati viene quindi crittografato utilizzando una chiave AES derivata dalla password dell'utente.

La mia domanda è: devo implementare una modalità? e pensi che mantenere tutte le password nei metadati crittografati sia una pratica accettabile?

Ecco il codice a cui mi riferivo:

public class PasswordBasedEncryption {

PBEKeySpec pbeKeySpec;
PBEParameterSpec pbeParamSpec;
SecretKeyFactory keyFac;

// Salt
byte[] salt = {
        (byte)0xc7, (byte)0x73, (byte)0x21, (byte)0x8c,
        (byte)0x7e, (byte)0xc8, (byte)0xee, (byte)0x99
};
// Iteration count
int count = 65536;
int keySize = 128;

Cipher pbeCipher;
SecretKey pbeKey;
FileInputStream fis;
FileOutputStream fos;

/**
 * constructor given a master password
 * Use password based derivation function II to make AES key.
 * used only for the metadata file encryption
 * @param password
 */
public PasswordBasedEncryption(char[] password){
    try{
        keyFac = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
        pbeKeySpec = new PBEKeySpec(password, salt, count, keySize);
        SecretKey tempKey = keyFac.generateSecret(pbeKeySpec);
        pbeKey = new SecretKeySpec(tempKey.getEncoded(), "AES");
        pbeCipher = Cipher.getInstance("AES");
    }
    catch (Exception e){e.printStackTrace();}
}
/**
 * constructor given a generated AES key
 * each file has its own AES key to avoid known text attacks
 * @param key
 */
public PasswordBasedEncryption(SecretKey key){
    try{
        pbeKey = key;
    }
    catch (Exception e){e.printStackTrace();}
}

public void encrypt(String filePath, String cipherName){
    try{
        File clearFile = new File(filePath);
        fis = new FileInputStream(clearFile);

        pbeCipher = Cipher.getInstance("AES");
        pbeCipher.init(Cipher.ENCRYPT_MODE, pbeKey);

        CipherInputStream cis = new CipherInputStream(fis, pbeCipher);          
        File cipherFile = new File(Path.TEMP + cipherName);
        fos = new FileOutputStream(cipherFile);
        int read;
        while((read = cis.read())!=-1)
        {
            fos.write((char)read);
            fos.flush();
        } 
        cis.close();
        fos.close();
        fis.close();
    }
    catch(Exception e ){e.printStackTrace();}
}

public void decrypt(String cipherName, String filePath){
    try{

        fis = new FileInputStream(Path.TEMP + cipherName);          
        File clearFile = new File(filePath);
        fos = new FileOutputStream(clearFile);

        pbeCipher = Cipher.getInstance("AES");
        pbeCipher.init(Cipher.DECRYPT_MODE, pbeKey);
        CipherOutputStream cos = new CipherOutputStream(fos, pbeCipher);            
        int read;
        while((read = fis.read())!=-1)
        {
            cos.write(read);
            cos.flush();
        } 
        cos.close();
        fis.close();
        fos.close();
    }
    catch(Exception e ){e.printStackTrace();}
}


/**
 * Generate secret password used each time a new file needs encrypting
 * @return
 */
public static SecretKey genPass(){
    KeyGenerator keyGen;
    try {
        keyGen = KeyGenerator.getInstance("AES");
        keyGen.init(128);
        return keyGen.generateKey();
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
        return null;
    }
}
}
    
posta John 01.05.2014 - 15:52
fonte

3 risposte

9

AES è una cifra di blocco : prende come input una chiave e un blocco di esattamente 16 byte e genera un altro blocco di 16 byte. Questa è la portata di ciò che fa lo stesso AES.

Quindi, se vuoi criptare una sequenza di byte che non è un singolo blocco di 16 byte, devi usare un " modalità di funzionamento ". Ed è quello che stai già facendo nel tuo codice. Semplicemente non lo hai specificato nel tuo codice e hai permesso a Java di selezionarne uno per te. Sfortunatamente, il default potrebbe essere la BCE, che è atroce e debole; vedi questo documento che include quanto segue:

For example, the SunJCE provider uses ECB as the default mode, and PKCS5Padding as the default padding scheme for DES, DES-EDE and Blowfish ciphers.

(Nessuna parola su AES qui.)

Quindi, in ogni caso:

  • DEVI capire cosa stai facendo. La sicurezza non può essere testata, quindi l'unico modo per rendere sicuro il codice, specialmente con la crittografia, è avere una conoscenza approfondita e approfondita di ciò che accade internamente.

  • DEVI specificare esattamente cosa stai facendo. Non lasciare che la tua lingua selezioni valori predefiniti non definiti.

  • NON DEVI farlo da solo. Scrivere codice crittografico sicuro è uno dei compiti più difficili in fase di sviluppo, proprio perché non c'è modo di sapere se lo hai fatto correttamente (anche se l'esperienza dimostra che la risposta "no, è stata fatta male, è debole" si adatta quasi sempre).

risposta data 01.05.2014 - 16:14
fonte
3

Vedo alcuni problemi con il tuo codice in generale; non è affatto sicuro da Thrad ed elimina le eccezioni, il che non è adatto per qualsiasi applicazione rilevante per la sicurezza.

Suppongo che non sia per un qualche tipo di progetto commerciale, ma un progetto privato che fai (e solo per) apprendi qualcosa. Questo è assolutamente soddisfacente. Tuttavia, raccomanderei di non spedirlo a nessun cliente (compresi gli amici), finché non avrai più familiarità con la scrittura di un codice sicuro.

Devi specificare padding e modalità del tuo cifrario, come "AES/CBC/PKCS5Padding" . Non specificare una modalità e il padding può portare a problemi dipendenti dall'implementazione (come una JVM diversa che usa un'altra modalità e quindi non è in grado di decrittografare il file). Tieni inoltre presente che modalità come ECB non proteggono da alcuni attacchi, fai riferimento a questa immagine crittografata:

Copyrightdell'immagine:tuttigliusisonoconsentitiacondizionecheLarryEwing,ilproprietariodell'immagineoriginale,chirichiedadimenzionarlo,ilsuoindirizzoemail,[email protected],secondo link .

Per maggiori dettagli, vedi articolo di Wikipedia sulle modalità di cifratura a blocchi . Quindi, vorrei andare a CBC per la tua applicazione.

    
risposta data 01.05.2014 - 16:14
fonte
0

Bene, no, suppongo che tu non lo faccia, ma non ci sarebbe modo di crittografare qualsiasi cosa oltre il primo blocco con una determinata chiave. Questo è un po 'come chiedere se è possibile crittografare qualcosa senza input o senza un algoritmo di crittografia. La modalità è la modalità di derivazione della chiave per ogni blocco e il modo in cui si verifica effettivamente la crittografia. È una parte fondamentale della crittografia, non puoi "non avere una modalità" e avere un algoritmo funzionante.

Come per la memorizzazione delle chiavi del file AES nei metadati crittografati. Non ti darà molta più sicurezza nell'usare la stessa chiave per tutto, ma non è sbagliato. Il tuo file di metadati è fondamentalmente un portachiavi, quindi se un file viene perso e incrinato, il resto non sarà compromesso, anche se realisticamente, se hai fatto le cose correttamente, un file AES non dovrebbe essere crackato prima del riscalda la morte dell'universo, quindi non guadagnando molto ...

    
risposta data 01.05.2014 - 16:14
fonte

Leggi altre domande sui tag