Как это возвращает "Данный последний блок не заполнен должным образом"? - PullRequest
0 голосов
/ 11 января 2020

Эта ошибка возникает иногда, в основном с более сложными парольными фразами, но даже тогда я печатаю необработанные шестнадцатеричные значения KEY, IV и CRYPTOGRAM на обеих сторонах шифрования и дешифрования, и они совпадают! Что я не вижу? Это способ записи / чтения из файла? (MA C отсутствует ik, это следующий шаг)

Шифрование:

private static String bytesToHex(byte[] hashInBytes) {

    StringBuilder sb = new StringBuilder();
    for (byte b : hashInBytes) {
        sb.append(String.format("%02x", b));
    }
    return sb.toString();

}

public static byte[] sha256(byte[] text) throws NoSuchAlgorithmException{

        MessageDigest md = MessageDigest.getInstance("SHA-256");
        byte[] digest = md.digest(text);
        return digest;    
}
public static String aesCbc(String message, byte[] Key, byte[] iv) throws UnsupportedEncodingException{
    try{
        IvParameterSpec Vetor = new IvParameterSpec(iv);
        SecretKeySpec Chave = new SecretKeySpec(Key,"AES");

        Cipher cifra = Cipher.getInstance("AES/CBC/PKCS5PADDING");
        cifra.init(Cipher.ENCRYPT_MODE, Chave, Vetor);

        byte[] cifrado = cifra.doFinal(message.getBytes());
        return Base64.getEncoder().encodeToString(cifrado);
    }catch(Exception e){
        e.printStackTrace();
        System.out.println("Erro ao cifrar mensagem");
    }
    return null;
}

public static void main(String[] args) throws UnsupportedEncodingException{

    //USER IMPUT BEGIN
    System.out.println("Qual a pergunta?");
    Scanner scanner = new Scanner(System.in);
    String question = scanner.nextLine();

    System.out.println("Qual a resposta?");
    String answer = scanner.nextLine();
    answer = answer.toLowerCase();

    System.out.println("Escrever mensagem a enviar: ");
    String message = scanner.nextLine();
    scanner.close();
    //USER IMPUT END

    //GERAR NÚMERO ALEATÓRIO DE 128 BITS (16 BYTES)
    SecureRandom random = new SecureRandom();
    BigInteger randN = (new BigInteger(random.generateSeed(16))).abs();

    //CONCATENAÇÃO PASS+ALEATÓRIO
    byte[] randPassConcat = (answer+randN).getBytes();

    //CHAMADA DO MÉTODO DE HASHING
    int iteracoes = 0;
    long start = System.currentTimeMillis();
    while(System.currentTimeMillis()-start<15000){
        try{
            randPassConcat = sha256(randPassConcat); 
            iteracoes++;                    
        }catch(Exception e){
            e.printStackTrace();
            System.out.println("Erro ao calcular hash");
        }                 
    }
    byte[] iv = random.generateSeed(16);

    String cripto = aesCbc(message,randPassConcat,iv);


    String key = bytesToHex(randPassConcat);
    System.out.println("KEY: "+key);

    //PRINT IV AS HEX
    System.out.println("IV: "+bytesToHex(iv));

    //PRINT CRIPTO AS HEX
    System.out.println("CRIPTO :"+bytesToHex(cripto.getBytes()) );

    String base64question = Base64.getEncoder().encodeToString(question.getBytes());
    //String base64cripto   = Base64.getEncoder().encodeToString(cripto.getBytes());
    String base64iv       = Base64.getEncoder().encodeToString(iv);
    try{
        PrintWriter writer = new PrintWriter("file.txt","UTF-8");
        writer.println(iteracoes); // NÚMERO ITERAÇÕES (int)
        writer.println(base64question); // PERGUNTA (string -> base64 string)
        writer.println(randN); // NÚMERO ALEATÓRIO (bigInt)
        writer.println(cripto); // CRIPTOGRAMA (string -> base64 string)
        writer.println(base64iv); // VECTOR INICIALIZAÇÃO (byte[] -> base64 string)
        writer.close();
    }catch(Exception e){
        e.printStackTrace();
    }
}   

Расшифровка:

private static String bytesToHex(byte[] hashInBytes) {

    StringBuilder sb = new StringBuilder();
    for (byte b : hashInBytes) {
        sb.append(String.format("%02x", b));
    }
    return sb.toString();

}

public static String aesCbcDecrypt(String cripto, byte[] Key, byte[] iv) throws UnsupportedEncodingException {
    try {
        IvParameterSpec Vetor = new IvParameterSpec(iv);
        SecretKeySpec Chave = new SecretKeySpec(Key, "AES");

        Cipher cifra = Cipher.getInstance("AES/CBC/PKCS5PADDING");
        cifra.init(Cipher.DECRYPT_MODE, Chave, Vetor);

        byte[] original = cifra.doFinal(cripto.getBytes()); 
        return new String(original);
    } catch (Exception ex) {
        System.out.println("Erro ao decifrar mensagem");
        ex.printStackTrace();
    }

    return null;
}

public static byte[] sha256(byte[] text) throws NoSuchAlgorithmException{

    MessageDigest md = MessageDigest.getInstance("SHA-256");
    byte[] digest = md.digest(text);
    return digest;    


public static void main(String [] args) throws UnsupportedEncodingException{
    //LER FICHEIRO LINHA-A-LINHA
    String array[] = new String[5];       
    try {
        int i = 0;
        Scanner scanner = new Scanner(new File(args[0])); //NOME DADO COMO PARÂMETRO
        while(scanner.hasNextLine()){
             array[i]=(scanner.nextLine());
             i++;         
        }
        scanner.close();
    } catch (Exception e) {
        e.printStackTrace();
    }

    int iteracoes = Integer.parseInt(array[0]);
    String question = new String(Base64.getDecoder().decode(array[1]));
    BigInteger randN = new BigInteger(array[2]);
    String cripto = new String(Base64.getDecoder().decode(array[3]));
    byte[] iv = (Base64.getDecoder().decode(array[4]));

    System.out.println(question);
    System.out.print("Introduzir resposta: ");
    Scanner scanner = new Scanner(System.in);
    String answer = scanner.nextLine();
    answer = answer.toLowerCase();
    scanner.close();

    byte[] randPassConcat = (answer+randN).getBytes();

    for(int i=0;i<iteracoes;i++){
        try {
            randPassConcat = sha256(randPassConcat);
        } catch (Exception e) {
            System.out.println("Erro ao calcular Hash");
            e.printStackTrace();
        }
    }
    String key = bytesToHex(randPassConcat);
    System.out.println("KEY: "+key);

    //PRINT IV AS HEX
    System.out.println("IV: "+bytesToHex(iv));

    //PRINT CRIPTO AS HEX
    System.out.println("CRIPTO :"+bytesToHex(array[3].getBytes()) );

    System.out.println(aesCbcDecrypt(cripto, randPassConcat, iv)); 
}

Я знаю, что это неправильный пароль но если исходные шестнадцатеричные значения совпадают, как это возможно?

1 Ответ

1 голос
/ 11 января 2020

Вы храните двоичные данные в переменной String cripto с помощью

String cripto = new String(Base64.getDecoder().decode(array[3]));

, а затем пытаетесь получить двоичные данные из строки в этом выражении

byte[] original = cifra.doFinal(cripto.getBytes());

Поскольку не существует однозначного перевода всех байтов назад и вперед между byte[] и String, вы в конечном итоге повредите данные, что в итоге приведет к ошибке заполнения. Ошибка заполнения является лишь признаком повреждения данных.

Просто сохраните данные в byte[] после декодирования base64

...