当前位置: 首页 > 知识库问答 >
问题:

获取错误javax.crypto.IllegalBlocksizeException:当用Java解密密码时,输入应该是8的倍数

卢黎昕
2023-03-14

在这里我添加密码和连接到他们的网站到我的数据库,我认为这工作很好。当我检查数据库时,我可以在数据库中看到加密密码:

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个答案

哈宪
2023-03-14

首先,除非您真正知道自己在做什么,否则加密密码(而不是比较正确的密码哈希,而不是普通的加密哈希)是个坏主意。用DES和ECB加密密码是一个糟糕的想法,前者已经被破坏了20年,后者的块大小很小,甚至不解密就可以破坏许多值。但是,安全性是security.sx的主题,而不是stackoverflow的主题,所以我假设您实际上并不想拥有安全性。

您最大的问题是生成两个不同的密钥:使用一个密钥加密,然后尝试使用不同的密钥解密。这是完全打破的;传统的(形式上,对称的)密码学的基础,从历史开始就是加密和解密使用相同的密钥。即使是现代的“非对称”公钥密码学也使用配对的密钥:给定一个P1键,你可以用P1的公共部分加密,用P1的私人部分解密,但不能用一些不同的P2或PX键。

由于要存储要在以后解密的加密html" target="_blank">数据,因此需要存储用于解密的密钥,以防止未授权方使用密钥。这是所谓的密钥管理的(一部分),也是实现安全性的实际困难部分,比简单的加密和解密要困难得多。你对你想做什么以及在什么环境中做什么的信息太少了,以至于我无法给出任何具体的建议。

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

您的代码字符串erikryptattu=(new String(cipherText,“UTF8”);将是另一个错误,除非这是死代码;你从不使用这个值。

对于电子和计算机密码学(即自1950年以来),密文值(以及散列、MACs和签名)基本上是任意的随机比特;它不是字符,并且试图像Javastring那样将其视为字符,通常会损坏它,特别是会更改密文,使其无法解密(即使使用正确的密钥和IV)。所以别那么做。使用base64,就像您的实时代码一样,是处理任意位的一种好方法

但你需要完全做到。您的解密例程tulkkaa需要在解密密文之前对密文进行base64解码。

 类似资料: