我目前正在使用 PgPEncryptionService 并成功地使用我的公钥加密文件。我面临的问题是解密。
我目前在为我的解密方法运行测试用例时收到此错误。
[main] INFO com.rxbenefits.service.impl.PGPEncryptionService - Secret key algorithm: 9
org.bouncycastle.openpgp.PGPException: unknown hash algorithm: 8
at org.bouncycastle.openpgp.PGPUtil.getS2kDigestName(Unknown Source)
at org.bouncycastle.openpgp.PGPUtil.makeKeyFromPassPhrase(Unknown Source)
at org.bouncycastle.openpgp.PGPSecretKey.extractKeyData(Unknown Source)
at org.bouncycastle.openpgp.PGPSecretKey.extractPrivateKey(Unknown Source)
at org.bouncycastle.openpgp.PGPSecretKey.extractPrivateKey(Unknown Source)
at com.rxbenefits.service.impl.PGPEncryptionService.findSecretKey(PGPEncryptionService.java:102)
at com.rxbenefits.service.impl.PGPEncryptionService.decryptFile(PGPEncryptionService.java:132)
at com.rxbenefits.service.impl.PGPEncryptionServiceTest.testFileEncryption(PGPEncryptionServiceTest.java:55)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.mockito.internal.runners.DefaultInternalRunner$1$1.evaluate(DefaultInternalRunner.java:54)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
在调试中运行时,我可以看到值通过正常......我在算法 9 的调试器中唯一能找到的就是下图所示的
总之。我不知道自己做错了什么。我自己生成了这些密钥,并且能够使用 pub 密钥进行加密……但由于某种原因,解密让我很头疼。以下是我用来解密的两种方法。
这是解密方法
/**
* decrypt the passed in message stream
*/
@SuppressWarnings("unchecked")
public static void decryptFile(InputStream in, OutputStream out, InputStream keyIn, char[] passwd) throws Exception
{
Security.addProvider(new BouncyCastleProvider());
in = org.bouncycastle.openpgp.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();
}
// find the secret key
Iterator<PGPPublicKeyEncryptedData> it = enc.getEncryptedDataObjects();
PGPPrivateKey sKey = null;
PGPPublicKeyEncryptedData pbe = null;
while (sKey == null && it.hasNext())
{
pbe = it.next();
sKey = findSecretKey(keyIn, pbe.getKeyID(), passwd);
}
if (sKey == null)
{
throw new IllegalArgumentException("Secret key for message not found.");
}
InputStream clear = pbe.getDataStream(sKey, "BC");
PGPObjectFactory plainFact = new PGPObjectFactory(clear);
Object message = plainFact.nextObject();
PGPObjectFactory pgpFact = null;
if (message instanceof PGPCompressedData)
{
PGPCompressedData cData = (PGPCompressedData) message;
pgpFact = new PGPObjectFactory(cData.getDataStream());
message = pgpFact.nextObject();
}
if (message instanceof PGPLiteralData)
{
PGPLiteralData ld = (PGPLiteralData) message;
InputStream unc = ld.getInputStream();
int ch;
while ((ch = unc.read()) >= 0)
{
out.write(ch);
}
}
else if (message instanceof PGPOnePassSignatureList)
{
PGPOnePassSignatureList p1 = (PGPOnePassSignatureList) message;
PGPOnePassSignature ops = p1.get(0);
PGPLiteralData ld = (PGPLiteralData) pgpFact.nextObject();
InputStream unc = ld.getInputStream();
int ch;
while ((ch = unc.read()) >= 0)
{
out.write(ch);
}
}
else
{
throw new PGPException("Message is not a simple encrypted file - type unknown.");
}
if (pbe.isIntegrityProtected())
{
if (!pbe.verify())
{
throw new PGPException("Message failed integrity check");
}
}
}
这是用来获取密钥的方法
private static PGPPrivateKey findSecretKey(InputStream keyIn, long keyID, char[] pass) throws IOException, PGPException, NoSuchProviderException {
PGPSecretKeyRingCollection pgpSec = new PGPSecretKeyRingCollection(org.bouncycastle.openpgp.PGPUtil.getDecoderStream(keyIn));
PGPSecretKey pgpSecKey = pgpSec.getSecretKey(keyID);
if (pgpSecKey == null) {
return null;
}
log.info("Secret key algorithm: " + pgpSecKey.getKeyEncryptionAlgorithm());
return pgpSecKey.extractPrivateKey(pass, "BC");
}
这是我对以上内容的单元测试
@Test
public void testFileEncryption() throws Exception {
// create unencrypted file
String tempPath = "temp";
FileRepo fileRepo = new FileRepo();
fileRepo.setEncryptionKeyNo(123L);
// Create the unencrypted file
File unencryptedFile = new File("unencrypted.txt");
try (PrintWriter writer = new PrintWriter(unencryptedFile)) {
writer.println("Hello, world!");
}
// Encrypt the file
File encryptedFile = new File(tempPath + unencryptedFile.getName() + ".pgp");
File encryptedResult = new File("encrypted.txt");
try (OutputStream out = new DataOutputStream(new FileOutputStream(encryptedFile));
FileInputStream publicKeyStream = new FileInputStream(publicKey)) {
encryptFile(out, unencryptedFile.getPath(), readPublicKey(publicKeyStream), false, true);
try (InputStream in = new FileInputStream(encryptedFile);
OutputStream outResult = new FileOutputStream(encryptedResult);
FileInputStream privateKeyStream = new FileInputStream(secretKey)) {
// Decrypt the encrypted file
decryptFile(in, outResult, privateKeyStream, passPhrase);
}
}
// Check that the decrypted file matches the original unencrypted file
try (BufferedReader reader1 = new BufferedReader(new FileReader(unencryptedFile));
BufferedReader reader2 = new BufferedReader(new FileReader(encryptedResult))) {
String line1 = reader1.readLine();
String line2 = reader2.readLine();
while (line1 != null && line2 != null) {
assertEquals(line1, line2);
line1 = reader1.readLine();
line2 = reader2.readLine();
}
assertNull(line1);
assertNull(line2);
}
// Clean up the files
unencryptedFile.delete();
encryptedFile.delete();
encryptedResult.delete();
}
findSecretKey 方法是我收到错误的方法。特别是当它返回 pgpSecKey.extractPrivateKey 时。
我认为是问题所在:
密码错误。 (事实并非如此。我创建了 4 个不同的密钥对,密码为 12345,但均无效)
更改加密时使用的算法。 (现在使用 AES_256,错误仍然存在)