diff --git a/PgpCore/CompositeDisposable.cs b/PgpCore/CompositeDisposable.cs
new file mode 100644
index 0000000..8045816
--- /dev/null
+++ b/PgpCore/CompositeDisposable.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Collections.Concurrent;
+
+namespace PgpCore
+{
+ ///
+ /// Simplified adaptation from System.Reactive.
+ ///
+ internal sealed class CompositeDisposable : IDisposable
+ {
+ private readonly ConcurrentQueue _disposables = new ConcurrentQueue();
+
+ public void Add(IDisposable disposable)
+ {
+ if (disposable == null)
+ throw new ArgumentNullException(nameof(disposable));
+
+ _disposables.Enqueue(disposable);
+ }
+
+ public void Dispose()
+ {
+ while (_disposables.TryDequeue(out IDisposable disposable))
+ disposable.Dispose();
+ }
+ }
+}
diff --git a/PgpCore/DisposableExtensions.cs b/PgpCore/DisposableExtensions.cs
new file mode 100644
index 0000000..cb8fd51
--- /dev/null
+++ b/PgpCore/DisposableExtensions.cs
@@ -0,0 +1,22 @@
+using System;
+
+namespace PgpCore
+{
+ internal static class DisposableExtensions
+ {
+ ///
+ /// Adapted from ReactiveUI.
+ ///
+ public static T DisposeWith(this T @this, CompositeDisposable disposables)
+ where T : IDisposable
+ {
+ if (@this == null)
+ throw new ArgumentNullException(nameof(@this));
+ if (disposables == null)
+ throw new ArgumentNullException(nameof(disposables));
+
+ disposables.Add(@this);
+ return @this;
+ }
+ }
+}
diff --git a/PgpCore/PGP.cs b/PgpCore/PGP.cs
index 82fc822..6d21b5a 100644
--- a/PgpCore/PGP.cs
+++ b/PgpCore/PGP.cs
@@ -5001,81 +5001,76 @@ private async Task DecryptAsync(Stream inputStream, Stream outputStream)
if (enc == null && message == null)
throw new ArgumentException("Failed to detect encrypted content format.", nameof(inputStream));
- // decrypt
- PgpPrivateKey privateKey = null;
- PgpPublicKeyEncryptedData pbe = null;
- if (enc != null)
+ using (CompositeDisposable disposables = new CompositeDisposable())
{
- foreach (PgpPublicKeyEncryptedData publicKeyEncryptedData in enc.GetEncryptedDataObjects())
+ // decrypt
+ PgpPrivateKey privateKey = null;
+ PgpPublicKeyEncryptedData pbe = null;
+ if (enc != null)
{
- privateKey = EncryptionKeys.FindSecretKey(publicKeyEncryptedData.KeyId);
-
- if (privateKey != null)
+ foreach (PgpPublicKeyEncryptedData publicKeyEncryptedData in enc.GetEncryptedDataObjects())
{
- pbe = publicKeyEncryptedData;
- break;
- }
- }
-
- if (privateKey == null)
- throw new ArgumentException("Secret key for message not found.");
+ privateKey = EncryptionKeys.FindSecretKey(publicKeyEncryptedData.KeyId);
- PgpObjectFactory plainFact;
+ if (privateKey != null)
+ {
+ pbe = publicKeyEncryptedData;
+ break;
+ }
+ }
- using (Stream clear = pbe.GetDataStream(privateKey))
- {
- plainFact = new PgpObjectFactory(clear);
- }
+ if (privateKey == null)
+ throw new ArgumentException("Secret key for message not found.");
- message = plainFact.NextPgpObject();
+ Stream clear = pbe.GetDataStream(privateKey).DisposeWith(disposables);
+ PgpObjectFactory plainFact = new PgpObjectFactory(clear);
- if (message is PgpOnePassSignatureList)
- {
message = plainFact.NextPgpObject();
- }
- }
-
- if (message is PgpCompressedData pgpCompressedData)
- {
- PgpObjectFactory objectFactory;
- using (Stream compDataIn = pgpCompressedData.GetDataStream())
- {
- objectFactory = new PgpObjectFactory(compDataIn);
- message = objectFactory.NextPgpObject();
+ if (message is PgpOnePassSignatureList)
+ {
+ message = plainFact.NextPgpObject();
+ }
}
- if (message is PgpOnePassSignatureList)
+ if (message is PgpCompressedData pgpCompressedData)
{
+ Stream compDataIn = pgpCompressedData.GetDataStream().DisposeWith(disposables);
+ PgpObjectFactory objectFactory = new PgpObjectFactory(compDataIn);
message = objectFactory.NextPgpObject();
- var literalData = (PgpLiteralData)message;
- Stream unc = literalData.GetInputStream();
- await Streams.PipeAllAsync(unc, outputStream);
+
+ if (message is PgpOnePassSignatureList)
+ {
+ message = objectFactory.NextPgpObject();
+ var literalData = (PgpLiteralData)message;
+ Stream unc = literalData.GetInputStream();
+ await Streams.PipeAllAsync(unc, outputStream);
+ }
+ else
+ {
+ PgpLiteralData literalData = (PgpLiteralData)message;
+ Stream unc = literalData.GetInputStream();
+ await Streams.PipeAllAsync(unc, outputStream);
+ }
}
- else
+ else if (message is PgpLiteralData literalData)
{
- PgpLiteralData literalData = (PgpLiteralData)message;
Stream unc = literalData.GetInputStream();
await Streams.PipeAllAsync(unc, outputStream);
- }
- }
- else if (message is PgpLiteralData literalData)
- {
- Stream unc = literalData.GetInputStream();
- await Streams.PipeAllAsync(unc, outputStream);
- if (pbe.IsIntegrityProtected())
- {
- if (!pbe.Verify())
+ if (pbe.IsIntegrityProtected())
{
- throw new PgpException("Message failed integrity check.");
+ if (!pbe.Verify())
+ {
+ throw new PgpException("Message failed integrity check.");
+ }
}
}
+ else if (message is PgpOnePassSignatureList)
+ throw new PgpException("Encrypted message contains a signed message - not literal data.");
+ else
+ throw new PgpException("Message is not a simple encrypted file.");
}
- else if (message is PgpOnePassSignatureList)
- throw new PgpException("Encrypted message contains a signed message - not literal data.");
- else
- throw new PgpException("Message is not a simple encrypted file.");
}
#endregion DecryptAsync
@@ -5114,81 +5109,76 @@ private void Decrypt(Stream inputStream, Stream outputStream)
if (enc == null && message == null)
throw new ArgumentException("Failed to detect encrypted content format.", nameof(inputStream));
- // decrypt
- PgpPrivateKey privateKey = null;
- PgpPublicKeyEncryptedData pbe = null;
- if (enc != null)
+ using (CompositeDisposable disposables = new CompositeDisposable())
{
- foreach (PgpPublicKeyEncryptedData publicKeyEncryptedData in enc.GetEncryptedDataObjects())
+ // decrypt
+ PgpPrivateKey privateKey = null;
+ PgpPublicKeyEncryptedData pbe = null;
+ if (enc != null)
{
- privateKey = EncryptionKeys.FindSecretKey(publicKeyEncryptedData.KeyId);
-
- if (privateKey != null)
+ foreach (PgpPublicKeyEncryptedData publicKeyEncryptedData in enc.GetEncryptedDataObjects())
{
- pbe = publicKeyEncryptedData;
- break;
- }
- }
+ privateKey = EncryptionKeys.FindSecretKey(publicKeyEncryptedData.KeyId);
- if (privateKey == null)
- throw new ArgumentException("Secret key for message not found.");
-
- PgpObjectFactory plainFact;
+ if (privateKey != null)
+ {
+ pbe = publicKeyEncryptedData;
+ break;
+ }
+ }
- using (Stream clear = pbe.GetDataStream(privateKey))
- {
- plainFact = new PgpObjectFactory(clear);
- }
+ if (privateKey == null)
+ throw new ArgumentException("Secret key for message not found.");
- message = plainFact.NextPgpObject();
+ Stream clear = pbe.GetDataStream(privateKey).DisposeWith(disposables);
+ PgpObjectFactory plainFact = new PgpObjectFactory(clear);
- if (message is PgpOnePassSignatureList)
- {
message = plainFact.NextPgpObject();
- }
- }
- if (message is PgpCompressedData pgpCompressedData)
- {
- PgpObjectFactory objectFactory;
-
- using (Stream compDataIn = pgpCompressedData.GetDataStream())
- {
- objectFactory = new PgpObjectFactory(compDataIn);
- message = objectFactory.NextPgpObject();
+ if (message is PgpOnePassSignatureList)
+ {
+ message = plainFact.NextPgpObject();
+ }
}
- if (message is PgpOnePassSignatureList)
+ if (message is PgpCompressedData pgpCompressedData)
{
+ Stream compDataIn = pgpCompressedData.GetDataStream().DisposeWith(disposables);
+ PgpObjectFactory objectFactory = new PgpObjectFactory(compDataIn);
message = objectFactory.NextPgpObject();
- PgpLiteralData literalData = (PgpLiteralData)message;
- Stream unc = literalData.GetInputStream();
- Streams.PipeAll(unc, outputStream);
+
+ if (message is PgpOnePassSignatureList)
+ {
+ message = objectFactory.NextPgpObject();
+ PgpLiteralData literalData = (PgpLiteralData)message;
+ Stream unc = literalData.GetInputStream();
+ Streams.PipeAll(unc, outputStream);
+ }
+ else
+ {
+ PgpLiteralData literalData = (PgpLiteralData)message;
+ Stream unc = literalData.GetInputStream();
+ Streams.PipeAll(unc, outputStream);
+ }
}
- else
+ else if (message is PgpLiteralData literalData)
{
- PgpLiteralData literalData = (PgpLiteralData)message;
Stream unc = literalData.GetInputStream();
Streams.PipeAll(unc, outputStream);
- }
- }
- else if (message is PgpLiteralData literalData)
- {
- Stream unc = literalData.GetInputStream();
- Streams.PipeAll(unc, outputStream);
- if (pbe.IsIntegrityProtected())
- {
- if (!pbe.Verify())
+ if (pbe.IsIntegrityProtected())
{
- throw new PgpException("Message failed integrity check.");
+ if (!pbe.Verify())
+ {
+ throw new PgpException("Message failed integrity check.");
+ }
}
}
+ else if (message is PgpOnePassSignatureList)
+ throw new PgpException("Encrypted message contains a signed message - not literal data.");
+ else
+ throw new PgpException("Message is not a simple encrypted file.");
}
- else if (message is PgpOnePassSignatureList)
- throw new PgpException("Encrypted message contains a signed message - not literal data.");
- else
- throw new PgpException("Message is not a simple encrypted file.");
}
#endregion Decrypt
@@ -5221,100 +5211,95 @@ private async Task DecryptAndVerifyAsync(Stream inputStream, Stream outputStream
if (encryptedDataList == null && message == null)
throw new ArgumentException("Failed to detect encrypted content format.", nameof(inputStream));
- // decrypt
- PgpPrivateKey privateKey = null;
- PgpPublicKeyEncryptedData pbe = null;
- if (encryptedDataList != null)
+ using (CompositeDisposable disposables = new CompositeDisposable())
{
- foreach (PgpPublicKeyEncryptedData publicKeyEncryptedData in
- encryptedDataList.GetEncryptedDataObjects())
+ // decrypt
+ PgpPrivateKey privateKey = null;
+ PgpPublicKeyEncryptedData pbe = null;
+ if (encryptedDataList != null)
{
- privateKey = EncryptionKeys.FindSecretKey(publicKeyEncryptedData.KeyId);
-
- if (privateKey != null)
+ foreach (PgpPublicKeyEncryptedData publicKeyEncryptedData in
+ encryptedDataList.GetEncryptedDataObjects())
{
- pbe = publicKeyEncryptedData;
- break;
- }
- }
-
- if (privateKey == null)
- throw new ArgumentException("Secret key for message not found.");
+ privateKey = EncryptionKeys.FindSecretKey(publicKeyEncryptedData.KeyId);
- PgpObjectFactory plainFact;
-
- using (Stream clear = pbe.GetDataStream(privateKey))
- {
- plainFact = new PgpObjectFactory(clear);
- }
-
- message = plainFact.NextPgpObject();
+ if (privateKey != null)
+ {
+ pbe = publicKeyEncryptedData;
+ break;
+ }
+ }
- if (message is PgpOnePassSignatureList pgpOnePassSignatureList)
- {
- PgpOnePassSignature pgpOnePassSignature = pgpOnePassSignatureList[0];
- var keyIdToVerify = pgpOnePassSignature.KeyId;
+ if (privateKey == null)
+ throw new ArgumentException("Secret key for message not found.");
- // var verified = EncryptionKeys.ValidationPublicKey.KeyId == pgpOnePassSignature.KeyId ||
- // EncryptionKeys.ValidationPublicKey.GetKeySignatures().Cast()
- // .Select(x => x.KeyId).Contains(pgpOnePassSignature.KeyId);
- var verified = Utilities.FindPublicKey(keyIdToVerify, EncryptionKeys.VerificationKeys,
- out PgpPublicKey _);
- if (verified == false)
- throw new PgpException("Failed to verify file.");
+ Stream clear = pbe.GetDataStream(privateKey).DisposeWith(disposables);
+ PgpObjectFactory plainFact = new PgpObjectFactory(clear);
message = plainFact.NextPgpObject();
- }
- else if (!(message is PgpCompressedData))
- throw new PgpException("File was not signed.");
- }
- if (message is PgpCompressedData cData)
- {
- PgpObjectFactory objectFactory;
+ if (message is PgpOnePassSignatureList pgpOnePassSignatureList)
+ {
+ PgpOnePassSignature pgpOnePassSignature = pgpOnePassSignatureList[0];
+ var keyIdToVerify = pgpOnePassSignature.KeyId;
+
+ // var verified = EncryptionKeys.ValidationPublicKey.KeyId == pgpOnePassSignature.KeyId ||
+ // EncryptionKeys.ValidationPublicKey.GetKeySignatures().Cast()
+ // .Select(x => x.KeyId).Contains(pgpOnePassSignature.KeyId);
+ var verified = Utilities.FindPublicKey(keyIdToVerify, EncryptionKeys.VerificationKeys,
+ out PgpPublicKey _);
+ if (verified == false)
+ throw new PgpException("Failed to verify file.");
+
+ message = plainFact.NextPgpObject();
+ }
+ else if (!(message is PgpCompressedData))
+ throw new PgpException("File was not signed.");
+ }
- using (Stream compDataIn = cData.GetDataStream())
+ if (message is PgpCompressedData cData)
{
- objectFactory = new PgpObjectFactory(compDataIn);
+ Stream compDataIn = cData.GetDataStream().DisposeWith(disposables);
+ PgpObjectFactory objectFactory = new PgpObjectFactory(compDataIn);
message = objectFactory.NextPgpObject();
- }
- if (message is PgpOnePassSignatureList pgpOnePassSignatureList)
+ if (message is PgpOnePassSignatureList pgpOnePassSignatureList)
+ {
+ PgpOnePassSignature pgpOnePassSignature = pgpOnePassSignatureList[0];
+ var keyIdToVerify = pgpOnePassSignature.KeyId;
+
+ // var verified = EncryptionKeys.ValidationKeys.First().KeyId == pgpOnePassSignature.KeyId || EncryptionKeys.ValidationKeys.First().GetKeySignatures().Cast().Select(x => x.KeyId).Contains(pgpOnePassSignature.KeyId);
+ var verified = Utilities.FindPublicKey(keyIdToVerify, EncryptionKeys.VerificationKeys,
+ out PgpPublicKey _);
+ if (verified == false)
+ throw new PgpException("Failed to verify file.");
+
+ message = objectFactory.NextPgpObject();
+ PgpLiteralData literalData = (PgpLiteralData)message;
+ Stream unc = literalData.GetInputStream();
+ await Streams.PipeAllAsync(unc, outputStream);
+ }
+ else
+ {
+ throw new PgpException("File was not signed.");
+ }
+ }
+ else if (message is PgpLiteralData literalData)
{
- PgpOnePassSignature pgpOnePassSignature = pgpOnePassSignatureList[0];
- var keyIdToVerify = pgpOnePassSignature.KeyId;
-
- // var verified = EncryptionKeys.ValidationKeys.First().KeyId == pgpOnePassSignature.KeyId || EncryptionKeys.ValidationKeys.First().GetKeySignatures().Cast().Select(x => x.KeyId).Contains(pgpOnePassSignature.KeyId);
- var verified = Utilities.FindPublicKey(keyIdToVerify, EncryptionKeys.VerificationKeys,
- out PgpPublicKey _);
- if (verified == false)
- throw new PgpException("Failed to verify file.");
-
- message = objectFactory.NextPgpObject();
- PgpLiteralData literalData = (PgpLiteralData)message;
Stream unc = literalData.GetInputStream();
await Streams.PipeAllAsync(unc, outputStream);
- }
- else
- {
- throw new PgpException("File was not signed.");
- }
- }
- else if (message is PgpLiteralData literalData)
- {
- Stream unc = literalData.GetInputStream();
- await Streams.PipeAllAsync(unc, outputStream);
- if (pbe.IsIntegrityProtected())
- {
- if (!pbe.Verify())
+ if (pbe.IsIntegrityProtected())
{
- throw new PgpException("Message failed integrity check.");
+ if (!pbe.Verify())
+ {
+ throw new PgpException("Message failed integrity check.");
+ }
}
}
+ else
+ throw new PgpException("File was not signed.");
}
- else
- throw new PgpException("File was not signed.");
}
#endregion DecryptAndVerifyAsync
@@ -5347,101 +5332,96 @@ private void DecryptAndVerify(Stream inputStream, Stream outputStream)
if (encryptedDataList == null && message == null)
throw new ArgumentException("Failed to detect encrypted content format.", nameof(inputStream));
- // decrypt
- PgpPrivateKey privateKey = null;
- PgpPublicKeyEncryptedData pbe = null;
- if (encryptedDataList != null)
+ using (CompositeDisposable disposables = new CompositeDisposable())
{
- foreach (PgpPublicKeyEncryptedData publicKeyEncryptedData in
- encryptedDataList.GetEncryptedDataObjects())
+ // decrypt
+ PgpPrivateKey privateKey = null;
+ PgpPublicKeyEncryptedData pbe = null;
+ if (encryptedDataList != null)
{
- privateKey = EncryptionKeys.FindSecretKey(publicKeyEncryptedData.KeyId);
-
- if (privateKey != null)
+ foreach (PgpPublicKeyEncryptedData publicKeyEncryptedData in
+ encryptedDataList.GetEncryptedDataObjects())
{
- pbe = publicKeyEncryptedData;
- break;
- }
- }
-
- if (privateKey == null)
- throw new ArgumentException("Secret key for message not found.");
-
- PgpObjectFactory plainFact;
-
- using (Stream clear = pbe.GetDataStream(privateKey))
- {
- plainFact = new PgpObjectFactory(clear);
- }
+ privateKey = EncryptionKeys.FindSecretKey(publicKeyEncryptedData.KeyId);
- message = plainFact.NextPgpObject();
+ if (privateKey != null)
+ {
+ pbe = publicKeyEncryptedData;
+ break;
+ }
+ }
- if (message is PgpOnePassSignatureList pgpOnePassSignatureList)
- {
- PgpOnePassSignature pgpOnePassSignature = pgpOnePassSignatureList[0];
- var keyIdToVerify = pgpOnePassSignature.KeyId;
+ if (privateKey == null)
+ throw new ArgumentException("Secret key for message not found.");
- // var verified = EncryptionKeys.ValidationPublicKey.KeyId == pgpOnePassSignature.KeyId ||
- // EncryptionKeys.ValidationPublicKey.GetKeySignatures().Cast()
- // .Select(x => x.KeyId).Contains(pgpOnePassSignature.KeyId);
- var verified = Utilities.FindPublicKey(keyIdToVerify, EncryptionKeys.VerificationKeys,
- out PgpPublicKey _);
- if (verified == false)
- throw new PgpException("Failed to verify file.");
+ Stream clear = pbe.GetDataStream(privateKey).DisposeWith(disposables);
+ PgpObjectFactory plainFact = new PgpObjectFactory(clear);
message = plainFact.NextPgpObject();
- }
- else if (!(message is PgpCompressedData))
- throw new PgpException("File was not signed.");
- }
- if (message is PgpCompressedData cData)
- {
- PgpObjectFactory objectFactory;
+ if (message is PgpOnePassSignatureList pgpOnePassSignatureList)
+ {
+ PgpOnePassSignature pgpOnePassSignature = pgpOnePassSignatureList[0];
+ var keyIdToVerify = pgpOnePassSignature.KeyId;
+
+ // var verified = EncryptionKeys.ValidationPublicKey.KeyId == pgpOnePassSignature.KeyId ||
+ // EncryptionKeys.ValidationPublicKey.GetKeySignatures().Cast()
+ // .Select(x => x.KeyId).Contains(pgpOnePassSignature.KeyId);
+ var verified = Utilities.FindPublicKey(keyIdToVerify, EncryptionKeys.VerificationKeys,
+ out PgpPublicKey _);
+ if (verified == false)
+ throw new PgpException("Failed to verify file.");
+
+ message = plainFact.NextPgpObject();
+ }
+ else if (!(message is PgpCompressedData))
+ throw new PgpException("File was not signed.");
+ }
- using (Stream compDataIn = cData.GetDataStream())
+ if (message is PgpCompressedData cData)
{
- objectFactory = new PgpObjectFactory(compDataIn);
+ Stream compDataIn = cData.GetDataStream().DisposeWith(disposables);
+ PgpObjectFactory objectFactory = new PgpObjectFactory(compDataIn);
message = objectFactory.NextPgpObject();
- }
- if (message is PgpOnePassSignatureList pgpOnePassSignatureList)
+ if (message is PgpOnePassSignatureList pgpOnePassSignatureList)
+ {
+ PgpOnePassSignature pgpOnePassSignature = pgpOnePassSignatureList[0];
+ var keyIdToVerify = pgpOnePassSignature.KeyId;
+ // var verified = EncryptionKeys.ValidationPublicKey.KeyId == pgpOnePassSignature.KeyId ||
+ // EncryptionKeys.ValidationPublicKey.GetKeySignatures().Cast()
+ // .Select(x => x.KeyId).Contains(pgpOnePassSignature.KeyId);
+ var verified = Utilities.FindPublicKey(keyIdToVerify, EncryptionKeys.VerificationKeys,
+ out PgpPublicKey _);
+ if (verified == false)
+ throw new PgpException("Failed to verify file.");
+
+ message = objectFactory.NextPgpObject();
+ var literalData = (PgpLiteralData)message;
+ Stream unc = literalData.GetInputStream();
+ Streams.PipeAll(unc, outputStream);
+ }
+ else
+ {
+ throw new PgpException("File was not signed.");
+ }
+ }
+ else if (message is PgpLiteralData literalData)
{
- PgpOnePassSignature pgpOnePassSignature = pgpOnePassSignatureList[0];
- var keyIdToVerify = pgpOnePassSignature.KeyId;
- // var verified = EncryptionKeys.ValidationPublicKey.KeyId == pgpOnePassSignature.KeyId ||
- // EncryptionKeys.ValidationPublicKey.GetKeySignatures().Cast()
- // .Select(x => x.KeyId).Contains(pgpOnePassSignature.KeyId);
- var verified = Utilities.FindPublicKey(keyIdToVerify, EncryptionKeys.VerificationKeys,
- out PgpPublicKey _);
- if (verified == false)
- throw new PgpException("Failed to verify file.");
-
- message = objectFactory.NextPgpObject();
- var literalData = (PgpLiteralData)message;
Stream unc = literalData.GetInputStream();
Streams.PipeAll(unc, outputStream);
- }
- else
- {
- throw new PgpException("File was not signed.");
- }
- }
- else if (message is PgpLiteralData literalData)
- {
- Stream unc = literalData.GetInputStream();
- Streams.PipeAll(unc, outputStream);
- if (pbe.IsIntegrityProtected())
- {
- if (!pbe.Verify())
+ if (pbe.IsIntegrityProtected())
{
- throw new PgpException("Message failed integrity check.");
+ if (!pbe.Verify())
+ {
+ throw new PgpException("Message failed integrity check.");
+ }
}
}
+ else
+ throw new PgpException("File was not signed.");
}
- else
- throw new PgpException("File was not signed.");
}
#endregion DecryptAndVerify