I’ve been working with the Bouncy Castle library for encrypting and decrypting my data using a subkey (designated as E) for encryption. However, I have a few specific concerns that I’d like some clarification on:
Relationship Between Subkey and Master Key: I understand that the subkey and the master key are linked by a binding signature. Could someone explain how this binding actually works? What is the underlying mechanism that ensures this link between the two keys?
Encrypting a File with a Subkey: I attempted to encrypt a file using the subkey associated with a public key. My goal was to specify the recipient’s email address ([email protected]) during the encryption process. However, I’m struggling to find a method to include the recipient’s email in the encryption workflow. Could anyone provide guidance or example code on how to achieve this?
I’ll include the relevant portions of my code below, and I would greatly appreciate any assistance or insights you can offer.
Thank you in advance for your help!
public static PGPPublicKey readPublicKey(final String path) throws Exception {
try (InputStream in = new BufferedInputStream(new FileInputStream(path))) {
PGPPublicKeyRingCollection pgpPub = new PGPPublicKeyRingCollection(
PGPUtil.getDecoderStream(in), new JcaKeyFingerprintCalculator());
for (PGPPublicKeyRing keyRing : pgpPub) {
// Get the primary (master) key which contains the user IDs
PGPPublicKey primaryKey = keyRing.getPublicKey();
Iterator<String> userIDs = primaryKey.getUserIDs();
while (userIDs.hasNext()) {
System.out.println("Recipient user ID: " + userIDs.next());
}
// Now, if you want to use a sub key for encryption (if available)
for (PGPPublicKey key : keyRing) {
if (!key.isMasterKey() && key.isEncryptionKey()) {
// Use this sub key for encryption if desired
return key;
}
}
}
throw new IllegalArgumentException("No suitable encryption key found in the public key file. Ensure the key is not a master key and is intended for encryption.");
}
}
Encryption
public static void encryptFile(String outputFileName, String inputFileName, PGPPublicKey encKey, boolean armor, boolean withIntegrityCheck)
throws IOException, PGPException {
// Use try-with-resources to automatically close streams
try (OutputStream out = new BufferedOutputStream(new FileOutputStream(outputFileName));
OutputStream encOut = armor ? new ArmoredOutputStream(out) : out) {
// Set up the encrypted data generator with AES-256 encryption
PGPEncryptedDataGenerator encGen = new PGPEncryptedDataGenerator(
new JcePGPDataEncryptorBuilder(PGPEncryptedData.AES_256)
.setWithIntegrityPacket(withIntegrityCheck)
.setSecureRandom(new SecureRandom())
.setProvider("BC"));
encGen.addMethod(new JcePublicKeyKeyEncryptionMethodGenerator(encKey)
.setProvider("BC"));
// Compress the file using gzip
Path tempGzipFile = Files.createTempFile("temp", ".gz");
try (InputStream in = new BufferedInputStream(new FileInputStream(inputFileName));
OutputStream gzipOut = new GZIPOutputStream(Files.newOutputStream(tempGzipFile))) {
byte[] buf = new byte[4096];
int len;
while ((len = in.read(buf)) > 0) {
gzipOut.write(buf, 0, len);
}
}
// Open encryption stream and write literal data to a temporary file
Path tempEncFile = Files.createTempFile("temp_enc", ".gpg");
try (OutputStream cOut = encGen.open(Files.newOutputStream(tempEncFile), new byte[4096]);
InputStream in = new BufferedInputStream(Files.newInputStream(tempGzipFile))) {
PGPLiteralDataGenerator lData = new PGPLiteralDataGenerator();
// Use only the file name (not the full path) in the literal data packet
try (OutputStream pOut = lData.open(cOut, PGPLiteralData.BINARY, tempGzipFile.getFileName().toString(), new Date(), new byte[4096])) {
byte[] buf = new byte[4096];
int len;
while ((len = in.read(buf)) > 0) {
pOut.write(buf, 0, len);
}
}
}
// Read from the temporary encrypted file and write to the final output file
try (InputStream tempEncIn = Files.newInputStream(tempEncFile);
OutputStream finalOut = new BufferedOutputStream(new FileOutputStream(outputFileName))) {
byte[] buf = new byte[4096];
int len;
while ((len = tempEncIn.read(buf)) > 0) {
finalOut.write(buf, 0, len);
}
}
// Delete the temporary files
Files.delete(tempGzipFile);
Files.delete(tempEncFile);
}
}
Please help me add the recipient to the encryption process.