Initial commit

This commit is contained in:
Paul Schaub 2022-03-01 15:19:01 +01:00
commit b142f310be
Signed by: vanitasvitae
GPG key ID: 62BEE9264BF17311
46 changed files with 2494 additions and 0 deletions

View file

@ -0,0 +1,47 @@
// SPDX-FileCopyrightText: 2022 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
package pgp.cert_d.jdbc.sqlite;
import java.io.IOException;
import java.sql.SQLException;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import pgp.certificate_store.SubkeyLookup;
public class DatabaseSubkeyLookup implements SubkeyLookup {
private final SubkeyLookupDao dao;
public DatabaseSubkeyLookup(SubkeyLookupDao dao) {
this.dao = dao;
}
@Override
public Set<String> getCertificateFingerprintsForSubkeyId(long subkeyId) throws IOException {
try {
List<Entry> entries = dao.selectValues(subkeyId);
Set<String> certificates = new HashSet<>();
for (Entry entry : entries) {
certificates.add(entry.getCertificate());
}
return Collections.unmodifiableSet(certificates);
} catch (SQLException e) {
throw new IOException("Cannot query for subkey lookup entries.", e);
}
}
@Override
public void storeCertificateSubkeyIds(String certificate, List<Long> subkeyIds) throws IOException {
try {
dao.insertValues(certificate, subkeyIds);
} catch (SQLException e) {
throw new IOException("Cannot store subkey lookup entries in database.", e);
}
}
}

View file

@ -0,0 +1,47 @@
// SPDX-FileCopyrightText: 2022 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
package pgp.cert_d.jdbc.sqlite;
/**
* Subkey-ID database entry.
*/
public class Entry {
private final int id;
private final String certificate;
private final long subkeyId;
public Entry(int id, long subkeyId, String certificate) {
this.id = id;
this.subkeyId = subkeyId;
this.certificate = certificate;
}
/**
* Get the internal ID of this entry in the database.
*
* @return internal id
*/
public int getId() {
return id;
}
/**
* Return the key-ID of the subkey.
*
* @return subkey id
*/
public long getSubkeyId() {
return subkeyId;
}
/**
* Return the fingerprint of the certificate the subkey belongs to.
* @return fingerprint
*/
public String getCertificate() {
return certificate;
}
}

View file

@ -0,0 +1,93 @@
// SPDX-FileCopyrightText: 2022 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
package pgp.cert_d.jdbc.sqlite;
import org.sqlite.SQLiteErrorCode;
import org.sqlite.SQLiteException;
import java.io.File;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
public class SqliteSubkeyLookupDaoImpl implements SubkeyLookupDao {
private final String databaseUrl;
private static final String CREATE_TABLE_STMT = "" +
"CREATE TABLE IF NOT EXISTS subkey_lookup (\n" +
" id integer PRIMARY KEY,\n" + // id (internal to the database)
" certificate text NOT NULL,\n" + // certificate fingerprint
" subkey_id integer NOT NULL,\n" + // subkey id
" UNIQUE(certificate, subkey_id)\n" +
")";
private static final String INSERT_STMT = "" +
"INSERT INTO subkey_lookup(certificate, subkey_id) " +
"VALUES (?,?)";
private static final String QUERY_STMT = "" +
"SELECT * FROM subkey_lookup " +
"WHERE subkey_id=?";
public SqliteSubkeyLookupDaoImpl(String databaseURL) throws SQLException {
this.databaseUrl = databaseURL;
try (Connection connection = getConnection(); Statement statement = connection.createStatement()) {
statement.execute(CREATE_TABLE_STMT);
}
}
public Connection getConnection() throws SQLException {
return DriverManager.getConnection(databaseUrl);
}
public static SqliteSubkeyLookupDaoImpl forDatabaseFile(File databaseFile) throws SQLException {
return new SqliteSubkeyLookupDaoImpl("jdbc:sqlite:" + databaseFile.getAbsolutePath());
}
public int insertValues(String certificate, List<Long> subkeyIds) throws SQLException {
int inserted = 0;
try (Connection connection = getConnection(); PreparedStatement statement = connection.prepareStatement(INSERT_STMT)) {
for (long subkeyId : subkeyIds) {
try {
statement.setString(1, certificate);
statement.setLong(2, subkeyId);
statement.executeUpdate();
inserted++;
} catch (SQLiteException e) {
// throw any exception, except:
// ignore unique constraint-related exceptions if we ignoreDuplicates
if (e.getResultCode().code == SQLiteErrorCode.SQLITE_CONSTRAINT_UNIQUE.code) {
// ignore duplicates
} else {
throw e;
}
}
}
}
return inserted;
}
public List<Entry> selectValues(long subkeyId) throws SQLException {
List<Entry> results = new ArrayList<>();
try (Connection connection = getConnection(); PreparedStatement statement = connection.prepareStatement(QUERY_STMT)) {
statement.setLong(1, subkeyId);
try (ResultSet resultSet = statement.executeQuery()) {
while (resultSet.next()) {
Entry entry = new Entry(
resultSet.getInt("id"),
resultSet.getLong("subkey_id"),
resultSet.getString("certificate"));
results.add(entry);
}
}
}
return results;
}
}

View file

@ -0,0 +1,15 @@
// SPDX-FileCopyrightText: 2022 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
package pgp.cert_d.jdbc.sqlite;
import java.sql.SQLException;
import java.util.List;
public interface SubkeyLookupDao {
int insertValues(String certificate, List<Long> subkeyIds) throws SQLException;
List<Entry> selectValues(long subkeyId) throws SQLException;
}

View file

@ -0,0 +1,8 @@
// SPDX-FileCopyrightText: 2022 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
/**
* Implementation of a {@link pgp.certificate_store.SubkeyLookup} mechanism using an SQLite Database.
*/
package pgp.cert_d.jdbc.sqlite;