获取错误javax.crypto.IllegalBlockSizeException:使用Java解密密码时,输入应为8的倍数

时间:2017-09-26 01:40:10

标签: java encryption javax

在这里,我将连接到它们的密码和站点添加到我的数据库中,我认为这样可以正常工作。当我检查它时,我可以在数据库中看到加密的密码:

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;
}

}

1 个答案:

答案 0 :(得分:0)

作为初步,加密密码是一个坏主意(而不是比较正确的密码哈希,不是一个简单的加密哈希),除非你真的知道你在做什么。使用DES加密密码是一个糟糕的想法,已经破坏了20年,而ECB使用小块大小可以在不解密的情况下破解许多值。但是,安全性是security.SX的主题,而不是stackoverflow,所以我假设你不想真正拥有安全性。

您最大的问题是您生成了两个不同的密钥:使用一个密钥加密,然后尝试使用其他密钥进行解密。这完全打破了;自历史开始以来,传统(形式上称为“对称”)密码术的基础是加密和解密使用相同的密钥。即使是现代的“非对称”aka公钥加密也使用匹配对中的密钥:给定密钥对P1,您可以使用P1的公共部分进行加密,并使用P1的私有部分进行解密,但不能使用某些不同的密钥对P2或Px进行解密。

由于您希望存储要在以后解密的加密数据,因此您需要存储将用于解密的密钥,以防止未经授权方使用该密钥。这是所谓的密钥管理(的一部分),是实现安全性的实际难点,比简单的加密和解密要困难得多。您提供的信息很少,关于您想要做什么以及在什么环境中我无法给出任何具体建议。

如果您更改为比ECB更好的模式,您还需要为每个加密值存储初始化向量(IV)(或等效),但这更容易,因为IV不需要保密。

您的代码String erikryptattu = ( new String(cipherText, "UTF8") ); 成为另一个错误,除了这是死代码;你从不使用这个值。

对于电子和计算机密码术(即大约1950年以来),密文值(以及散列,MAC和签名)本质上是随机的随机位;它不是字符,并试图将其视为字符,正如Java String所做的那样,通常会破坏它,特别是会改变密文以使其无法解密(即使使用正确的密钥和IV)。所以不要这样做。使用base64作为实时代码,是处理任意位的一种好方法。

但你需要完全做到。在解密之前,您的解密例程tulkkaa需要 base64-decode the ciphertext