
me.sniggle.pgp.crypt.internal.BasePGPCommon Maven / Gradle / Ivy
The newest version!
package me.sniggle.pgp.crypt.internal;
import org.bouncycastle.bcpg.ArmoredInputStream;
import org.bouncycastle.openpgp.*;
import org.bouncycastle.openpgp.operator.PBESecretKeyDecryptor;
import org.bouncycastle.openpgp.operator.bc.BcKeyFingerprintCalculator;
import org.bouncycastle.openpgp.operator.bc.BcPBESecretKeyDecryptorBuilder;
import org.bouncycastle.openpgp.operator.bc.BcPGPDigestCalculatorProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.InputStream;
import java.security.SecureRandom;
import java.util.Iterator;
/**
* Helper class centralizing access to commonly used PGP function by (all) PGP classes
*
* @author iulius
*/
public abstract class BasePGPCommon {
private static final Logger LOGGER = LoggerFactory.getLogger(BasePGPCommon.class);
/**
* A functional interface to find the correct PGP key
*
* @param should be PGPPublicKey or PGPSecretKey
*/
protected interface KeyFilter {
/**
*
* @param pgpKey
* the PGP key to check
* @return true if the PGP key matches the selection criteria
*/
boolean accept(T pgpKey);
}
private boolean unlimitedEncryptionStrength = false;
private int compressionAlgorithm = AlgorithmSelection.getDefaultCompressionAlgorithm();
protected BasePGPCommon() {
}
/**
* accessor to the compression algorithm
*
* @return the compression algorithm to use
*/
protected int getCompressionAlgorithm() {
return compressionAlgorithm;
}
/**
* set the compression algorithm
*
* @param compressionAlgorithm
* the compression algorithm constant
*/
public void setCompressionAlgorithm(int compressionAlgorithm) {
this.compressionAlgorithm = compressionAlgorithm;
}
/**
* retrieve the appropriate secret key from the secret key ring collection
* based on the key filter
*
* @param secretKeyRingCollection
* the PGP secret key ring collection
* @param keyFilter
* the key filter to apply
* @return the secret key or null if none matches the filter
* @throws PGPException
*/
protected PGPSecretKey retrieveSecretKey(PGPSecretKeyRingCollection secretKeyRingCollection, KeyFilter keyFilter) throws PGPException {
LOGGER.trace("retrieveSecretKey(PGPSecretKeyRingCollection, KeyFilter)");
LOGGER.trace("Secret KeyRing Collection: {}, Key Filter: {}", secretKeyRingCollection == null ? "not set" : "set", keyFilter == null ? "not set" : "set");
PGPSecretKey result = null;
Iterator secretKeyRingIterator = secretKeyRingCollection.getKeyRings();
PGPSecretKeyRing secretKeyRing = null;
LOGGER.debug("Iterating secret key ring");
while( result == null && secretKeyRingIterator.hasNext() ) {
secretKeyRing = secretKeyRingIterator.next();
Iterator secretKeyIterator = secretKeyRing.getSecretKeys();
LOGGER.debug("Iterating secret keys in key ring");
while( secretKeyIterator.hasNext() ) {
PGPSecretKey secretKey = secretKeyIterator.next();
LOGGER.info("Found secret key: {}", secretKey.getKeyID());
LOGGER.debug("Checking secret key with filter");
if (keyFilter.accept(secretKey)) {
LOGGER.info("Key {} selected from secret key ring");
result = secretKey;
}
}
}
return result;
}
/**
* helper method to read the secret key
*
* @param secretKey
* the secret key stream
* @param userId
* the user id
* @return the applicable secret key or null if none is part of the stream for the user id
* @throws IOException
* @throws PGPException
*/
protected PGPSecretKey findSecretKey(InputStream secretKey, final String userId) throws IOException, PGPException {
LOGGER.trace("findSecretKey(InputStream, String)");
LOGGER.trace("Secret Key: {}, User ID: {}", secretKey == null ? "not set" : "set", userId);
return findSecretKey(secretKey, new KeyFilter() {
@Override
public boolean accept(PGPSecretKey secretKey) {
boolean result = false;
Iterator userIdIterator = secretKey.getUserIDs();
while( userIdIterator.hasNext() && !result) {
result |= userId.equals(userIdIterator.next());
}
return result;
}
});
}
/**
* helper method to read a specific secret key
*
* @param secretKey
* the secret key stream
* @param keyId
* the key id
* @return the applicable secret key or null if none is part of the stream for the key id
* @throws IOException
* @throws PGPException
*/
protected PGPSecretKey findSecretKey(InputStream secretKey, final long keyId) throws IOException, PGPException {
LOGGER.trace("findSecretKey(InputStream, long)");
LOGGER.trace("Secret Key: {}, Key ID: {}", secretKey == null ? "not set" : "set", keyId);
return findSecretKey(secretKey, new KeyFilter() {
@Override
public boolean accept(PGPSecretKey secretKey) {
return secretKey.getKeyID() == keyId;
}
});
}
/**
* reads the given secret key and applies the provided key filter
*
* @param secretKey
* the secret key stream
* @param keyFilter
* the filter to apply on the stream
* @return the secret key or null if none matches the filter acceptance criteria
* @throws IOException
* @throws PGPException
*/
protected PGPSecretKey findSecretKey(InputStream secretKey, KeyFilter keyFilter) throws IOException, PGPException {
LOGGER.trace("findSecretKey(InputStream, KeyFilter)");
PGPSecretKey result = null;
LOGGER.debug("Wrapping secret key stream in ArmoredInputStream");
try( InputStream armoredSecretKey = new ArmoredInputStream(secretKey) ) {
LOGGER.debug("Creating PGPSecretKeyRingCollection");
PGPSecretKeyRingCollection keyRingCollection = new PGPSecretKeyRingCollection(armoredSecretKey, new BcKeyFingerprintCalculator());
result = retrieveSecretKey(keyRingCollection, keyFilter);
}
return result;
}
/**
* read a private key and unlock it with the given password
*
* @param secretKey
* the secret key stream
* @param userId
* the required user id
* @param password
* the password to unlock the private key
* @return the applicable private key or null if none is found
* @throws PGPException
* @throws IOException
*/
protected PGPPrivateKey findPrivateKey(InputStream secretKey, final String userId, String password) throws PGPException, IOException {
LOGGER.trace("findPrivateKey(InputStream, String, String)");
LOGGER.trace("Secret Key: {}, User ID: {}, Password: {}", secretKey == null ? "not set" : "set", userId, password == null ? "not set" : "********");
return findPrivateKey(secretKey, password, new KeyFilter() {
@Override
public boolean accept(PGPSecretKey secretKey) {
boolean result = false;
Iterator userIdIterator = secretKey.getUserIDs();
while (!result && userIdIterator.hasNext()) {
result = userId.equals(userIdIterator.next());
}
return result;
}
});
}
/**
* read a private key and unlock it with the given password
*
* @param secretKey
* the secret key stream
* @param keyId
* the required key id
* @param password
* the password to unlock the private key
* @return the applicable private key or null if none is found
* @throws PGPException
* @throws IOException
*/
protected PGPPrivateKey findPrivateKey(InputStream secretKey, final long keyId, String password) throws PGPException, IOException {
LOGGER.trace("findPrivateKey(InputStream, long, String)");
LOGGER.trace("Secret Key: {}, Key ID: {}, Password: {}", secretKey == null ? "not set" : "set", keyId, password == null ? "not set" : "********");
return findPrivateKey(secretKey, password, new KeyFilter() {
@Override
public boolean accept(PGPSecretKey secretKey) {
return secretKey.getKeyID() == keyId;
}
});
}
/**
* read a private key and unlock it with the given password
*
* @param secretKey
* the secret key stream
* @param password
* the password to use to unlock the private key
* @param keyFilter
* the filter ot find the appropriate key
* @return the appropriate private key or null if none matches the filter
* @throws IOException
* @throws PGPException
*/
protected PGPPrivateKey findPrivateKey(InputStream secretKey, String password, KeyFilter keyFilter) throws IOException, PGPException {
LOGGER.trace("findPrivateKey(InputStream, String, KeyFilter)");
LOGGER.trace("Secret Key: {}, Password: {}, KeyFilter: {}", secretKey == null ? "not set" : "set", password == null ? "not set" : "********", keyFilter == null ? "not set" : "set");
return findPrivateKey(findSecretKey(secretKey, keyFilter), password);
}
/**
* read the private key from the given secret key
*
* @param pgpSecretKey
* the secret key
* @param password
* the password to unlock the private key
* @return the unlocked private key
* @throws PGPException
*/
protected PGPPrivateKey findPrivateKey(PGPSecretKey pgpSecretKey, String password) throws PGPException {
LOGGER.trace("findPrivateKey(PGPSecretKey, String)");
LOGGER.trace("Secret Key: {}, Password: {}", pgpSecretKey == null ? "not set" : "set", password == null ? "not set" : "********");
PGPPrivateKey result = null;
PBESecretKeyDecryptor pbeSecretKeyDecryptor = new BcPBESecretKeyDecryptorBuilder(new BcPGPDigestCalculatorProvider()).build(password.toCharArray());
LOGGER.info("Extracting private key");
result = pgpSecretKey.extractPrivateKey(pbeSecretKeyDecryptor);
if( result == null && LOGGER.isErrorEnabled() ) {
LOGGER.error("No private key could be extracted");
}
return result;
}
/**
* reads the public key from the given stream
*
* @param publicKey
* the input key stream
* @param keyFilter
* the filter to apply
* @return the matching PGP public key
*/
protected PGPPublicKey findPublicKey(InputStream publicKey, KeyFilter keyFilter ) {
LOGGER.trace("findPublicKey(InputStream, KeyFilter)");
LOGGER.trace("Public Key: {}, Key Filter: {}", publicKey == null ? "not set" : "set", keyFilter == null ? "not set" : "set");
return retrievePublicKey(readPublicKeyRing(publicKey), keyFilter);
}
/**
* reads the PGP public key from a PublicKeyRing
*
* @param publicKeyRing
* the source public key ring
* @param keyFilter
* the filter to apply
* @return the matching PGP public or null if none matches
*/
protected PGPPublicKey retrievePublicKey(PGPPublicKeyRing publicKeyRing, KeyFilter keyFilter) {
LOGGER.trace("retrievePublicKey(PGPPublicKeyRing, KeyFilter)");
PGPPublicKey result = null;
Iterator publicKeyIterator = publicKeyRing.getPublicKeys();
LOGGER.debug("Iterating through public keys in public key ring");
while( result == null && publicKeyIterator.hasNext() ) {
PGPPublicKey key = publicKeyIterator.next();
LOGGER.info("Found secret key: {}", key.getKeyID());
LOGGER.debug("Checking public key with filter");
if( keyFilter.accept(key) ) {
LOGGER.info("Public key {} selected from key ring", key.getKeyID());
result = key;
}
}
return result;
}
/**
* reads the public key ring from the input stream
*
* @param publicKey
* the public key stream
* @return the public key ring
*/
protected PGPPublicKeyRing readPublicKeyRing(InputStream publicKey) {
LOGGER.trace("readPublicKeyRing(InputStream)");
PGPPublicKeyRing result = null;
LOGGER.debug("Wrapping public key stream in decoder stream");
try( InputStream decoderStream = PGPUtil.getDecoderStream(publicKey) ) {
LOGGER.debug("Creating PGP Object Factory");
PGPObjectFactory pgpObjectFactory = new PGPObjectFactory(decoderStream, new BcKeyFingerprintCalculator());
Object o = null;
LOGGER.debug("Looking up PGP Public KeyRing");
while( (o = pgpObjectFactory.nextObject()) != null && result == null ) {
if( o instanceof PGPPublicKeyRing ) {
LOGGER.info("PGP Public KeyRing retrieved");
result = (PGPPublicKeyRing)o;
}
}
} catch (IOException e) {
LOGGER.error("{}", e.getMessage());
}
return result;
}
/**
* accessor to the secure random generator
*
* @return the secure random generator
*/
protected SecureRandom getSecureRandom() {
return new SecureRandom();
}
/**
* setter for the unlimited strength encryption flag
*
* @param unlimitedEncryptionStrength
*/
public void setUnlimitedEncryptionStrength(boolean unlimitedEncryptionStrength) {
this.unlimitedEncryptionStrength = unlimitedEncryptionStrength;
}
/**
* the accessor of the unlimited encryption strength
*
* @return the value of the flag
*/
protected boolean isUnlimitedEncryptionStrength() {
return unlimitedEncryptionStrength;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy