Мы используем библиотеки Bouncy Castle Java для расшифровки PGP, и все работало хорошо, пока мы не достигли точки, где нам пришлось расшифровывать файл со следующими атрибутами (фрагмент из pgpdump <filename>
output)
> pgpdump file-name.csv.pgp
New: Symmetric-Key Encrypted Session Key Packet(tag 3)(29 bytes)
New version(4)
Sym alg - CAST5(sym 3)
Salted string-to-key(s2k 1):
Hash alg - SHA1(hash 2)
Salt - c3 89 7b 22 c0 90 a2 1f
Encrypted session key
-> sym alg(1 bytes) + session key
New: Public-Key Encrypted Session Key Packet(tag 1)(268 bytes)
New version(3)
Key ID - 0x00FB426B9D39D2D9
Pub alg - RSA Encrypt or Sign(pub 1)
RSA m^e mod n(2048 bits) - ...
-> m = sym alg(1 byte) + checksum(2 bytes) + PKCS-1 block type 02
New: Public-Key Encrypted Session Key Packet(tag 1)(268 bytes)
New version(3)
Key ID - 0x13BCC3DF42A3585C
Pub alg - RSA Encrypt or Sign(pub 1)
RSA m^e mod n(2048 bits) - ...
-> m = sym alg(1 byte) + checksum(2 bytes) + PKCS-1 block type 02
New: Symmetrically Encrypted and MDC Packet(tag 18)(8192 bytes) partial start
Ver 1
Encrypted data [sym alg is specified in pub-key encrypted session key]
(plain text + MDC SHA1(20 bytes))
Я могу расшифровать файл на моей ма c, используя
gpg --passphrase <passphrase> -v -d --pinentry-mode=loopback -o foo.out
Используя java код ниже на основе примера BouncyCastle , я заканчиваю org.bouncycastle.openpgp.PGPException: Exception creating cipher CAST5
.
public static byte[] decrypt(
byte[] encrypted,
char[] passPhrase)
throws IOException, PGPException, NoSuchProviderException
{
InputStream in = new ByteArrayInputStream(encrypted);
in = PGPUtil.getDecoderStream(in);
PGPObjectFactory pgpF = new PGPObjectFactory(in);
PGPEncryptedDataList enc;
Object o = pgpF.nextObject();
//
// the first object might be a PGP marker packet.
//
if (o instanceof PGPEncryptedDataList)
{
enc = (PGPEncryptedDataList)o;
}
else
{
enc = (PGPEncryptedDataList)pgpF.nextObject();
}
PGPPBEEncryptedData pbe = (PGPPBEEncryptedData)enc.get(0);
//****************************************
// Hitting an exception here while doing pbe.getDataStream()...
// Getting "org.bouncycastle.openpgp.PGPException: Exception creating cipher CAST5"
//****************************************
InputStream clear = pbe.getDataStream(new JcePBEDataDecryptorFactoryBuilder(new JcaPGPDigestCalculatorProviderBuilder().setProvider("BC").build()).setProvider("BC").build(passPhrase));
PGPObjectFactory pgpFact = new PGPObjectFactory(clear);
PGPCompressedData cData = (PGPCompressedData)pgpFact.nextObject();
pgpFact = new PGPObjectFactory(cData.getDataStream());
PGPLiteralData ld = (PGPLiteralData)pgpFact.nextObject();
return Streams.readAll(ld.getInputStream());
}
Информация об исключении -
org.bouncycastle.openpgp.PGPException: Exception creating cipher
at org.bouncycastle.openpgp.operator.jcajce.OperatorHelper.createDataDecryptor(Unknown Source)
at org.bouncycastle.openpgp.operator.jcajce.JcePBEDataDecryptorFactoryBuilder$1.createDataDecryptor(Unknown Source)
at org.bouncycastle.openpgp.PGPPBEEncryptedData.getDataStream(Unknown Source)
...
...
Caused by: java.lang.IllegalArgumentException: unknown symmetric algorithm: 112
at org.bouncycastle.openpgp.PGPUtil.getSymmetricCipherName(Unknown Source)
... 21 more
Я попытался запустить Security.getAlgorithms("Cipher")
, как предлагается здесь , и я не вижу CAST5 в списке возвращаемых алгоритмов.
Я нахожусь на Java 1.8 и использую библиотеки Bouncy Castle ниже
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.62</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpg-jdk15on</artifactId>
<version>1.62</version>
<scope>compile</scope>
</dependency>
Любые идеи, что я должен преследовать дальше? Я также убедился, что мой код устанавливает Security.addProvider(new BouncyCastleProvider());
во время запуска.
Я чувствую, что это должно быть вопросом дополнительной поддержки JVM Ciper Suites. Но я не знаю с чего начать.
Пожалуйста, совет.
ПРИМЕЧАНИЕ: Приведенный выше код был примером из inte rnet, но, основываясь на комментариях Мартена Бодьюса, я понял, скопировав это код из inte rnet локально - я сделал много изменений, чтобы заставить его работать.
Точный код, который я использую с моей машины
public static void decryptSymmetricFile(
InputStream in,
char[] passwd,
String outFileName) throws IOException {
in = PGPUtil.getDecoderStream(in);
PGPObjectFactory pgpF = new JcaPGPObjectFactory(in);
PGPEncryptedDataList enc;
Object o = pgpF.nextObject();
if (o instanceof PGPEncryptedDataList) {
enc = (PGPEncryptedDataList) o;
} else {
enc = (PGPEncryptedDataList) pgpF.nextObject();
}
Iterator<?> it = enc.getEncryptedDataObjects();
PGPPBEEncryptedData pbe = (PGPPBEEncryptedData) it.next();
try {
Security.getAlgorithms("Cipher");
//****************************************
// Hitting an exception here while doing pbe.getDataStream()...
// Getting "org.bouncycastle.openpgp.PGPException: Exception creating cipher CAST5"
//****************************************
InputStream dataStream = pbe.getDataStream((new JcePBEDataDecryptorFactoryBuilder((new JcaPGPDigestCalculatorProviderBuilder()).setProvider("BC").build())).setProvider("BC").build(passwd));
JcaPGPObjectFactory pgpObjectFactory = new JcaPGPObjectFactory(dataStream);
PGPCompressedData pgpCompressedData = (PGPCompressedData) pgpObjectFactory.nextObject();
pgpObjectFactory = new JcaPGPObjectFactory(pgpCompressedData.getDataStream());
PGPLiteralData literalData = (PGPLiteralData) pgpObjectFactory.nextObject();
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
InputStream unc = literalData.getInputStream();
int ch;
while ((ch = unc.read()) >= 0)
{
bOut.write(ch);
}
if (pbe.isIntegrityProtected() && !pbe.verify())
{
throw new PGPException("Data is integrity protected but integrity is lost.");
}
OutputStream fOut = new BufferedOutputStream(new FileOutputStream(outFileName));
Streams.pipeAll(new ByteArrayInputStream(bOut.toByteArray()), fOut);
fOut.close();
} catch (Exception ex) {
ex.printStackTrace();
logger.error(ex.getLocalizedMessage());
}
}