Получение ошибки javax.crypto.IllegalBlockSizeException: ввод должен быть кратен 8 при расшифровке паролей с помощью Java

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

public static void lisaa(PreparedStatement statement, ResultSet resultSet, 
    Connection connection, Scanner lukija, Kryptaaja kc)throws SQLException, 
    Exception {
    System.out.println("Sivu salasanalle: ");
    String sivu = lukija.nextLine();
    System.out.println("Salasana: ");
    String ss = lukija.nextLine();
    String[] sanabytes = new String[] {ss};


    statement = connection.prepareStatement("INSERT INTO PASSWORDS (sivu, 
    salasana) VALUES(?, ?)");
    statement.setString(1, sivu);
    statement.setString(2, kc.kryptaa(sanabytes));
   statement.executeUpdate();
}

Мой метод, который извлекает зашифрованные пароли из базы данных и пытается их распечатать:

public static void tulosta(PreparedStatement statement, ResultSet resultSet, 
    Connection connection, Kryptaaja kc)throws SQLException, Exception {
    statement = connection.prepareStatement("select * from PASSWORDS");
    resultSet = statement.executeQuery();
    boolean onko = false;
    while (resultSet.next()) {
        onko = true;
      String sivu = resultSet.getString("sivu");
      String ss = resultSet.getString("salasana");

     String[] sanabytes = new String[]{ss};
     String dekryptattu = kc.tulkkaa(sanabytes);
     System.out.println(sivu + ": " + dekryptattu );
   }
   if (!onko) {
    System.out.println("ei kappaleita!");
  }

}

Мой класс, который шифрует и расшифровывает пароль. Игнорируйте комментарии, это только для тестирования, они здесь, чтобы пояснить мне, что делает код (не мой):

public Kryptaaja(){

}

Шифруя пароль, я думаю, что это работает:

 public String kryptaa (String[] args) throws Exception {
    //
    // Check args and get plaintext
    if (args.length !=1) {
        System.err.println("Usage: java PrivateExample text");
        System.exit(1);
    }
    byte[] plainText = args[0].getBytes("UTF8");
    //
    // Get a DES private key
    KeyGenerator keyGen = KeyGenerator.getInstance("DES");

    // If you do not initialize the KeyGenerator, each provider supply a default initialization.
    keyGen.init(56);
    Key key = keyGen.generateKey();
    //
    // Creates the DES Cipher object (specifying the algorithm, mode, and padding).
    Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
    // Print the provider information       
    //
    // Initializes the Cipher object.
    cipher.init(Cipher.ENCRYPT_MODE, key);
    // Encrypt the plaintext using the public key
    byte[] cipherText = cipher.doFinal(plainText);
    String kryptattu = Base64.getEncoder().encodeToString(cipherText);
    String erikryptattu = ( new String(cipherText, "UTF8") );
    return kryptattu;
}

Способ расшифровки пароля, думаю проблема моя кроется вот в этом:

 public String tulkkaa (String[] args) throws Exception {
    //
    // Check args and get plaintext
    if (args.length !=1) {
        System.err.println("Usage: java PrivateExample text");
        System.exit(1);
    }
    byte[] krypted = args[0].getBytes("UTF8");
    //
    // Get a DES private key
    KeyGenerator keyGen = KeyGenerator.getInstance("DES");

    // If you do not initialize the KeyGenerator, each provider supply a default initialization.
    keyGen.init(56);
    Key key = keyGen.generateKey();
    //
    // Creates the DES Cipher object (specifying the algorithm, mode, and padding).
    Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
    // Initializes the Cipher object.
    cipher.init(Cipher.DECRYPT_MODE, key);
    // Decrypt the ciphertext using the same key
    byte[] newPlainText = cipher.doFinal(krypted);

Здесь я кодирую байты -> Строка:

    String sana = Base64.getEncoder().encodeToString(newPlainText);
    String eri =( new String(newPlainText, "UTF8") );
    return sana;
}

}


person Riku    schedule 26.09.2017    source источник
comment
Проверьте это stackoverflow.com/questions/10836139/   -  person Naman    schedule 26.09.2017


Ответы (1)


Предварительно, шифровать пароли (вместо сравнения правильного хэша пароля, не простого крипто-хэша) — плохая идея, если вы действительно не знаете, что делаете. Это ужасная идея шифровать пароли с помощью DES, который взломан уже 20 лет, и ECB, который при небольшом размере блока позволяет взломать множество значений, даже не расшифровывая. Тем не менее, безопасность - это тема безопасности. SX, а не stackoverflow, поэтому я предполагаю, что вы на самом деле не хотите иметь безопасность.

Ваша большая проблема в том, что вы генерируете два разных ключа: вы шифруете одним ключом, а затем пытаетесь расшифровать другим ключом. Это полностью сломано; в основе традиционной (формально «симметричной») криптографии с начала истории лежит то, что шифрование и дешифрование используют один и тот же ключ. Даже современная «асимметричная» криптография, известная как криптография с открытым ключом, использует ключи в совпадающих парах: при наличии пары ключей P1 вы можете зашифровать с помощью открытой части P1 и расшифровать с помощью частной части P1, но не какой-то другой пары ключей P2 или Px.

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

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


Ваш код String erikryptattu = ( new String(cipherText, "UTF8") ); был бы еще одной ошибкой, за исключением того, что это мертвый код; вы никогда не используете это значение.

Для электронной и компьютерной криптографии (то есть примерно с 1950 г.) значения зашифрованного текста (а также хэши, MAC и подписи) представляют собой произвольные по существу случайные биты; это не символы, и попытка обращаться с ними как с символами, как это делает Java String, обычно искажает их и, в частности, меняет зашифрованный текст, чтобы его нельзя было расшифровать (даже с правильным ключом и IV). Так что не делай этого. Использование base64, как и ваш живой код, является хорошим способом обработки произвольных битов.

Но делать это нужно полностью. Ваша подпрограмма расшифровки tulkkaa должна декодировать зашифрованный текст с помощью base64 перед его расшифровкой.

person dave_thompson_085    schedule 26.09.2017