Willena sqlite jdbc cannot open SqlCipher db - java

I am trying to figure out how to encrypt a sqlite database in non-android java.
It does not seem to be super straight forward, but I Willena jdbc crypt which does seem to be able to create an encrypted database, but I simply cannot figure out how to access a SQLCipher 4 encrypted database with it.
Here is my code.
String path = "jdbc:sqlite:C:\\Users\\User1\\Desktop\\testServer232.db";
Connection connection = null;
try
{
// create a database connection
connection = DriverManager.getConnection(path+"?cipher=sqlcipher&key=a");
Statement statement = connection.createStatement();
statement.setQueryTimeout(30); // set timeout to 30 sec.
statement.executeUpdate("drop table if exists person");
statement.executeUpdate("create table person (id integer, name string)");
statement.executeUpdate("insert into person values(3, 'leo1')");
statement.executeUpdate("insert into person values(4, 'yui1')");
ResultSet rs = statement.executeQuery("select * from person");
while(rs.next())
{
// read the result set
System.out.println("name = " + rs.getString("name"));
System.out.println("id = " + rs.getInt("id"));
}
}
catch(SQLException e)
{
// if the error message is "out of memory",
// it probably means no database file is found
System.err.println(e.getMessage());
}
finally
{
try
{
if(connection != null)
connection.close();
}
catch(SQLException e)
{
// connection close failed.
System.err.println(e.getMessage());
}
}
This code does work, but I don't think that it produces a SqlCipher 4 encrypted database. When I try to open it with DB browser for Sqlite, it does not allow me access when I put the password = a.
Where am I going wrong?

Ok, so I ended up finding the creator of the repository. And he solved it easily and answered really fast.
Here is the solution:
Here are a few things that could be tested:
Use version 3.31.1
Try to do the database connection using "jdbc:sqlite:file:C:\Users\User1\Desktop\test.db?cipher=sqlcipher&key=password123"as URI (notice the added "file:").
Try to add the legacy parameter for SQLCipher as available here (https://github.com/Willena/sqlite-jdbc-crypt#aes-256-bit-cbc---sha1sha256sha512-hmac-sqlcipher). The URI will become something like this: "cipher=sqlcipher&key=password123&legacy=4"
This is now working for me. I recommend that others use it if they are interested in an easy way to do sqlcipher version 4 similarly to how it is done in an android project.

Related

Batch Insert not Inserting

I have been trying to insert a "batch" of data into a SQLITE db in an Android application. I am getting no errors, but when trying to select from that Table later, no data is returned.
The application uses both SQL server and SQLITE since the device wont always be connected to the network it cannot access SQLServer all the time, so I am running a query to select from SQLServer and then I pass that resultset to the method that is meant to push the data to the SQLITE DB
The process flow I am following is as follows:
Delete everything currently in the sqliteDB
mDb = mDbHelper.getReadableDatabase();
mDb.execSQL("delete from TABLE_1");
Get data from SQLserver
Connection con = connectionClass.CONN();
connect = con;
try {
PreparedStatement statement = connect.prepareStatement("Exec SelectAll '" + Param1+ "'");
rs = statement.executeQuery();
liteAdapter.insertIntoDbLite(rs);
con.close();
} catch (SQLException ex) {
String error = ex.getMessage();
}
Pass resultset from step 2 to the method that should batch insert the data to sqlite
//Insert Records into Bale Table from SQL Server
public void insertIntoDbLite(ResultSet rs)
{
mDb = mDbHelper.getWritableDatabase();
mDb.beginTransaction();
try {
ContentValues values = new ContentValues();
try {
while (rs.next()) {
//put value(Column_Name, record)
values.put("COL1", rs.getString("Col1_Val"));
values.put("COL2", rs.getString("Col2_Val"));
values.put("COL3", rs.getString("Col3_Val"));
values.put("COL4", rs.getString("Col4_Val"));
values.put("COL5", rs.getString("Col5_Val"));
values.put("COL6", rs.getString("Col6_Val"));
values.put("COL7", rs.getString("Col7_Val"));
values.put("COL8", rs.getString("Col8_Val"));
values.put("COl9", rs.getString("Col9_Val"));
}
mDb.insert("TABLE_1", null, values);
}
catch (java.sql.SQLException e)
{
Log.e("Error in SQL",e.toString());
}
mDb.setTransactionSuccessful();
}
catch(Exception ex)
{
Log.e("Error in transaction",ex.toString());
}
finally
{
//End the transaction
mDb.endTransaction();
}
}
so it all seems to run fine, but when I later query the db and to a select, no values are returned from this table,
am I missing something or just doing it wrong?
Thanks
There appears to be nothing glaringly wrong with the given code. The likely scenario is that the update is in not performing the update due to a constraint (a rule such as, but not limited to NOT NULL, UNIQUE). Another, perhaps less likely scenario is that the while loop isn't being entered.
You could distinguish which by changing
mDb.insert("TABLE_1", null, values);
to
Log.d("INSERT","Return from insert is " + Long.toString(mDb.insert("TABLE_1", null, values)));
This will then either write output with :-
(a) no output to the log indicating that the while loop was not entered, so rs is empty.
(b) -1 being the sole value(s) returned, indicating that the update is not being done due to constraints.
(c) with all or some positive (> 0) value(s) returned, this would indicate, that the updates are being performed and that the issue is likely with the method used to checked the data later.
If (b) then changing mDb.insert to mDb.insertOrThrow should result in the first exception being caught which should indicate the issue.

Update statement working in SQLite Browser not in java with the exact same syntax

Okay I executed the same code thats in the update query in the SQLite db browser and it worked successfully
public void StatusUpdate(ActionEvent event) {
try {
String test = null;
test = txtEditStatus.getText();
System.out.println(test);
String query = "UPDATE member SET desc = ? WHERE username = ?";
PreparedStatement preparedStmt = connection.prepareStatement(query);
preparedStmt.setString (1, test);
preparedStmt.setString(2, "Custom Hue");
// execute the java preparedstatement
preparedStmt.executeUpdate();
connection.close();
} catch (Exception e) {
}
However when running eclipse with JFx, it prints what I type in the console but doesnt update in the db, anyone know why?
For the user asking about the connection:
Connection connection;
public ProfileController() {
connection = SQLConnection.Connector();
if (connection == null)
System.exit(1);
}
I would check that your connection is actually connected to the correct database.
are you sure you have the right connection string set up?
you should do an output on your exception handler, what if there is an exception?
are you sure the connection is open?
are you sure the user exists in the database and table you are trying to update?
try doing a read first, to see if you have an open connection. Print your exception, just in case, never leave it blank. That's just bad practice.
How about you try a
preparedStmt.executeUpdate();
connection.commit();
connection.close();
Just incase autocommit isn't enabled?

Get the connected mysql database name (JDBC)

How can get the name of the database name from connection object
try {
this.ds = (DataSource) new InitialContext().lookup("java:comp/env/jdbc/amger");
} catch (NamingException ne) {
}
Connection conObj = ds.getConnection();
How do I get that Database name from con
Probably the most straightforward way to get the database name from the JDBC Connection object itself is via the getCatalog() method:
Connection#getCatalog()
However, as Konstantin pointed out in his comment below, that value will not change if the current MySQL database is changed by issuing a USE dbname statement.
getCatalog() might still be useful in an application that
does not change databases, or
does things "The JDBC Way" by using setCatalog() to change the current database,
but for MySQL, using SELECT DATABASE() appears to be safer overall.
Note also that this potential discrepancy between getCatalog() and the actual current database depends on the behaviour of the particular JDBC driver. Out of curiosity I tried something similar with the Microsoft JDBC Driver 4.0 for SQL Server and .getCatalog() was indeed aware of the change to the current database immediately after running a USE dbname statement. That is, the code
String connectionUrl = "jdbc:sqlserver://localhost:52865;"
+ "databaseName=myDb;" + "integratedSecurity=true";
try (Connection con = DriverManager.getConnection(connectionUrl)) {
System.out.println(String.format(
"getCatalog() returns: %s",
con.getCatalog()));
try (Statement s = con.createStatement()) {
System.out.println(" Executing: USE master");
s.execute("USE master");
}
System.out.println(String.format(
"getCatalog() returns: %s",
con.getCatalog()));
} catch (Exception e) {
e.printStackTrace(System.out);
}
produced the following results:
getCatalog() returns: myDb
Executing: USE master
getCatalog() returns: master
If you know that DB is Mysql you could just perform SELECT DATABASE() on your connection and read the resulset with current database name in it.
Here is description of DATABASE function.
Let's assume you used url as "jdbc:mysql://localhost/test"
Then do the following:
DatabaseMetaData dmd = connection.getMetaData();
String url = dmd.getURL();
System.out.println(url.substring(url.lastIndexOf("/") + 1));
Run
System.out.println(connection.getMetaData().getURL());
Paste the output in notepad
search the value for 'databaseName=yourDBName'

Save a fingerprint template into a database mysql - java

I am developing a project with the sdk fingerprint of Griaule , and as a start I'm creating a program without a GUI that allows the user to scan his fingerprint and store it in a mysql database already created earlier.
I'm here to ask you a hand with regard to storing the fingerprint in the database.
In the program I created, I captured the fingerprint, I extracted the template from the fingerprint through a function I call extract () .
After that I should call another function , enroll (), which allows me to save the fingerprint in a database.
Even looking at the SDK examples I did not understand how it works, can someone help me? thanks in advance! :)
public void enroll() {
try {
//Inserts the template on the database
enrollStmt.setBinaryStream(1,new ByteArrayInputStream(template.getData()), template.getData().length);
enrollStmt.executeUpdate();
//Picks the ID generated for it.
ResultSet rs = insertedIdStmt.executeQuery();
rs.next();
ui.writeLog("Fingerprint enrolled with id = "+Integer.toString(rs.getInt(1)));
} catch (SQLException e) {
ui.writeLog("Error enrolling template");
}
}
It is saving the finger print data as BLOB in the database. Blob (Binary Large Object) is nothing but a byte array representation of information, mainly used to store images etc in database. In your case, the fingerprint information is being stored.
enrollStmt.setBinaryStream(1,new ByteArrayInputStream(template.getData()), template.getData().length);
In this line, the bytearrayinputstream is created using the data in the template object. template.getData is giving you the byte[] representation of the fingerprint information. Then the byte[] is getting saved in database, by
enrollStmt.executeUpdate();
Whereas, the following query gives you the id for the data stored, for your use.
ResultSet rs = insertedIdStmt.executeQuery();
Ok thank you very much Hirak , so I open a new connection with a function I created called initdb () , structured as follows:
private void initDB() {
try {
//Loads the JDBC driver.
Class.forName("com.mysql.jdbc.Driver").newInstance();
/**Connection to the Database.*/
Connection db;
String user = "root";
String password = "";
// connect to a memory database
db = DriverManager.getConnection("jdbc:mysql://localhost:3306/impronte?user=" + user + "&password=" + password);
Statement stm = (Statement) db.createStatement();
//Creates the statements that will be executed on the database,
enrollStmt = db.prepareStatement("INSERT INTO persona(template) values(?)");
insertedIdStmt = db.prepareStatement("SELECT MAX(ID) FROM persona");
} catch (Exception e) {
System.out.println("Error connecting to the database.");
System.out.println(e.getMessage());
}
}
and inside the enroll function this code, but nevertheless gives me the error("Error enrolling template"):
public void enroll ( Template template ) throws GrFingerJavaException {
try {
//Inserts the template on the database
enrollStmt.setBinaryStream(1,new ByteArrayInputStream(template.getData()), template.getData().length);
enrollStmt.executeUpdate();
//Picks the ID generated for it.
ResultSet rs = insertedIdStmt.executeQuery();
rs.next();
System.out.println("Fingerprint enrolled with id = "+Integer.toString(rs.getInt(1)));
System.out.println("Fingerprint enrolled");
} catch (SQLException e) {
System.out.println("Error enrolling template");
}
}
You need to set the template to the template class of the sdk you are using before calling the binaryStream, see what I meant: Line 6 if I'm correct.
public void enroll ( Template template ) throws GrFingerJavaException {
try {
//Inserts the template on the database
Template temp = template;
if(temp != null){
byte[] b = temp.serialize();
enrollStmt.setBytes(1, b);
}
enrollStmt.executeUpdate();
//Picks the ID generated for it.
ResultSet rs = insertedIdStmt.executeQuery();
rs.next();
System.out.println("Fingerprint enrolled with id = "+Integer.toString(rs.getInt(1)));
System.out.println("Fingerprint enrolled");
} catch (SQLException e) {
System.out.println("Error enrolling template");
}
}

Unable to figure out JDBC ClassNotFoundException (JTDS driver)

So a little background on my problem: I am trying to copy over a table on an Microsoft SQL system from an Oracle database. Besides giving password and user access to the table I cannot edit or do anything to the MSSQL database.
I successfully used the Oracle SQL Developer to connect and view the tables I want (using a third party JDBC driver), but I want to set up an automated copy-over into my Oracle database so I am attempting to use the same driver in some stored java code.
I have a java function that all it should do is go and count the number of entries in the table. So far my code looks like:
public static String getCount() {
Statement stmt = null;
Connection conn = null;
int rowCount = 0;
String message = "";
try {
Class.forName("net.sourceforge.jtds.jdbc.Driver");
}
catch(ClassNotFoundException e) {
System.err.println("Error loading driver: " + e);
message = message + e + " -ER1 \n";
}
try {
conn = DriverManager.getConnection("jdbc:jtds:sqlserver://site.school.edu:2000/ACCESS", "user", "password");
stmt = conn.createStatement();
String strSelect = "select 1 as field;";
ResultSet rset = stmt.executeQuery(strSelect);
while (rset.next()) {
++rowCount;
}
}
catch(SQLException ex) {
ex.printStackTrace();
message = message + ex.getSQLState() + " -ER2";
}
finally {
try {
if (stmt != null) stmt.close();
if (conn != null) conn.close();
} catch(SQLException ex) {
ex.printStackTrace();
message = message + ex.getSQLState() + "-ER3";
}
}
return message;
}
Which is being calling from a stored function :
CREATE OR REPLACE function Schema.java_testMessage return varchar2
as language java
name 'ConnectAndQuery.getCount() return java.lang.String';
Which I am calling from a script in TOAD:
set serveroutput on;
declare
words varchar2(400);
begin
words := KSL_ADMIN.java_testMessage;
dbms_output.put_line(words);
end;
However the result is that I'm getting:
java.lang.ClassNotFoundException: net/sourceforge/jtds/jdbc/Driver -ER1
08001 -ER2
PL/SQL procedure successfully completed.
I have the jar file within the class path, I can't think of any reason it shouldn't have the nessecary permissions to see the jar, and as far as I can tell I have everything spelled correctly.
Please help me figure out what I am doing wrong. Or if there is perhaps an easier way to go about connecting an Oracle DB to an MSSQL DB without really installing anything. Any knowledge on this is welcome as I am pretty new to a lot of this.
Oracle has its own internal java virtual machine and it does not use the system classpath. If you need external libraries you must “load” them into the internal JVM. You can do this using Oracle's loadjava tool.
See the Oracle's loadjava documentation (http://docs.oracle.com/cd/B28359_01/java.111/b31225/cheleven.htm#JJDEV10060)

Categories

Resources