使用 ChangeFileEncryption() 解密 H2 数据库失败

Decrypt H2 Database using ChangeFileEncryption() fails

我想解密加密的 H2 数据库,以便能够在后续步骤中使用恢复工具。通过 "ChangeFileEncryption" 的解密似乎无法正常工作。一个小示例程序:

public class H2DecryptionTest{
    public static void main(String[] args){
      try {
          String path = "C:\test";
          String dbName = "database";
          String dbPassword = "password";
          String userName = "username";
          String userPassword = "userpassword";
          JdbcDataSource datasource = new JdbcDataSource();
          String dbAttributes = "\"+dbName+";USER="+userName+";PASSWORD="+userPassword+" " + dbPassword;
          datasource.setURL("jdbc:h2:" + path + dbAttributes);
          datasource.setUser(userName);
          datasource.setPassword(userPassword);

          Connection connection = datasource.getConnection();

          insertDefaultValues(connection);
          connection.close();

          /////// the following does not work properly: //////////
          ChangeFileEncryption.execute(path, dbName, "AES", dbPassword.toCharArray(), null, false);

          Recover.execute(path, dbName); // <<<<---- Exception is thrown here!
      } catch (Exception e) {
        e.printStackTrace();
      }
  }

  // just writing some stuff into the database to see that creation was ok, not important
  private static void insertDefaultValues(Connection connection) throws SQLException {
      Statement stmt = null;
      try {
          connection.setAutoCommit(false);
          stmt = connection.createStatement();
          stmt.execute("CREATE TABLE PERSON(id int primary key, name varchar(255))");
          stmt.execute("INSERT INTO PERSON(id, name) VALUES(1, 'One')");
          stmt.execute("INSERT INTO PERSON(id, name) VALUES(2, 'Two')");
          stmt.execute("INSERT INTO PERSON(id, name) VALUES(3, 'Three')");

          ResultSet rs = stmt.executeQuery("select * from PERSON");
          System.out.println("H2 Database inserted through Statement");
          while (rs.next()) {
              System.out.println("Id "+rs.getInt("id")+" Name "+rs.getString("name"));
          }
          stmt.close();
          connection.commit();
      } catch (SQLException e) {
          System.out.println("Exception Message " + e.getLocalizedMessage());
      } catch (Exception e) {
          e.printStackTrace();
      }
    }
}

控制台输出为:

    Connected to the target VM, address: '127.0.0.1:63156', transport: 'socket'
    H2 Database inserted through Statement
    Id 1 Name One
    Id 2 Name Two
    Id 3 Name Three
    Disconnected from the target VM, address: '127.0.0.1:63156', transport: 'socket'
    java.lang.IllegalStateException: Store header is corrupt: nio:C:/test/database.mv.db [1.4.193/6]
        at org.h2.mvstore.DataUtils.newIllegalStateException(DataUtils.java:765)
        at org.h2.mvstore.MVStore.readStoreHeader(MVStore.java:609)
        at org.h2.mvstore.MVStore.<init>(MVStore.java:359)
        at org.h2.mvstore.MVStore$Builder.open(MVStore.java:2923)
        at org.h2.mvstore.MVStoreTool.info(MVStoreTool.java:346)
        at org.h2.tools.Recover.process(Recover.java:342)
        at org.h2.tools.Recover.execute(Recover.java:320)
        at H2DecryptionTest.main(H2DecryptionTest.java:22)

    Process finished with exit code 0

所以我的问题是:如何正确解密数据库?提前致谢:)

我自己发现了错误 - 也许它可以帮助其他人:

  • 例子中忘记在dbAttributes中添加加密方式(cypher=AES)

    String dbAttributes = "\"+dbName+";CIPHER=AES;USER="+userName+";PASSWORD="+userPassword+" " + dbPassword;
    
  • 我输入了错误的 ChangeFileEncryption 密码。第一个密码(在这种情况下 "userPassword")应该可以做到。