Te sugerimos que pruebes esta respuesta en un entorno controlado antes de pasarlo a producción, saludos.
Solución:
Si alguien está interesado en saber cómo cifrar y descifrar archivos gpg utilizando la biblioteca openPGP del castillo hinchable, consulte el siguiente código java:
Los siguientes son los 4 métodos que necesitará:
El siguiente método leerá e importará su secreto key del archivo .asc:
public static PGPSecretKey readSecretKeyFromCol(InputStream in, long keyId) throws IOException, PGPException
in = PGPUtil.getDecoderStream(in);
PGPSecretKeyRingCollection pgpSec = new PGPSecretKeyRingCollection(in, new BcKeyFingerprintCalculator());
PGPSecretKey key = pgpSec.getSecretKey(keyId);
if (key == null)
throw new IllegalArgumentException("Can't find encryption key in key ring.");
return key;
El siguiente método leerá e importará su público key del archivo .asc:
@SuppressWarnings("rawtypes")
public static PGPPublicKey readPublicKeyFromCol(InputStream in) throws IOException, PGPException
in = PGPUtil.getDecoderStream(in);
PGPPublicKeyRingCollection pgpPub = new PGPPublicKeyRingCollection(in, new BcKeyFingerprintCalculator());
PGPPublicKey key = null;
Iterator rIt = pgpPub.getKeyRings();
while (key == null && rIt.hasNext())
PGPPublicKeyRing kRing = (PGPPublicKeyRing) rIt.next();
Iterator kIt = kRing.getPublicKeys();
while (key == null && kIt.hasNext())
PGPPublicKey k = (PGPPublicKey) kIt.next();
if (k.isEncryptionKey())
key = k;
if (key == null)
throw new IllegalArgumentException("Can't find encryption key in key ring.");
return key;
Los siguientes 2 métodos para descifrar y cifrar archivos gpg:
public void decryptFile(InputStream in, InputStream secKeyIn, InputStream pubKeyIn, char[] pass) throws IOException, PGPException, InvalidCipherTextException
Security.addProvider(new BouncyCastleProvider());
PGPPublicKey pubKey = readPublicKeyFromCol(pubKeyIn);
PGPSecretKey secKey = readSecretKeyFromCol(secKeyIn, pubKey.getKeyID());
in = PGPUtil.getDecoderStream(in);
JcaPGPObjectFactory pgpFact;
PGPObjectFactory pgpF = new PGPObjectFactory(in, new BcKeyFingerprintCalculator());
Object o = pgpF.nextObject();
PGPEncryptedDataList encList;
if (o instanceof PGPEncryptedDataList)
encList = (PGPEncryptedDataList) o;
else
encList = (PGPEncryptedDataList) pgpF.nextObject();
Iterator itt = encList.getEncryptedDataObjects();
PGPPrivateKey sKey = null;
PGPPublicKeyEncryptedData encP = null;
while (sKey == null && itt.hasNext())
encP = itt.next();
secKey = readSecretKeyFromCol(new FileInputStream("PrivateKey.asc"), encP.getKeyID());
sKey = secKey.extractPrivateKey(new BcPBESecretKeyDecryptorBuilder(new BcPGPDigestCalculatorProvider()).build(pass));
if (sKey == null)
throw new IllegalArgumentException("Secret key for message not found.");
InputStream clear = encP.getDataStream(new BcPublicKeyDataDecryptorFactory(sKey));
pgpFact = new JcaPGPObjectFactory(clear);
PGPCompressedData c1 = (PGPCompressedData) pgpFact.nextObject();
pgpFact = new JcaPGPObjectFactory(c1.getDataStream());
PGPLiteralData ld = (PGPLiteralData) pgpFact.nextObject();
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
InputStream inLd = ld.getDataStream();
int ch;
while ((ch = inLd.read()) >= 0)
bOut.write(ch);
//System.out.println(bOut.toString());
bOut.writeTo(new FileOutputStream(ld.getFileName()));
//return bOut;
public static void encryptFile(OutputStream out, String fileName, PGPPublicKey encKey) throws IOException, NoSuchProviderException, PGPException
Security.addProvider(new BouncyCastleProvider());
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
PGPCompressedDataGenerator comData = new PGPCompressedDataGenerator(PGPCompressedData.ZIP);
PGPUtil.writeFileToLiteralData(comData.open(bOut), PGPLiteralData.BINARY, new File(fileName));
comData.close();
PGPEncryptedDataGenerator cPk = new PGPEncryptedDataGenerator(new BcPGPDataEncryptorBuilder(SymmetricKeyAlgorithmTags.TRIPLE_DES).setSecureRandom(new SecureRandom()));
cPk.addMethod(new BcPublicKeyKeyEncryptionMethodGenerator(encKey));
byte[] bytes = bOut.toByteArray();
OutputStream cOut = cPk.open(out, bytes.length);
cOut.write(bytes);
cOut.close();
out.close();
Ahora aquí está cómo invocar/ejecutar lo anterior:
try
decryptFile(new FileInputStream("encryptedFile.gpg"), new FileInputStream("PrivateKey.asc"), new FileInputStream("PublicKey.asc"), "yourKeyPassword".toCharArray());
PGPPublicKey pubKey = readPublicKeyFromCol(new FileInputStream("PublicKey.asc"));
encryptFile(new FileOutputStream("encryptedFileOutput.gpg"), "fileToEncrypt.txt", pubKey);
catch (PGPException e)
fail("exception: " + e.getMessage(), e.getUnderlyingException());
Decidí ir con un enfoque muy diferente, que es renunciar por completo al uso del castillo hinchable y simplemente usar un proceso de tiempo de ejecución en su lugar. Para mí, esta solución funciona y elimina por completo la complejidad que rodea al castillo hinchable:
String[] gpgCommands = new String[]
"gpg",
"--passphrase",
"password",
"--decrypt",
"test-files/accounts.txt.gpg"
;
Process gpgProcess = Runtime.getRuntime().exec(gpgCommands);
BufferedReader gpgOutput = new BufferedReader(new InputStreamReader(gpgProcess.getInputStream()));
BufferedReader gpgError = new BufferedReader(new InputStreamReader(gpgProcess.getErrorStream()));
Después de hacer eso, debe recordar drenar su flujo de entrada a medida que su proceso se está ejecutando o su programa probablemente se bloqueará dependiendo de cuánto esté generando. Vea mi respuesta en este hilo (y también la de Cameron Skinner y Matthew Wilson, quienes me guiaron por el camino correcto) para obtener un poco más de contexto: llamar a GnuPG en Java a través de un proceso de tiempo de ejecución para cifrar y descifrar archivos: el descifrado siempre se bloquea
Para cualquiera que busque una solución alternativa, consulte https://stackoverflow.com/a/42176529/7550201
final InputStream plaintextStream = BouncyGPG
.decryptAndVerifyStream()
.withConfig(keyringConfig)
.andRequireSignatureFromAllKeys("[email protected]")
.fromEncryptedInputStream(cipherTextStream)
Para resumir: la programación de Bouncycastle es a menudo una gran cantidad de programación de culto de carga y escribí una biblioteca para cambiar eso.