diff --git a/crypto/BouncyCastle.Android.csproj b/crypto/BouncyCastle.Android.csproj
index 5859a1bc8..fc7236b70 100644
--- a/crypto/BouncyCastle.Android.csproj
+++ b/crypto/BouncyCastle.Android.csproj
@@ -546,6 +546,7 @@
<Compile Include="src\bcpg\SymmetricKeyAlgorithmTags.cs" />
<Compile Include="src\bcpg\SymmetricKeyEncSessionPacket.cs" />
<Compile Include="src\bcpg\TrustPacket.cs" />
+ <Compile Include="src\bcpg\UnsupportedPacketVersionException.cs" />
<Compile Include="src\bcpg\UserAttributePacket.cs" />
<Compile Include="src\bcpg\UserAttributeSubpacket.cs" />
<Compile Include="src\bcpg\UserAttributeSubpacketTags.cs" />
diff --git a/crypto/BouncyCastle.csproj b/crypto/BouncyCastle.csproj
index 3a3dadd21..a7dee10ff 100644
--- a/crypto/BouncyCastle.csproj
+++ b/crypto/BouncyCastle.csproj
@@ -540,6 +540,7 @@
<Compile Include="src\bcpg\SymmetricKeyAlgorithmTags.cs" />
<Compile Include="src\bcpg\SymmetricKeyEncSessionPacket.cs" />
<Compile Include="src\bcpg\TrustPacket.cs" />
+ <Compile Include="src\bcpg\UnsupportedPacketVersionException.cs" />
<Compile Include="src\bcpg\UserAttributePacket.cs" />
<Compile Include="src\bcpg\UserAttributeSubpacket.cs" />
<Compile Include="src\bcpg\UserAttributeSubpacketTags.cs" />
diff --git a/crypto/BouncyCastle.iOS.csproj b/crypto/BouncyCastle.iOS.csproj
index d02d6b97b..5fbdb6d27 100644
--- a/crypto/BouncyCastle.iOS.csproj
+++ b/crypto/BouncyCastle.iOS.csproj
@@ -541,6 +541,7 @@
<Compile Include="src\bcpg\SymmetricKeyAlgorithmTags.cs" />
<Compile Include="src\bcpg\SymmetricKeyEncSessionPacket.cs" />
<Compile Include="src\bcpg\TrustPacket.cs" />
+ <Compile Include="src\bcpg\UnsupportedPacketVersionException.cs" />
<Compile Include="src\bcpg\UserAttributePacket.cs" />
<Compile Include="src\bcpg\UserAttributeSubpacket.cs" />
<Compile Include="src\bcpg\UserAttributeSubpacketTags.cs" />
diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj
index c7f5d4c22..e06b37f9f 100644
--- a/crypto/crypto.csproj
+++ b/crypto/crypto.csproj
@@ -2589,6 +2589,11 @@
BuildAction = "Compile"
/>
<File
+ RelPath = "src\bcpg\UnsupportedPacketVersionException.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
RelPath = "src\bcpg\UserAttributePacket.cs"
SubType = "Code"
BuildAction = "Compile"
@@ -14984,6 +14989,11 @@
BuildAction = "Compile"
/>
<File
+ RelPath = "test\src\openpgp\test\PgpSignatureInvalidVersionIgnoredTest.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
RelPath = "test\src\openpgp\test\PGPSignatureTest.cs"
SubType = "Code"
BuildAction = "Compile"
diff --git a/crypto/src/bcpg/BcpgInputStream.cs b/crypto/src/bcpg/BcpgInputStream.cs
index 3dba953ea..38b5382ad 100644
--- a/crypto/src/bcpg/BcpgInputStream.cs
+++ b/crypto/src/bcpg/BcpgInputStream.cs
@@ -196,7 +196,7 @@ namespace Org.BouncyCastle.Bcpg
else
{
PartialInputStream pis = new PartialInputStream(this, partial, bodyLen);
- objStream = new BcpgInputStream(pis);
+ objStream = new BcpgInputStream(new BufferedStream(pis));
}
switch (tag)
diff --git a/crypto/src/bcpg/SignaturePacket.cs b/crypto/src/bcpg/SignaturePacket.cs
index 70138d584..9a664f902 100644
--- a/crypto/src/bcpg/SignaturePacket.cs
+++ b/crypto/src/bcpg/SignaturePacket.cs
@@ -5,6 +5,7 @@ using System.IO;
using Org.BouncyCastle.Bcpg.Sig;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.Date;
+using Org.BouncyCastle.Utilities.IO;
namespace Org.BouncyCastle.Bcpg
{
@@ -121,7 +122,9 @@ namespace Org.BouncyCastle.Bcpg
}
else
{
- throw new Exception("unsupported version: " + version);
+ Streams.Drain(bcpgIn);
+
+ throw new UnsupportedPacketVersionException("unsupported version: " + version);
}
fingerprint = new byte[2];
diff --git a/crypto/src/bcpg/UnsupportedPacketVersionException.cs b/crypto/src/bcpg/UnsupportedPacketVersionException.cs
new file mode 100644
index 000000000..447d75286
--- /dev/null
+++ b/crypto/src/bcpg/UnsupportedPacketVersionException.cs
@@ -0,0 +1,13 @@
+using System;
+
+namespace Org.BouncyCastle.Bcpg
+{
+ public class UnsupportedPacketVersionException
+ : Exception
+ {
+ public UnsupportedPacketVersionException(string msg)
+ : base(msg)
+ {
+ }
+ }
+}
diff --git a/crypto/src/openpgp/PgpObjectFactory.cs b/crypto/src/openpgp/PgpObjectFactory.cs
index 1f1c32c83..c67c7ccd1 100644
--- a/crypto/src/openpgp/PgpObjectFactory.cs
+++ b/crypto/src/openpgp/PgpObjectFactory.cs
@@ -50,6 +50,12 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
{
l.Add(new PgpSignature(bcpgIn));
}
+ catch (UnsupportedPacketVersionException e)
+ {
+ // Signatures of unsupported version MUST BE ignored
+ // see: https://tests.sequoia-pgp.org/#Detached_signatures_with_unknown_packets
+ continue;
+ }
catch (PgpException e)
{
throw new IOException("can't create signature object: " + e);
@@ -61,7 +67,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
{
sigs[i] = (PgpSignature)l[i];
}
- return new PgpSignatureList(sigs);
+ return new PgpSignatureList(sigs);
}
case PacketTag.SecretKey:
try
diff --git a/crypto/test/UnitTests.csproj b/crypto/test/UnitTests.csproj
index 64505fb15..1650a05fa 100644
--- a/crypto/test/UnitTests.csproj
+++ b/crypto/test/UnitTests.csproj
@@ -395,6 +395,7 @@
<Compile Include="src\openpgp\test\PGPPBETest.cs" />
<Compile Include="src\openpgp\test\PGPPacketTest.cs" />
<Compile Include="src\openpgp\test\PGPRSATest.cs" />
+ <Compile Include="src\openpgp\test\PgpSignatureInvalidVersionIgnoredTest.cs" />
<Compile Include="src\openpgp\test\PGPSignatureTest.cs" />
<Compile Include="src\openpgp\test\PgpECDHTest.cs" />
<Compile Include="src\openpgp\test\PgpECDsaTest.cs" />
diff --git a/crypto/test/src/openpgp/test/PgpSignatureInvalidVersionIgnoredTest.cs b/crypto/test/src/openpgp/test/PgpSignatureInvalidVersionIgnoredTest.cs
new file mode 100644
index 000000000..873ddf147
--- /dev/null
+++ b/crypto/test/src/openpgp/test/PgpSignatureInvalidVersionIgnoredTest.cs
@@ -0,0 +1,111 @@
+using System;
+using System.Collections;
+using System.IO;
+using System.Text;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
+{
+ [TestFixture]
+ public class PgpSignatureInvalidVersionIgnoredTest
+ : SimpleTest
+ {
+ // Signing Key ID
+ private static readonly long KEY_ID = new BigInteger("FBFCC82A015E7330", 16).LongValue;
+
+ // Signature List consisting of Version 4 Signature and Version 23 (invalid version) Signature
+ private static readonly string SIG4SIG23 = "-----BEGIN PGP SIGNATURE-----\n" +
+ "\n" +
+ "wsE7BAABCgBvBYJgyf2fCRD7/MgqAV5zMEcUAAAAAAAeACBzYWx0QG5vdGF0aW9u\n" +
+ "cy5zZXF1b2lhLXBncC5vcmdURSYEGurWv1IDN4trcpgfrHMZeGRdhG5jlQazr8tJ\n" +
+ "QRYhBNGmbhojsYLJmA94jPv8yCoBXnMwAADAYwv+NeSzVRrR/CGLMna43b0xCrOz\n" +
+ "tEYVp3hLzjCYWP1F5d7OdrpQWB3jzgMhjkH5ZnSm369A6D6eEoo05uP7lUNoex7s\n" +
+ "Bcksq4QF2t9y0YHwjhciVyPUw0rgzOIDpJ6jb/HqEgWB+EYz5qU3RFAk4tz+ghpw\n" +
+ "93x+EAI7QBnw+PRjgmJiXQvcq78W+h8aysAQCv/dNJc9W8gfCpwDY2VKTc0BW9VI\n" +
+ "R4KbeI2Rgx378JYjzJNP9ORgDTacBdQh3LiqJ8B4x7OeVGouGbWEVG6x+htQ9YMH\n" +
+ "uOY1CmcNzoMSRyk50JOeM0Xcge/9PLuQM+b4OQ3ZRN/BhUEg4P/VclXzkWeDKCvP\n" +
+ "cGEUrdFnyU1Lk2mYh1HTKS3gurTP9bdAyS9sdjXj9kv2fRM5N46rBRAffjwfW/LT\n" +
+ "VedvgRZ3RMCLrwPo90ID/xVU8PC9VmBR+WrqOijdsgnh7n940NR5hSyeWVeMwNFl\n" +
+ "Js043gKSIc5yNLS16mE/YzgosnUpIUsDlSR6D8M/wsE7FwABCgBvBYJgyf2fCRD7\n" +
+ "/MgqAV5zMEcUAAAAAAAeACBzYWx0QG5vdGF0aW9ucy5zZXF1b2lhLXBncC5vcmdU\n" +
+ "RSYEGurWv1IDN4trcpgfrHMZeGRdhG5jlQazr8tJQRYhBNGmbhojsYLJmA94jPv8\n" +
+ "yCoBXnMwAADAYwv+NeSzVRrR/CGLMna43b0xCrOztEYVp3hLzjCYWP1F5d7OdrpQ\n" +
+ "WB3jzgMhjkH5ZnSm369A6D6eEoo05uP7lUNoex7sBcksq4QF2t9y0YHwjhciVyPU\n" +
+ "w0rgzOIDpJ6jb/HqEgWB+EYz5qU3RFAk4tz+ghpw93x+EAI7QBnw+PRjgmJiXQvc\n" +
+ "q78W+h8aysAQCv/dNJc9W8gfCpwDY2VKTc0BW9VIR4KbeI2Rgx378JYjzJNP9ORg\n" +
+ "DTacBdQh3LiqJ8B4x7OeVGouGbWEVG6x+htQ9YMHuOY1CmcNzoMSRyk50JOeM0Xc\n" +
+ "ge/9PLuQM+b4OQ3ZRN/BhUEg4P/VclXzkWeDKCvPcGEUrdFnyU1Lk2mYh1HTKS3g\n" +
+ "urTP9bdAyS9sdjXj9kv2fRM5N46rBRAffjwfW/LTVedvgRZ3RMCLrwPo90ID/xVU\n" +
+ "8PC9VmBR+WrqOijdsgnh7n940NR5hSyeWVeMwNFlJs043gKSIc5yNLS16mE/Yzgo\n" +
+ "snUpIUsDlSR6D8M/\n" +
+ "=Ptch\n" +
+ "-----END PGP SIGNATURE-----";
+
+ // Signature List consisting of Version 23 (invalid version) Signature and Version 4 Signature
+ private static readonly string SIG23SIG4 = "-----BEGIN PGP SIGNATURE-----\n" +
+ "\n" +
+ "wsE7FwABCgBvBYJgyf2fCRD7/MgqAV5zMEcUAAAAAAAeACBzYWx0QG5vdGF0aW9u\n" +
+ "cy5zZXF1b2lhLXBncC5vcmdURSYEGurWv1IDN4trcpgfrHMZeGRdhG5jlQazr8tJ\n" +
+ "QRYhBNGmbhojsYLJmA94jPv8yCoBXnMwAADAYwv+NeSzVRrR/CGLMna43b0xCrOz\n" +
+ "tEYVp3hLzjCYWP1F5d7OdrpQWB3jzgMhjkH5ZnSm369A6D6eEoo05uP7lUNoex7s\n" +
+ "Bcksq4QF2t9y0YHwjhciVyPUw0rgzOIDpJ6jb/HqEgWB+EYz5qU3RFAk4tz+ghpw\n" +
+ "93x+EAI7QBnw+PRjgmJiXQvcq78W+h8aysAQCv/dNJc9W8gfCpwDY2VKTc0BW9VI\n" +
+ "R4KbeI2Rgx378JYjzJNP9ORgDTacBdQh3LiqJ8B4x7OeVGouGbWEVG6x+htQ9YMH\n" +
+ "uOY1CmcNzoMSRyk50JOeM0Xcge/9PLuQM+b4OQ3ZRN/BhUEg4P/VclXzkWeDKCvP\n" +
+ "cGEUrdFnyU1Lk2mYh1HTKS3gurTP9bdAyS9sdjXj9kv2fRM5N46rBRAffjwfW/LT\n" +
+ "VedvgRZ3RMCLrwPo90ID/xVU8PC9VmBR+WrqOijdsgnh7n940NR5hSyeWVeMwNFl\n" +
+ "Js043gKSIc5yNLS16mE/YzgosnUpIUsDlSR6D8M/wsE7BAABCgBvBYJgyf2fCRD7\n" +
+ "/MgqAV5zMEcUAAAAAAAeACBzYWx0QG5vdGF0aW9ucy5zZXF1b2lhLXBncC5vcmdU\n" +
+ "RSYEGurWv1IDN4trcpgfrHMZeGRdhG5jlQazr8tJQRYhBNGmbhojsYLJmA94jPv8\n" +
+ "yCoBXnMwAADAYwv+NeSzVRrR/CGLMna43b0xCrOztEYVp3hLzjCYWP1F5d7OdrpQ\n" +
+ "WB3jzgMhjkH5ZnSm369A6D6eEoo05uP7lUNoex7sBcksq4QF2t9y0YHwjhciVyPU\n" +
+ "w0rgzOIDpJ6jb/HqEgWB+EYz5qU3RFAk4tz+ghpw93x+EAI7QBnw+PRjgmJiXQvc\n" +
+ "q78W+h8aysAQCv/dNJc9W8gfCpwDY2VKTc0BW9VIR4KbeI2Rgx378JYjzJNP9ORg\n" +
+ "DTacBdQh3LiqJ8B4x7OeVGouGbWEVG6x+htQ9YMHuOY1CmcNzoMSRyk50JOeM0Xc\n" +
+ "ge/9PLuQM+b4OQ3ZRN/BhUEg4P/VclXzkWeDKCvPcGEUrdFnyU1Lk2mYh1HTKS3g\n" +
+ "urTP9bdAyS9sdjXj9kv2fRM5N46rBRAffjwfW/LTVedvgRZ3RMCLrwPo90ID/xVU\n" +
+ "8PC9VmBR+WrqOijdsgnh7n940NR5hSyeWVeMwNFlJs043gKSIc5yNLS16mE/Yzgo\n" +
+ "snUpIUsDlSR6D8M/\n" +
+ "=o4rJ\n" +
+ "-----END PGP SIGNATURE-----";
+
+ public override string Name
+ {
+ get { return "PgpSignatureInvalidVersionIgnoredTest"; }
+ }
+
+ public override void PerformTest()
+ {
+ AssertInvalidSignatureVersionIsIgnored(SIG4SIG23);
+ AssertInvalidSignatureVersionIsIgnored(SIG23SIG4);
+ }
+
+ public static void Main(string[] args)
+ {
+ RunTest(new PgpSignatureInvalidVersionIgnoredTest());
+ }
+
+ [Test]
+ public void TestFunction()
+ {
+ string resultText = Perform().ToString();
+
+ Assert.AreEqual(Name + ": Okay", resultText);
+ }
+
+ private void AssertInvalidSignatureVersionIsIgnored(string sig)
+ {
+ ArmoredInputStream armorIn = new ArmoredInputStream(
+ new MemoryStream(Encoding.UTF8.GetBytes(sig), false));
+ PgpObjectFactory objectFactory = new PgpObjectFactory(armorIn);
+ PgpSignatureList signatures = (PgpSignatureList)objectFactory.NextPgpObject();
+ IsEquals(1, signatures.Count);
+ PgpSignature signature = signatures[0];
+ IsEquals(KEY_ID, signature.KeyId);
+ }
+ }
+}
diff --git a/crypto/test/src/openpgp/test/RegressionTest.cs b/crypto/test/src/openpgp/test/RegressionTest.cs
index 3f5bcfcbd..a6a7edf5f 100644
--- a/crypto/test/src/openpgp/test/RegressionTest.cs
+++ b/crypto/test/src/openpgp/test/RegressionTest.cs
@@ -26,6 +26,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
new PgpParsingTest(),
new PgpPbeTest(),
new PgpRsaTest(),
+ new PgpSignatureInvalidVersionIgnoredTest(),
new PgpSignatureTest(),
};
|