4

Вопрос по encryption, passwords, java – PBE: проверьте пароль, прежде чем пытаться расшифровать

Я делаю приложение на Java и хочу разрешить пользователям шифровать файл (или папку - я заархивирую каталог), используя пароль по своему выбору. В настоящее время у меня есть следующие методы:

static Cipher createCipher(int mode, String password) throws Exception {
            PBEKeySpec keySpec = new PBEKeySpec(password.toCharArray());
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
            SecretKey key = keyFactory.generateSecret(keySpec);
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update("input".getBytes());
            byte[] digest = md.digest();
            byte[] salt = new byte[8];
            for (int i = 0; i < 8; ++i)
              salt[i] = digest[i];
            PBEParameterSpec paramSpec = new PBEParameterSpec(salt, 20);
            Cipher cipher = Cipher.getInstance("PBEWithMD5AndDES");
            cipher.init(mode, key, paramSpec);
            return cipher;
    }

     static void applyCipher(String inFile, String outFile, Cipher cipher) throws Exception {
            String decryption = "";
            CipherInputStream in = new CipherInputStream(new FileInputStream(inFile), cipher);
            BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(outFile));
            int BUFFER_SIZE = 8;
            byte[] buffer = new byte[BUFFER_SIZE];
            int numRead = 0;
            do {
              numRead = in.read(buffer);
              System.out.println(buffer + ", 0, " + numRead);
              if (numRead > 0){
                out.write(buffer, 0, numRead);
                System.out.println(toHexString(buffer, 0, numRead));
              }
             } while (numRead == 8);
            in.close();
            out.flush();
            out.close();
          }
     private static char[] hex_table = {
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 
            'a', 'b', 'c', 'd', 'e', 'f'};

     public static String toHexString(byte[] data, int offset, int length)
     {
       StringBuffer s = new StringBuffer(length*2);
       int end = offset+length;

       for (int i = offset; i < end; i++)
       {
         int high_nibble = (data[i] & 0xf0) >>> 4;
         int low_nibble = (data[i] & 0x0f);
         s.append(hex_table[high_nibble]);
         s.append(hex_table[low_nibble]);
       }

       return s.toString();
     }

Однако, чтобы сделать программу более удобной для пользователя, я хотел бы иметь возможность проверить, что пользователь ввел правильный пароль перед созданием файла. Я не хочу "оставлять ключ под ковриком у двери". или полностью отменить безопасность и т. д. - я просто хочу предотвратить создание неправильного файла, если пользователь вводит неправильный пароль ...

Любые идеи будут с благодарностью. Если вам нужна дополнительная информация, не стесняйтесь спрашивать.

заранее спасибо

  • Я знаю, что вы не должны этого делать, но я полагаю, что «менее небезопасно»; Вы имеете в виду «менее безопасный»!? Кроме того, развивая эти идеи, вы думаете, что я смогу использовать метод по следующей ссылке, чтобы сохранить хешированную версию пароля в верхней части файла для проверки, а затем продолжить дешифрование остальной части файл, если пароль правильный? Если это так, насколько это будет безопасно?rgagnon.com/javadetails/java-0400.html Кстати, спасибо за ваш ответ, особенно с примитивами / стандартами!

    от Andy
  • Спасибо за ваш ответ и искренние извинения за отсутствие моего ответа. Я бы внедрил режим AEAD, но, честно говоря, он кажется немного сложным для того, что я делаю (в данный момент), и ответ, который я принял, является наиболее подходящим для моей ситуации ... +1

    от Andy
  • Да, я имею в виду менее безопасный. При условии, что файл с хэшем пароля зашифрован, конечно. На самом деле, вы можете просто сохранить пароль в этот момент, так как файл защищен. На самом деле, пост @erickson ниже, вероятно, является лучшей идеей, если вы можете получить аутентифицированный режим работы блочного шифра (он не поддерживается на всех платформах Java). Я не думаю, что PBKDF2 - это замена для PBE. Мне нужны разные параметры. Я считаю, что это рабочий примерstackoverflow.com/a/992413/980922

    от
  • Кроме того, я только что попытался реализовать этот PBKDF2WithHmacSHA1 и создать шифр так же, как я делал с PBEWithMD5AndDES, но каждый раз, когда я делаю это, я получаюInvalidKeySpecException: Salt not found, Кто-нибудь знает почему? Я использую последнюю версию Java / JDK.

    от Andy
  • С той же солью, паролем и количеством итераций PBKDF2 выдаст тот же ключ. Вы упоминаете зашифрованный текст. По своему замыслу (на самом деле это крайне важно для их безопасности) шифры, такие как AES, имеющие один и тот же ключ и сообщение, будут каждый раз создавать разные шифрованные тексты. Это особенность.

    от
  • Спасибо за эту ссылку и разъяснения. Я пытался внедрить PBKDF2, используя несколько примеров в сети, например, по следующей ссылке. Тем не менее, насколько я вижу сейчас, каждый раз, когда вы создаете новый шифр даже с тем же паролем и солью, он дает другой результат, а это не то, чего я хочу. Есть идеи?

    от Andy
  • Еще раз спасибо, я в конечном итоге использовал этот метод, но теперь я храню пароль в верхней части файла (как вы увидите, прочитав принятый ответ).

    от Andy
  • Спасибо за ваш ответ, но я не совсем понимаю, что вы имеете в виду. Вы говорите, что я должен хранить пароль в виде простого текста рядом с зашифрованным файлом или хранить пароль в зашифрованном файле с фиксированным паролем / алгоритмом? Пожалуйста, уточните / объясните ...

    от Andy
  • когда пользователь дает пароль к файлу, вы шифруете его и сохраняете в файле (который шифруется таким же образом). когда пользователь загружает файл, вы запрашиваете пароль, шифруете его и сравниваете его с зашифрованным паролем из файла. поэтому пароль хранится в файле, но зашифрован. Я думаю, что так же, как пароли хранятся в Unix.

    от
  • Если бы я реализовал что-то вроде этого, я бы сжал файлы, выбранные пользователем, но я бы также добавил очень маленький файл (1 байт), используемый для проверки пароля, а затем проверил содержимое файла.

    от Security Hound
  • 2

    Используйте PBKDF2WithHmacSHA1

    а не PBEWithMD5AndDES. У поздних пользователей два разных устаревших примитива. Первый является текущим стандартом.

    у вас есть два варианта

    Fast but less secure: Put a short known value at the start of your encrypted file or encrypt an entirely different short file under the same password. When you decrypt this file, check for the known value.

    Clearly this works quickly. Its slightly less secure because it means an attacker attempting to brute force the password can discard a guessed password faster: instead of having to look at the whole file, they just have to check that value. This is not really a big issue since your key derivation function should be hard enough and they still have to run that

    Store the hash of the file encrypted as well and verify the hash on decryption. More secure in that the attacker has to decrypt the whole file and read through it, but by the same token it is slow.

  • 3

    Вы можете сохранить зашифрованный пароль вместе с файлом. Когда пользо

    ватель вводит пароль, вы шифруете его и проверяете, присутствует ли в файле тот же зашифрованный пароль. Если нет, вы не загружаете файл.

  • 1

    Я бы использовал

    AEAD режим, как CCM или EAX. Это проверит целостность каждого блока файла во время его дешифрования, в случае неудачи, если ключ неверен или файл был подделан. Поставщик Bouncy Castleподдерживает оба из этих режимов.