diff --git a/crypto/src/bcpg/DsaPublicBcpgKey.cs b/crypto/src/bcpg/DsaPublicBcpgKey.cs
index 61159567c..11294cc22 100644
--- a/crypto/src/bcpg/DsaPublicBcpgKey.cs
+++ b/crypto/src/bcpg/DsaPublicBcpgKey.cs
@@ -4,46 +4,46 @@ using Org.BouncyCastle.Math;
namespace Org.BouncyCastle.Bcpg
{
- /// <remarks>Base class for a DSA public key.</remarks>
- public class DsaPublicBcpgKey
- : BcpgObject, IBcpgKey
+ /// <remarks>Base class for a DSA public key.</remarks>
+ public class DsaPublicBcpgKey
+ : BcpgObject, IBcpgKey
{
private readonly MPInteger p, q, g, y;
- /// <param name="bcpgIn">The stream to read the packet from.</param>
- public DsaPublicBcpgKey(
- BcpgInputStream bcpgIn)
- {
- this.p = new MPInteger(bcpgIn);
- this.q = new MPInteger(bcpgIn);
- this.g = new MPInteger(bcpgIn);
- this.y = new MPInteger(bcpgIn);
- }
+ /// <param name="bcpgIn">The stream to read the packet from.</param>
+ public DsaPublicBcpgKey(
+ BcpgInputStream bcpgIn)
+ {
+ this.p = new MPInteger(bcpgIn);
+ this.q = new MPInteger(bcpgIn);
+ this.g = new MPInteger(bcpgIn);
+ this.y = new MPInteger(bcpgIn);
+ }
- public DsaPublicBcpgKey(
- BigInteger p,
- BigInteger q,
- BigInteger g,
- BigInteger y)
- {
- this.p = new MPInteger(p);
- this.q = new MPInteger(q);
- this.g = new MPInteger(g);
- this.y = new MPInteger(y);
- }
+ public DsaPublicBcpgKey(
+ BigInteger p,
+ BigInteger q,
+ BigInteger g,
+ BigInteger y)
+ {
+ this.p = new MPInteger(p);
+ this.q = new MPInteger(q);
+ this.g = new MPInteger(g);
+ this.y = new MPInteger(y);
+ }
- /// <summary>The format, as a string, always "PGP".</summary>
- public string Format
- {
- get { return "PGP"; }
- }
+ /// <summary>The format, as a string, always "PGP".</summary>
+ public string Format
+ {
+ get { return "PGP"; }
+ }
- /// <summary>Return the standard PGP encoding of the key.</summary>
+ /// <summary>Return the standard PGP encoding of the key.</summary>
public override byte[] GetEncoded()
{
try
{
- return base.GetEncoded();
+ return base.GetEncoded();
}
catch (Exception)
{
@@ -51,30 +51,30 @@ namespace Org.BouncyCastle.Bcpg
}
}
- public override void Encode(
- BcpgOutputStream bcpgOut)
- {
- bcpgOut.WriteObjects(p, q, g, y);
- }
+ public override void Encode(
+ BcpgOutputStream bcpgOut)
+ {
+ bcpgOut.WriteObjects(p, q, g, y);
+ }
- public BigInteger G
- {
- get { return g.Value; }
- }
+ public BigInteger G
+ {
+ get { return g.Value; }
+ }
- public BigInteger P
- {
- get { return p.Value; }
- }
+ public BigInteger P
+ {
+ get { return p.Value; }
+ }
- public BigInteger Q
- {
- get { return q.Value; }
- }
+ public BigInteger Q
+ {
+ get { return q.Value; }
+ }
- public BigInteger Y
- {
- get { return y.Value; }
- }
+ public BigInteger Y
+ {
+ get { return y.Value; }
+ }
}
}
diff --git a/crypto/src/bcpg/PublicKeyPacket.cs b/crypto/src/bcpg/PublicKeyPacket.cs
index 32d43149b..a45aeb469 100644
--- a/crypto/src/bcpg/PublicKeyPacket.cs
+++ b/crypto/src/bcpg/PublicKeyPacket.cs
@@ -5,11 +5,11 @@ using Org.BouncyCastle.Utilities.Date;
namespace Org.BouncyCastle.Bcpg
{
- /// <remarks>Basic packet for a PGP public key.</remarks>
+ /// <remarks>Basic packet for a PGP public key.</remarks>
public class PublicKeyPacket
: ContainedPacket //, PublicKeyAlgorithmTag
{
- private int version;
+ private int version;
private long time;
private int validDays;
private PublicKeyAlgorithmTag algorithm;
@@ -49,44 +49,44 @@ namespace Org.BouncyCastle.Bcpg
}
}
- /// <summary>Construct a version 4 public key packet.</summary>
+ /// <summary>Construct a version 4 public key packet.</summary>
public PublicKeyPacket(
PublicKeyAlgorithmTag algorithm,
DateTime time,
IBcpgKey key)
{
- this.version = 4;
+ this.version = 4;
this.time = DateTimeUtilities.DateTimeToUnixMs(time) / 1000L;
this.algorithm = algorithm;
this.key = key;
}
- public int Version
+ public virtual int Version
{
- get { return version; }
+ get { return version; }
}
- public PublicKeyAlgorithmTag Algorithm
+ public virtual PublicKeyAlgorithmTag Algorithm
{
- get { return algorithm; }
+ get { return algorithm; }
}
- public int ValidDays
+ public virtual int ValidDays
{
- get { return validDays; }
+ get { return validDays; }
}
- public DateTime GetTime()
+ public virtual DateTime GetTime()
{
return DateTimeUtilities.UnixMsToDateTime(time * 1000L);
}
- public IBcpgKey Key
+ public virtual IBcpgKey Key
{
- get { return key; }
+ get { return key; }
}
- public byte[] GetEncodedContents()
+ public virtual byte[] GetEncodedContents()
{
MemoryStream bOut = new MemoryStream();
BcpgOutputStream pOut = new BcpgOutputStream(bOut);
@@ -94,22 +94,22 @@ namespace Org.BouncyCastle.Bcpg
pOut.WriteByte((byte) version);
pOut.WriteInt((int) time);
- if (version <= 3)
+ if (version <= 3)
{
pOut.WriteShort((short) validDays);
}
- pOut.WriteByte((byte) algorithm);
+ pOut.WriteByte((byte) algorithm);
- pOut.WriteObject((BcpgObject)key);
+ pOut.WriteObject((BcpgObject)key);
- return bOut.ToArray();
+ return bOut.ToArray();
}
- public override void Encode(
- BcpgOutputStream bcpgOut)
- {
- bcpgOut.WritePacket(PacketTag.PublicKey, GetEncodedContents(), true);
- }
- }
+ public override void Encode(
+ BcpgOutputStream bcpgOut)
+ {
+ bcpgOut.WritePacket(PacketTag.PublicKey, GetEncodedContents(), true);
+ }
+ }
}
diff --git a/crypto/src/bcpg/UserAttributeSubpacket.cs b/crypto/src/bcpg/UserAttributeSubpacket.cs
index bd49d2150..05f60ac17 100644
--- a/crypto/src/bcpg/UserAttributeSubpacket.cs
+++ b/crypto/src/bcpg/UserAttributeSubpacket.cs
@@ -10,40 +10,44 @@ namespace Org.BouncyCastle.Bcpg
*/
public class UserAttributeSubpacket
{
- private readonly UserAttributeSubpacketTag type;
- private readonly byte[] data;
+ internal readonly UserAttributeSubpacketTag type;
+ private readonly bool longLength; // we preserve this as not everyone encodes length properly.
+ protected readonly byte[] data;
- internal UserAttributeSubpacket(
- UserAttributeSubpacketTag type,
- byte[] data)
+ protected internal UserAttributeSubpacket(UserAttributeSubpacketTag type, byte[] data)
+ : this(type, false, data)
+ {
+ }
+
+ protected internal UserAttributeSubpacket(UserAttributeSubpacketTag type, bool forceLongLength, byte[] data)
{
this.type = type;
+ this.longLength = forceLongLength;
this.data = data;
}
- public UserAttributeSubpacketTag SubpacketType
+ public virtual UserAttributeSubpacketTag SubpacketType
{
get { return type; }
}
- /**
+ /**
* return the generic data making up the packet.
*/
- public byte[] GetData()
+ public virtual byte[] GetData()
{
return data;
}
- public void Encode(
- Stream os)
+ public virtual void Encode(Stream os)
{
int bodyLen = data.Length + 1;
- if (bodyLen < 192)
+ if (bodyLen < 192 && !longLength)
{
os.WriteByte((byte)bodyLen);
}
- else if (bodyLen <= 8383)
+ else if (bodyLen <= 8383 && !longLength)
{
bodyLen -= 192;
@@ -69,18 +73,18 @@ namespace Org.BouncyCastle.Bcpg
if (obj == this)
return true;
- UserAttributeSubpacket other = obj as UserAttributeSubpacket;
+ UserAttributeSubpacket other = obj as UserAttributeSubpacket;
- if (other == null)
- return false;
+ if (other == null)
+ return false;
- return type == other.type
- && Arrays.AreEqual(data, other.data);
+ return type == other.type
+ && Arrays.AreEqual(data, other.data);
}
- public override int GetHashCode()
+ public override int GetHashCode()
{
- return type.GetHashCode() ^ Arrays.GetHashCode(data);
+ return type.GetHashCode() ^ Arrays.GetHashCode(data);
}
}
}
diff --git a/crypto/src/bcpg/UserAttributeSubpacketsReader.cs b/crypto/src/bcpg/UserAttributeSubpacketsReader.cs
index 2e5ea0f3e..f0cc1b8e4 100644
--- a/crypto/src/bcpg/UserAttributeSubpacketsReader.cs
+++ b/crypto/src/bcpg/UserAttributeSubpacketsReader.cs
@@ -5,59 +5,61 @@ using Org.BouncyCastle.Utilities.IO;
namespace Org.BouncyCastle.Bcpg
{
- /**
- * reader for user attribute sub-packets
- */
- public class UserAttributeSubpacketsParser
- {
- private readonly Stream input;
+ /**
+ * reader for user attribute sub-packets
+ */
+ public class UserAttributeSubpacketsParser
+ {
+ private readonly Stream input;
- public UserAttributeSubpacketsParser(
- Stream input)
- {
- this.input = input;
- }
+ public UserAttributeSubpacketsParser(
+ Stream input)
+ {
+ this.input = input;
+ }
- public UserAttributeSubpacket ReadPacket()
- {
- int l = input.ReadByte();
- if (l < 0)
- return null;
+ public virtual UserAttributeSubpacket ReadPacket()
+ {
+ int l = input.ReadByte();
+ if (l < 0)
+ return null;
- int bodyLen = 0;
- if (l < 192)
- {
- bodyLen = l;
- }
- else if (l <= 223)
- {
- bodyLen = ((l - 192) << 8) + (input.ReadByte()) + 192;
- }
- else if (l == 255)
- {
- bodyLen = (input.ReadByte() << 24) | (input.ReadByte() << 16)
- | (input.ReadByte() << 8) | input.ReadByte();
- }
- else
- {
- // TODO Error?
- }
+ int bodyLen = 0;
+ bool longLength = false;
+ if (l < 192)
+ {
+ bodyLen = l;
+ }
+ else if (l <= 223)
+ {
+ bodyLen = ((l - 192) << 8) + (input.ReadByte()) + 192;
+ }
+ else if (l == 255)
+ {
+ bodyLen = (input.ReadByte() << 24) | (input.ReadByte() << 16)
+ | (input.ReadByte() << 8) | input.ReadByte();
+ longLength = true;
+ }
+ else
+ {
+ throw new IOException("unrecognised length reading user attribute sub packet");
+ }
- int tag = input.ReadByte();
- if (tag < 0)
- throw new EndOfStreamException("unexpected EOF reading user attribute sub packet");
+ int tag = input.ReadByte();
+ if (tag < 0)
+ throw new EndOfStreamException("unexpected EOF reading user attribute sub packet");
- byte[] data = new byte[bodyLen - 1];
- if (Streams.ReadFully(input, data) < data.Length)
- throw new EndOfStreamException();
+ byte[] data = new byte[bodyLen - 1];
+ if (Streams.ReadFully(input, data) < data.Length)
+ throw new EndOfStreamException();
- UserAttributeSubpacketTag type = (UserAttributeSubpacketTag) tag;
- switch (type)
- {
- case UserAttributeSubpacketTag.ImageAttribute:
- return new ImageAttrib(data);
- }
- return new UserAttributeSubpacket(type, data);
- }
- }
+ UserAttributeSubpacketTag type = (UserAttributeSubpacketTag) tag;
+ switch (type)
+ {
+ case UserAttributeSubpacketTag.ImageAttribute:
+ return new ImageAttrib(longLength, data);
+ }
+ return new UserAttributeSubpacket(type, longLength, data);
+ }
+ }
}
diff --git a/crypto/src/bcpg/attr/ImageAttrib.cs b/crypto/src/bcpg/attr/ImageAttrib.cs
index 73490791c..2d0fef8b8 100644
--- a/crypto/src/bcpg/attr/ImageAttrib.cs
+++ b/crypto/src/bcpg/attr/ImageAttrib.cs
@@ -3,25 +3,29 @@ using System.IO;
namespace Org.BouncyCastle.Bcpg.Attr
{
- /// <remarks>Basic type for a image attribute packet.</remarks>
+ /// <remarks>Basic type for a image attribute packet.</remarks>
public class ImageAttrib
- : UserAttributeSubpacket
+ : UserAttributeSubpacket
{
- public enum Format : byte
- {
- Jpeg = 1
- }
+ public enum Format : byte
+ {
+ Jpeg = 1
+ }
- private static readonly byte[] Zeroes = new byte[12];
+ private static readonly byte[] Zeroes = new byte[12];
- private int hdrLength;
+ private int hdrLength;
private int _version;
private int _encoding;
private byte[] imageData;
- public ImageAttrib(
- byte[] data)
- : base(UserAttributeSubpacketTag.ImageAttribute, data)
+ public ImageAttrib(byte[] data)
+ : this(false, data)
+ {
+ }
+
+ public ImageAttrib(bool forceLongLength, byte[] data)
+ : base(UserAttributeSubpacketTag.ImageAttribute, forceLongLength, data)
{
hdrLength = ((data[1] & 0xff) << 8) | (data[0] & 0xff);
_version = data[2] & 0xff;
@@ -31,36 +35,36 @@ namespace Org.BouncyCastle.Bcpg.Attr
Array.Copy(data, hdrLength, imageData, 0, imageData.Length);
}
- public ImageAttrib(
- Format imageType,
- byte[] imageData)
- : this(ToByteArray(imageType, imageData))
- {
- }
+ public ImageAttrib(
+ Format imageType,
+ byte[] imageData)
+ : this(ToByteArray(imageType, imageData))
+ {
+ }
- private static byte[] ToByteArray(
- Format imageType,
- byte[] imageData)
- {
- MemoryStream bOut = new MemoryStream();
- bOut.WriteByte(0x10); bOut.WriteByte(0x00); bOut.WriteByte(0x01);
- bOut.WriteByte((byte) imageType);
- bOut.Write(Zeroes, 0, Zeroes.Length);
- bOut.Write(imageData, 0, imageData.Length);
- return bOut.ToArray();
- }
+ private static byte[] ToByteArray(
+ Format imageType,
+ byte[] imageData)
+ {
+ MemoryStream bOut = new MemoryStream();
+ bOut.WriteByte(0x10); bOut.WriteByte(0x00); bOut.WriteByte(0x01);
+ bOut.WriteByte((byte) imageType);
+ bOut.Write(Zeroes, 0, Zeroes.Length);
+ bOut.Write(imageData, 0, imageData.Length);
+ return bOut.ToArray();
+ }
- public int Version
+ public virtual int Version
{
- get { return _version; }
+ get { return _version; }
}
- public int Encoding
+ public virtual int Encoding
{
- get { return _encoding; }
+ get { return _encoding; }
}
- public byte[] GetImageData()
+ public virtual byte[] GetImageData()
{
return imageData;
}
diff --git a/crypto/src/openpgp/PgpPublicKeyRing.cs b/crypto/src/openpgp/PgpPublicKeyRing.cs
index ecb935e4b..7b1ac93bf 100644
--- a/crypto/src/openpgp/PgpPublicKeyRing.cs
+++ b/crypto/src/openpgp/PgpPublicKeyRing.cs
@@ -7,164 +7,164 @@ using Org.BouncyCastle.Utilities.Collections;
namespace Org.BouncyCastle.Bcpg.OpenPgp
{
- /// <remarks>
- /// Class to hold a single master public key and its subkeys.
- /// <p>
- /// Often PGP keyring files consist of multiple master keys, if you are trying to process
- /// or construct one of these you should use the <c>PgpPublicKeyRingBundle</c> class.
- /// </p>
- /// </remarks>
- public class PgpPublicKeyRing
- : PgpKeyRing
+ /// <remarks>
+ /// Class to hold a single master public key and its subkeys.
+ /// <p>
+ /// Often PGP keyring files consist of multiple master keys, if you are trying to process
+ /// or construct one of these you should use the <c>PgpPublicKeyRingBundle</c> class.
+ /// </p>
+ /// </remarks>
+ public class PgpPublicKeyRing
+ : PgpKeyRing
{
private readonly IList keys;
- public PgpPublicKeyRing(
+ public PgpPublicKeyRing(
byte[] encoding)
: this(new MemoryStream(encoding, false))
{
}
- internal PgpPublicKeyRing(
+ internal PgpPublicKeyRing(
IList pubKeys)
{
this.keys = pubKeys;
}
- public PgpPublicKeyRing(
+ public PgpPublicKeyRing(
Stream inputStream)
{
- this.keys = Platform.CreateArrayList();
+ this.keys = Platform.CreateArrayList();
BcpgInputStream bcpgInput = BcpgInputStream.Wrap(inputStream);
- PacketTag initialTag = bcpgInput.NextPacketTag();
+ PacketTag initialTag = bcpgInput.NextPacketTag();
if (initialTag != PacketTag.PublicKey && initialTag != PacketTag.PublicSubkey)
{
throw new IOException("public key ring doesn't start with public key tag: "
- + "tag 0x" + ((int)initialTag).ToString("X"));
+ + "tag 0x" + ((int)initialTag).ToString("X"));
}
- PublicKeyPacket pubPk = (PublicKeyPacket) bcpgInput.ReadPacket();;
- TrustPacket trustPk = ReadOptionalTrustPacket(bcpgInput);
+ PublicKeyPacket pubPk = (PublicKeyPacket) bcpgInput.ReadPacket();;
+ TrustPacket trustPk = ReadOptionalTrustPacket(bcpgInput);
// direct signatures and revocations
- IList keySigs = ReadSignaturesAndTrust(bcpgInput);
+ IList keySigs = ReadSignaturesAndTrust(bcpgInput);
- IList ids, idTrusts, idSigs;
- ReadUserIDs(bcpgInput, out ids, out idTrusts, out idSigs);
+ IList ids, idTrusts, idSigs;
+ ReadUserIDs(bcpgInput, out ids, out idTrusts, out idSigs);
- keys.Add(new PgpPublicKey(pubPk, trustPk, keySigs, ids, idTrusts, idSigs));
+ keys.Add(new PgpPublicKey(pubPk, trustPk, keySigs, ids, idTrusts, idSigs));
- // Read subkeys
- while (bcpgInput.NextPacketTag() == PacketTag.PublicSubkey)
+ // Read subkeys
+ while (bcpgInput.NextPacketTag() == PacketTag.PublicSubkey)
{
- keys.Add(ReadSubkey(bcpgInput));
+ keys.Add(ReadSubkey(bcpgInput));
}
}
- /// <summary>Return the first public key in the ring.</summary>
- public PgpPublicKey GetPublicKey()
+ /// <summary>Return the first public key in the ring.</summary>
+ public virtual PgpPublicKey GetPublicKey()
{
return (PgpPublicKey) keys[0];
}
- /// <summary>Return the public key referred to by the passed in key ID if it is present.</summary>
- public PgpPublicKey GetPublicKey(
+ /// <summary>Return the public key referred to by the passed in key ID if it is present.</summary>
+ public virtual PgpPublicKey GetPublicKey(
long keyId)
{
- foreach (PgpPublicKey k in keys)
- {
- if (keyId == k.KeyId)
+ foreach (PgpPublicKey k in keys)
+ {
+ if (keyId == k.KeyId)
{
return k;
}
}
- return null;
+ return null;
}
- /// <summary>Allows enumeration of all the public keys.</summary>
- /// <returns>An <c>IEnumerable</c> of <c>PgpPublicKey</c> objects.</returns>
- public IEnumerable GetPublicKeys()
+ /// <summary>Allows enumeration of all the public keys.</summary>
+ /// <returns>An <c>IEnumerable</c> of <c>PgpPublicKey</c> objects.</returns>
+ public virtual IEnumerable GetPublicKeys()
{
return new EnumerableProxy(keys);
}
- public byte[] GetEncoded()
+ public virtual byte[] GetEncoded()
{
MemoryStream bOut = new MemoryStream();
- Encode(bOut);
+ Encode(bOut);
- return bOut.ToArray();
+ return bOut.ToArray();
}
- public void Encode(
+ public virtual void Encode(
Stream outStr)
{
- if (outStr == null)
- throw new ArgumentNullException("outStr");
+ if (outStr == null)
+ throw new ArgumentNullException("outStr");
- foreach (PgpPublicKey k in keys)
- {
- k.Encode(outStr);
+ foreach (PgpPublicKey k in keys)
+ {
+ k.Encode(outStr);
}
}
- /// <summary>
- /// Returns a new key ring with the public key passed in either added or
- /// replacing an existing one.
- /// </summary>
- /// <param name="pubRing">The public key ring to be modified.</param>
- /// <param name="pubKey">The public key to be inserted.</param>
- /// <returns>A new <c>PgpPublicKeyRing</c></returns>
+ /// <summary>
+ /// Returns a new key ring with the public key passed in either added or
+ /// replacing an existing one.
+ /// </summary>
+ /// <param name="pubRing">The public key ring to be modified.</param>
+ /// <param name="pubKey">The public key to be inserted.</param>
+ /// <returns>A new <c>PgpPublicKeyRing</c></returns>
public static PgpPublicKeyRing InsertPublicKey(
PgpPublicKeyRing pubRing,
PgpPublicKey pubKey)
{
IList keys = Platform.CreateArrayList(pubRing.keys);
bool found = false;
- bool masterFound = false;
+ bool masterFound = false;
- for (int i = 0; i != keys.Count; i++)
+ for (int i = 0; i != keys.Count; i++)
{
PgpPublicKey key = (PgpPublicKey) keys[i];
- if (key.KeyId == pubKey.KeyId)
+ if (key.KeyId == pubKey.KeyId)
{
found = true;
keys[i] = pubKey;
}
- if (key.IsMasterKey)
- {
- masterFound = true;
- }
- }
+ if (key.IsMasterKey)
+ {
+ masterFound = true;
+ }
+ }
- if (!found)
+ if (!found)
{
- if (pubKey.IsMasterKey)
- {
- if (masterFound)
- throw new ArgumentException("cannot add a master key to a ring that already has one");
-
- keys.Insert(0, pubKey);
- }
- else
- {
- keys.Add(pubKey);
- }
- }
-
- return new PgpPublicKeyRing(keys);
+ if (pubKey.IsMasterKey)
+ {
+ if (masterFound)
+ throw new ArgumentException("cannot add a master key to a ring that already has one");
+
+ keys.Insert(0, pubKey);
+ }
+ else
+ {
+ keys.Add(pubKey);
+ }
+ }
+
+ return new PgpPublicKeyRing(keys);
}
- /// <summary>Returns a new key ring with the public key passed in removed from the key ring.</summary>
- /// <param name="pubRing">The public key ring to be modified.</param>
- /// <param name="pubKey">The public key to be removed.</param>
- /// <returns>A new <c>PgpPublicKeyRing</c>, or null if pubKey is not found.</returns>
+ /// <summary>Returns a new key ring with the public key passed in removed from the key ring.</summary>
+ /// <param name="pubRing">The public key ring to be modified.</param>
+ /// <param name="pubKey">The public key to be removed.</param>
+ /// <returns>A new <c>PgpPublicKeyRing</c>, or null if pubKey is not found.</returns>
public static PgpPublicKeyRing RemovePublicKey(
PgpPublicKeyRing pubRing,
PgpPublicKey pubKey)
@@ -172,29 +172,29 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
IList keys = Platform.CreateArrayList(pubRing.keys);
bool found = false;
- for (int i = 0; i < keys.Count; i++)
+ for (int i = 0; i < keys.Count; i++)
{
PgpPublicKey key = (PgpPublicKey) keys[i];
- if (key.KeyId == pubKey.KeyId)
+ if (key.KeyId == pubKey.KeyId)
{
found = true;
keys.RemoveAt(i);
}
}
- return found ? new PgpPublicKeyRing(keys) : null;
+ return found ? new PgpPublicKeyRing(keys) : null;
}
- internal static PgpPublicKey ReadSubkey(BcpgInputStream bcpgInput)
- {
+ internal static PgpPublicKey ReadSubkey(BcpgInputStream bcpgInput)
+ {
PublicKeyPacket pk = (PublicKeyPacket) bcpgInput.ReadPacket();
- TrustPacket kTrust = ReadOptionalTrustPacket(bcpgInput);
+ TrustPacket kTrust = ReadOptionalTrustPacket(bcpgInput);
- // PGP 8 actually leaves out the signature.
- IList sigList = ReadSignaturesAndTrust(bcpgInput);
+ // PGP 8 actually leaves out the signature.
+ IList sigList = ReadSignaturesAndTrust(bcpgInput);
- return new PgpPublicKey(pk, kTrust, sigList);
- }
+ return new PgpPublicKey(pk, kTrust, sigList);
+ }
}
}
diff --git a/crypto/test/src/openpgp/test/PGPSignatureTest.cs b/crypto/test/src/openpgp/test/PGPSignatureTest.cs
index 3aba2c302..0d8235307 100644
--- a/crypto/test/src/openpgp/test/PGPSignatureTest.cs
+++ b/crypto/test/src/openpgp/test/PGPSignatureTest.cs
@@ -12,750 +12,1034 @@ using Org.BouncyCastle.Utilities.Test;
namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
{
- [TestFixture]
- public class PgpSignatureTest
- : SimpleTest
- {
- private const int[] NO_PREFERENCES = null;
- private static readonly int[] PREFERRED_SYMMETRIC_ALGORITHMS
- = new int[] { (int)SymmetricKeyAlgorithmTag.Aes128, (int)SymmetricKeyAlgorithmTag.TripleDes };
- private static readonly int[] PREFERRED_HASH_ALGORITHMS
- = new int[] { (int)HashAlgorithmTag.Sha1, (int)HashAlgorithmTag.Sha256 };
- private static readonly int[] PREFERRED_COMPRESSION_ALGORITHMS
- = new int[] { (int)CompressionAlgorithmTag.ZLib };
-
- private const int TEST_EXPIRATION_TIME = 10000;
- private const string TEST_USER_ID = "test user id";
- private static readonly byte[] TEST_DATA = Encoding.ASCII.GetBytes("hello world!\nhello world!\n");
- private static readonly byte[] TEST_DATA_WITH_CRLF = Encoding.ASCII.GetBytes("hello world!\r\nhello world!\r\n");
-
- private static readonly byte[] dsaKeyRing = Base64.Decode(
- "lQHhBD9HBzURBACzkxRCVGJg5+Ld9DU4Xpnd4LCKgMq7YOY7Gi0EgK92gbaa6+zQ"
- + "oQFqz1tt3QUmpz3YVkm/zLESBBtC1ACIXGggUdFMUr5I87+1Cb6vzefAtGt8N5VV"
- + "1F/MXv1gJz4Bu6HyxL/ncfe71jsNhav0i4yAjf2etWFj53zK6R+Ojg5H6wCgpL9/"
- + "tXVfGP8SqFvyrN/437MlFSUEAIN3V6j/MUllyrZglrtr2+RWIwRrG/ACmrF6hTug"
- + "Ol4cQxaDYNcntXbhlTlJs9MxjTH3xxzylyirCyq7HzGJxZzSt6FTeh1DFYzhJ7Qu"
- + "YR1xrSdA6Y0mUv0ixD5A4nPHjupQ5QCqHGeRfFD/oHzD4zqBnJp/BJ3LvQ66bERJ"
- + "mKl5A/4uj3HoVxpb0vvyENfRqKMmGBISycY4MoH5uWfb23FffsT9r9KL6nJ4syLz"
- + "aRR0gvcbcjkc9Z3epI7gr3jTrb4d8WPxsDbT/W1tv9bG/EHawomLcihtuUU68Uej"
- + "6/wZot1XJqu2nQlku57+M/V2X1y26VKsipolPfja4uyBOOyvbP4DAwIDIBTxWjkC"
- + "GGAWQO2jy9CTvLHJEoTO7moHrp1FxOVpQ8iJHyRqZzLllO26OzgohbiPYz8u9qCu"
- + "lZ9Xn7QzRXJpYyBFY2hpZG5hIChEU0EgVGVzdCBLZXkpIDxlcmljQGJvdW5jeWNh"
- + "c3RsZS5vcmc+iFkEExECABkFAj9HBzUECwcDAgMVAgMDFgIBAh4BAheAAAoJEM0j"
- + "9enEyjRDAlwAnjTjjt57NKIgyym7OTCwzIU3xgFpAJ0VO5m5PfQKmGJRhaewLSZD"
- + "4nXkHg==");
-
- private static readonly char[] dsaPass = "hello world".ToCharArray();
-
- private static readonly byte[] rsaKeyRing = Base64.Decode(
- "lQIEBEBXUNMBBADScQczBibewnbCzCswc/9ut8R0fwlltBRxMW0NMdKJY2LF"
- + "7k2COeLOCIU95loJGV6ulbpDCXEO2Jyq8/qGw1qD3SCZNXxKs3GS8Iyh9Uwd"
- + "VL07nMMYl5NiQRsFB7wOb86+94tYWgvikVA5BRP5y3+O3GItnXnpWSJyREUy"
- + "6WI2QQAGKf4JAwIVmnRs4jtTX2DD05zy2mepEQ8bsqVAKIx7lEwvMVNcvg4Y"
- + "8vFLh9Mf/uNciwL4Se/ehfKQ/AT0JmBZduYMqRU2zhiBmxj4cXUQ0s36ysj7"
- + "fyDngGocDnM3cwPxaTF1ZRBQHSLewP7dqE7M73usFSz8vwD/0xNOHFRLKbsO"
- + "RqDlLA1Cg2Yd0wWPS0o7+qqk9ndqrjjSwMM8ftnzFGjShAdg4Ca7fFkcNePP"
- + "/rrwIH472FuRb7RbWzwXA4+4ZBdl8D4An0dwtfvAO+jCZSrLjmSpxEOveJxY"
- + "GduyR4IA4lemvAG51YHTHd4NXheuEqsIkn1yarwaaj47lFPnxNOElOREMdZb"
- + "nkWQb1jfgqO24imEZgrLMkK9bJfoDnlF4k6r6hZOp5FSFvc5kJB4cVo1QJl4"
- + "pwCSdoU6luwCggrlZhDnkGCSuQUUW45NE7Br22NGqn4/gHs0KCsWbAezApGj"
- + "qYUCfX1bcpPzUMzUlBaD5rz2vPeO58CDtBJ0ZXN0ZXIgPHRlc3RAdGVzdD6I"
- + "sgQTAQIAHAUCQFdQ0wIbAwQLBwMCAxUCAwMWAgECHgECF4AACgkQs8JyyQfH"
- + "97I1QgP8Cd+35maM2cbWV9iVRO+c5456KDi3oIUSNdPf1NQrCAtJqEUhmMSt"
- + "QbdiaFEkPrORISI/2htXruYn0aIpkCfbUheHOu0sef7s6pHmI2kOQPzR+C/j"
- + "8D9QvWsPOOso81KU2axUY8zIer64Uzqc4szMIlLw06c8vea27RfgjBpSCryw"
- + "AgAA");
-
- private static readonly char[] rsaPass = "2002 Buffalo Sabres".ToCharArray();
-
- private static readonly byte[] nullPacketsSubKeyBinding = Base64.Decode(
- "iDYEGBECAAAAACp9AJ9PlJCrFpi+INwG7z61eku2Wg1HaQCgl33X5Egj+Kf7F9CXIWj2iFCvQDo=");
-
- public override void PerformTest()
- {
- //
- // RSA tests
- //
- PgpSecretKeyRing pgpPriv = new PgpSecretKeyRing(rsaKeyRing);
- PgpSecretKey secretKey = pgpPriv.GetSecretKey();
- PgpPrivateKey pgpPrivKey = secretKey.ExtractPrivateKey(rsaPass);
-
- try
- {
- doTestSig(PublicKeyAlgorithmTag.Dsa, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey);
-
- Fail("RSA wrong key test failed.");
- }
- catch (PgpException)
- {
- // expected
- }
-
- try
- {
- doTestSigV3(PublicKeyAlgorithmTag.Dsa, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey);
-
- Fail("RSA V3 wrong key test failed.");
- }
- catch (PgpException)
- {
- // expected
- }
-
- //
- // certifications
- //
- PgpSignatureGenerator sGen = new PgpSignatureGenerator(PublicKeyAlgorithmTag.RsaGeneral, HashAlgorithmTag.Sha1);
-
- sGen.InitSign(PgpSignature.KeyRevocation, pgpPrivKey);
-
- PgpSignature sig = sGen.GenerateCertification(secretKey.PublicKey);
-
- sig.InitVerify(secretKey.PublicKey);
-
- if (!sig.VerifyCertification(secretKey.PublicKey))
- {
- Fail("revocation verification failed.");
- }
-
- PgpSecretKeyRing pgpDSAPriv = new PgpSecretKeyRing(dsaKeyRing);
- PgpSecretKey secretDSAKey = pgpDSAPriv.GetSecretKey();
- PgpPrivateKey pgpPrivDSAKey = secretDSAKey.ExtractPrivateKey(dsaPass);
-
- sGen = new PgpSignatureGenerator(PublicKeyAlgorithmTag.Dsa, HashAlgorithmTag.Sha1);
-
- sGen.InitSign(PgpSignature.SubkeyBinding, pgpPrivDSAKey);
-
- PgpSignatureSubpacketGenerator unhashedGen = new PgpSignatureSubpacketGenerator();
- PgpSignatureSubpacketGenerator hashedGen = new PgpSignatureSubpacketGenerator();
-
- hashedGen.SetSignatureExpirationTime(false, TEST_EXPIRATION_TIME);
- hashedGen.SetSignerUserId(true, TEST_USER_ID);
- hashedGen.SetPreferredCompressionAlgorithms(false, PREFERRED_COMPRESSION_ALGORITHMS);
- hashedGen.SetPreferredHashAlgorithms(false, PREFERRED_HASH_ALGORITHMS);
- hashedGen.SetPreferredSymmetricAlgorithms(false, PREFERRED_SYMMETRIC_ALGORITHMS);
-
- sGen.SetHashedSubpackets(hashedGen.Generate());
- sGen.SetUnhashedSubpackets(unhashedGen.Generate());
-
- sig = sGen.GenerateCertification(secretDSAKey.PublicKey, secretKey.PublicKey);
+ [TestFixture]
+ public class PgpSignatureTest
+ : SimpleTest
+ {
+ private const int[] NO_PREFERENCES = null;
+ private static readonly int[] PREFERRED_SYMMETRIC_ALGORITHMS
+ = new int[] { (int)SymmetricKeyAlgorithmTag.Aes128, (int)SymmetricKeyAlgorithmTag.TripleDes };
+ private static readonly int[] PREFERRED_HASH_ALGORITHMS
+ = new int[] { (int)HashAlgorithmTag.Sha1, (int)HashAlgorithmTag.Sha256 };
+ private static readonly int[] PREFERRED_COMPRESSION_ALGORITHMS
+ = new int[] { (int)CompressionAlgorithmTag.ZLib };
+
+ private const int TEST_EXPIRATION_TIME = 10000;
+ private const string TEST_USER_ID = "test user id";
+ private static readonly byte[] TEST_DATA = Encoding.ASCII.GetBytes("hello world!\nhello world!\n");
+ private static readonly byte[] TEST_DATA_WITH_CRLF = Encoding.ASCII.GetBytes("hello world!\r\nhello world!\r\n");
+
+ private static readonly byte[] dsaKeyRing = Base64.Decode(
+ "lQHhBD9HBzURBACzkxRCVGJg5+Ld9DU4Xpnd4LCKgMq7YOY7Gi0EgK92gbaa6+zQ"
+ + "oQFqz1tt3QUmpz3YVkm/zLESBBtC1ACIXGggUdFMUr5I87+1Cb6vzefAtGt8N5VV"
+ + "1F/MXv1gJz4Bu6HyxL/ncfe71jsNhav0i4yAjf2etWFj53zK6R+Ojg5H6wCgpL9/"
+ + "tXVfGP8SqFvyrN/437MlFSUEAIN3V6j/MUllyrZglrtr2+RWIwRrG/ACmrF6hTug"
+ + "Ol4cQxaDYNcntXbhlTlJs9MxjTH3xxzylyirCyq7HzGJxZzSt6FTeh1DFYzhJ7Qu"
+ + "YR1xrSdA6Y0mUv0ixD5A4nPHjupQ5QCqHGeRfFD/oHzD4zqBnJp/BJ3LvQ66bERJ"
+ + "mKl5A/4uj3HoVxpb0vvyENfRqKMmGBISycY4MoH5uWfb23FffsT9r9KL6nJ4syLz"
+ + "aRR0gvcbcjkc9Z3epI7gr3jTrb4d8WPxsDbT/W1tv9bG/EHawomLcihtuUU68Uej"
+ + "6/wZot1XJqu2nQlku57+M/V2X1y26VKsipolPfja4uyBOOyvbP4DAwIDIBTxWjkC"
+ + "GGAWQO2jy9CTvLHJEoTO7moHrp1FxOVpQ8iJHyRqZzLllO26OzgohbiPYz8u9qCu"
+ + "lZ9Xn7QzRXJpYyBFY2hpZG5hIChEU0EgVGVzdCBLZXkpIDxlcmljQGJvdW5jeWNh"
+ + "c3RsZS5vcmc+iFkEExECABkFAj9HBzUECwcDAgMVAgMDFgIBAh4BAheAAAoJEM0j"
+ + "9enEyjRDAlwAnjTjjt57NKIgyym7OTCwzIU3xgFpAJ0VO5m5PfQKmGJRhaewLSZD"
+ + "4nXkHg==");
+
+ private static readonly char[] dsaPass = "hello world".ToCharArray();
+
+ private static readonly byte[] rsaKeyRing = Base64.Decode(
+ "lQIEBEBXUNMBBADScQczBibewnbCzCswc/9ut8R0fwlltBRxMW0NMdKJY2LF"
+ + "7k2COeLOCIU95loJGV6ulbpDCXEO2Jyq8/qGw1qD3SCZNXxKs3GS8Iyh9Uwd"
+ + "VL07nMMYl5NiQRsFB7wOb86+94tYWgvikVA5BRP5y3+O3GItnXnpWSJyREUy"
+ + "6WI2QQAGKf4JAwIVmnRs4jtTX2DD05zy2mepEQ8bsqVAKIx7lEwvMVNcvg4Y"
+ + "8vFLh9Mf/uNciwL4Se/ehfKQ/AT0JmBZduYMqRU2zhiBmxj4cXUQ0s36ysj7"
+ + "fyDngGocDnM3cwPxaTF1ZRBQHSLewP7dqE7M73usFSz8vwD/0xNOHFRLKbsO"
+ + "RqDlLA1Cg2Yd0wWPS0o7+qqk9ndqrjjSwMM8ftnzFGjShAdg4Ca7fFkcNePP"
+ + "/rrwIH472FuRb7RbWzwXA4+4ZBdl8D4An0dwtfvAO+jCZSrLjmSpxEOveJxY"
+ + "GduyR4IA4lemvAG51YHTHd4NXheuEqsIkn1yarwaaj47lFPnxNOElOREMdZb"
+ + "nkWQb1jfgqO24imEZgrLMkK9bJfoDnlF4k6r6hZOp5FSFvc5kJB4cVo1QJl4"
+ + "pwCSdoU6luwCggrlZhDnkGCSuQUUW45NE7Br22NGqn4/gHs0KCsWbAezApGj"
+ + "qYUCfX1bcpPzUMzUlBaD5rz2vPeO58CDtBJ0ZXN0ZXIgPHRlc3RAdGVzdD6I"
+ + "sgQTAQIAHAUCQFdQ0wIbAwQLBwMCAxUCAwMWAgECHgECF4AACgkQs8JyyQfH"
+ + "97I1QgP8Cd+35maM2cbWV9iVRO+c5456KDi3oIUSNdPf1NQrCAtJqEUhmMSt"
+ + "QbdiaFEkPrORISI/2htXruYn0aIpkCfbUheHOu0sef7s6pHmI2kOQPzR+C/j"
+ + "8D9QvWsPOOso81KU2axUY8zIer64Uzqc4szMIlLw06c8vea27RfgjBpSCryw"
+ + "AgAA");
+
+ private static readonly char[] rsaPass = "2002 Buffalo Sabres".ToCharArray();
+
+ private static readonly byte[] nullPacketsSubKeyBinding = Base64.Decode(
+ "iDYEGBECAAAAACp9AJ9PlJCrFpi+INwG7z61eku2Wg1HaQCgl33X5Egj+Kf7F9CXIWj2iFCvQDo=");
+
+ private static readonly byte[] okAttr = Base64.Decode(
+ "mQENBFOkuoMBCAC+8WcWLBZovlR5pLW4tbOoH3APia+poMEeTNkXKe8yAH0f"
+ + "ZmTQgeXFBIizd4Ka1QETbayv+C6Axt6Ipdwf+3N/lqcOqg6PEwuIX4MBrv5R"
+ + "ILMH5QyM3a3RlyXa7xES3I9t2VHiZvl15OrTZe67YNGtxlXyeawt6v/9d/a3"
+ + "M1EaUzjN4H2EfI3P/VWpMUvQkn70996UKInOyaSB0hef/QS10jshG9DdgmLM"
+ + "1/mJFRp8ynZOV4yGLnAdoEoPGG/HJZEzWfqOiwmWZOIrZIwedY1eKuMIhUGv"
+ + "LTC9u+9X0h+Y0st5eb1pf8OLvrpRpEyHMrxXfj/V3rxom4d160ifGihPABEB"
+ + "AAG0GndpdGggYXR0dHIgPGF0dHJAYXR0ci5uZXQ+iQE4BBMBAgAiBQJTpLqD"
+ + "AhsDBgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAKCRBCjbg0bKVgCXJiB/wO"
+ + "6ksdrAy+zVxygFhk6Ju2vpMAOGnLl1nqBVT1mA5XiJu3rSiJmROLF2l21K0M"
+ + "BICZfz+mjIwN56RZNzZnEmXk/E2+PgADV5VTRRsjqlyoeN/NrLWuTm9FyngJ"
+ + "f96jVPysN6FzYRUB5Fuys57P+nu0RMoLGkHmQhp4L5hgNJTBy1SRnXukoIgJ"
+ + "2Ra3EBQ7dBrzuWW1ycwU5acfOoxfcVqgXkiXaxgvujFChZGWT6djbnbbzlMm"
+ + "sMKr6POKChEPWo1HJXXz1OaPsd75JA8bImgnrHhB3dHhD2wIqzQrtTxvraqz"
+ + "ZWWR2xYZPltzBSlaAdn8Hf0GGBoMhutb3tJLzbAX0cybzJkBEAABAQAAAAAA"
+ + "AAAAAAAAAP/Y/+AAEEpGSUYAAQEAAAEAAQAA/9sAQwAKBwcIBwYKCAgICwoK"
+ + "Cw4YEA4NDQ4dFRYRGCMfJSQiHyIhJis3LyYpNCkhIjBBMTQ5Oz4+PiUuRElD"
+ + "PEg3PT47/9sAQwEKCwsODQ4cEBAcOygiKDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7"
+ + "Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7/8AAEQgAkAB4AwEiAAIR"
+ + "AQMRAf/EAB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYHCAkKC//EALUQAAIB"
+ + "AwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHw"
+ + "JDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVm"
+ + "Z2hpanN0dXZ3eHl6g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4"
+ + "ubrCw8TFxsfIycrS09TV1tfY2drh4uPk5ebn6Onq8fLz9PX29/j5+v/EAB8B"
+ + "AAMBAQEBAQEBAQEAAAAAAAABAgMEBQYHCAkKC//EALURAAIBAgQEAwQHBQQE"
+ + "AAECdwABAgMRBAUhMQYSQVEHYXETIjKBCBRCkaGxwQkjM1LwFWJy0QoWJDTh"
+ + "JfEXGBkaJicoKSo1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2"
+ + "d3h5eoKDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXG"
+ + "x8jJytLT1NXW19jZ2uLj5OXm5+jp6vLz9PX29/j5+v/aAAwDAQACEQMRAD8A"
+ + "9moqtf30Gm2cl3cvtijGSa4a++LNlGStlZvKR0ZuBWkKU6nwomU4x3PQqK8g"
+ + "uPinrEzYhhihX86ns/Ffia/XzElJUHOV4/rW/wBUqJXlZEe2i9j1iivMP+Ex"
+ + "1q3+/KCw6gip4PiXdREC5tUkHcrwaTwlVbK4e1iekUVzmheNdO1ycWyK8U5G"
+ + "drf410QOa55RcXaSNE09ULRRRUjCiiigAooooAKKKKAOY+IblfCN1g9cA/rX"
+ + "h1fQPiXT4dU0o2dwXEcrclCARgE8ZB9K4J/AGkKeJr38ZU/+Ir0MLiIUoNSO"
+ + "erTlJ3R54v3hXpfg3UdNGmrHPMsToOc9+KrQeBdAd2SS7vkYdPnX/wCIqy3g"
+ + "fRoThb+9GP8AaQ/+yVdavRqxs2yYU5wdzH164t57+V7XHlZOCOh5rn5n5Ndr"
+ + "J4U0xBt/tC8x16p/8RTP+EK0uRQ32q9IPfzE/wDiKuGKpRSSYnSm3c5/wjP5"
+ + "XiKFywUDqScelevR6/pCR4k1S0DDqPOXI/WvPLjwdplpbtPG9zI6so2yspU5"
+ + "YDoFHrW7pOmRWpEiqVyuPlHH41xYmPgpPmibU4uKszqY9f0aZtseq2bN6eeu"
+ + "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"
+ + "0GvLdt0Lx24c"
+ );
+
+ private static readonly byte[] attrLongLength = Base64.Decode(
+ "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"
+ + "/9sAQwAKBwcIBwYKCAgICwoKCw4YEA4NDQ4dFRYRGCMfJSQiHyIhJis3LyYp"
+ + "NCkhIjBBMTQ5Oz4+PiUuRElDPEg3PT47/9sAQwEKCwsODQ4cEBAcOygiKDs7"
+ + "Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7"
+ + "Ozs7/8AAEQgAkAB4AwEiAAIRAQMRAf/EAB8AAAEFAQEBAQEBAAAAAAAAAAAB"
+ + "AgMEBQYHCAkKC//EALUQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNR"
+ + "YQcicRQygZGhCCNCscEVUtHwJDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNE"
+ + "RUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6g4SFhoeIiYqSk5SVlpeY"
+ + "mZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk5ebn"
+ + "6Onq8fLz9PX29/j5+v/EAB8BAAMBAQEBAQEBAQEAAAAAAAABAgMEBQYHCAkK"
+ + "C//EALURAAIBAgQEAwQHBQQEAAECdwABAgMRBAUhMQYSQVEHYXETIjKBCBRC"
+ + "kaGxwQkjM1LwFWJy0QoWJDThJfEXGBkaJicoKSo1Njc4OTpDREVGR0hJSlNU"
+ + "VVZXWFlaY2RlZmdoaWpzdHV2d3h5eoKDhIWGh4iJipKTlJWWl5iZmqKjpKWm"
+ + "p6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uLj5OXm5+jp6vLz9PX2"
+ + "9/j5+v/aAAwDAQACEQMRAD8A9moqtf30Gm2cl3cvtijGSa4a++LNlGStlZvK"
+ + "R0ZuBWkKU6nwomU4x3PQqK8guPinrEzYhhihX86ns/Ffia/XzElJUHOV4/rW"
+ + "/wBUqJXlZEe2i9j1iivMP+Ex1q3+/KCw6gip4PiXdREC5tUkHcrwaTwlVbK4"
+ + "e1iekUVzmheNdO1ycWyK8U5Gdrf410QOa55RcXaSNE09ULRRRUjCiiigAooo"
+ + "oAKKKKAOY+IblfCN1g9cA/rXh1fQPiXT4dU0o2dwXEcrclCARgE8ZB9K4J/A"
+ + "GkKeJr38ZU/+Ir0MLiIUoNSOerTlJ3R54v3hXpfg3UdNGmrHPMsToOc9+KrQ"
+ + "eBdAd2SS7vkYdPnX/wCIqy3gfRoThb+9GP8AaQ/+yVdavRqxs2yYU5wdzH16"
+ + "4t57+V7XHlZOCOh5rn5n5NdrJ4U0xBt/tC8x16p/8RTP+EK0uRQ32q9IPfzE"
+ + "/wDiKuGKpRSSYnSm3c5/wjP5XiKFywUDqScelevR6/pCR4k1S0DDqPOXI/Wv"
+ + "PLjwdplpbtPG9zI6so2yspU5YDoFHrW7pOmRWpEiqVyuPlHH41xYmPgpPmib"
+ + "U4uKszqY9f0aZtseq2bN6eeuf51fVldQyMGU9CDkGueMCOpxtYe3NYWoabJJ"
+ + "OZrWV7V1yFe1cxnH1HX8a57Glz0CiuFg8U6rpjql2PtkXTMgCv8Agw4/MfjX"
+ + "U6VrthrCH7NKRIoy8LjDr+Hp7jIosFzRooopDCiiigClqXKRD1c/+gtWPLFi"
+ + "tnUfuRH/AG//AGUiqDKGFAzAmFzG7rGhAJJyB604XtzGGjeAuD3GR2x260t1"
+ + "fTJf3EChAsLKo+XOcorZP/fVQm8lPXZ/3yKLCJDPIBsjUjIHUewFWoYWS2jD"
+ + "DBArPN1IQR8o/wCAirdvcERwu33ZYkdgOgLKCcfnRYBL0f8AEvmz6x/+jUqx"
+ + "bzyCLCKoC92NRaiMWLkHhmj/AB+dTWlarutdoIXI64oQETXJ25MbA9DsolCE"
+ + "Y4zjpVswL5QXgMB1xWZMRDIywoJn6HnAWmIzb+GZyyIisD0Vl4Nc5I0ulXSO"
+ + "8zQtnMTrkGM/71dVNpufnMkm7Odwfmqd5CGi8tuQB0b5v51SEzf8M+Kl1Qix"
+ + "vdqXoHysOFmA7j0PqPxHoOlrxm5DROrRkxvGQVZOCpHQivSPCfiEa9px80gX"
+ + "lvhZ1Hf0Yex/mDRKNtQTN6iiioKKmoD9zGfSVf1OP61QrUuovOgZM4PBB9CD"
+ + "kH865PxJrVx4d057yS0inAcIqq5TJJ+hoAqXg/4m9/8A9dU/9FR1CRUGlan/"
+ + "AG7Fcal9n+z+dNjy9+/btRV64GemelWiKoRHVuIf6Ha/9e0X/oC1VIrIt/Ft"
+ + "xNGsFtoxk+zoITI1zhWKjbn7vt0zSYzfvJSLAIennIB+p/pWtZy4hXmuQa71"
+ + "fUzGhtre1jR920MXLHGMk+2T6da1oZb22ULM6FDwGCkHNFhGzNqCbjAmXkPG"
+ + "F7VJFAkEQHBNQWkMUcQIwc859fepJJeOtNIVyK4bg1jXjda0LiTg1k3b9atE"
+ + "sxr3qai0LWDoOvQXpYiEny5x6oep/Dg/hT7s9ayLoZVs1VriPeQcjIorC8F3"
+ + "7ah4Vs3kbdLCvkyexXjn3xg/jRWBqb1ee/FqYLpun24P+snLMPoOK9Crzb4u"
+ + "KQumSfwl2H44qo7iexB4JQHRwCMj7Q39K2roRRXTkqPLU8iuB8NFl8S6ftdg"
+ + "rSHIycH5T2rvb8b2uap6MS1RDJcWsq7YUCt65J4rA0FUCHKjh2/9CNYfjDUS"
+ + "kS2lskrlHDTSR/8ALPjocUaH4msUtVjCM0qLyqkAH8TyKSBnoELoOgFJf3Vo"
+ + "ITFcTBNy546gevtzXM6Rqd3fakWadyigsYw3y+gAH410O/PDZHHcU7E3LWnX"
+ + "ED2SC2nE0ajG4HJ/GpJJeOtYlxYpJdxXMcssLxkE+SwXdj14qrf6jrP22SK0"
+ + "t4RFkFZZMYx/n8aANieXg1mXMnWla5lKRCSMFmB8xoz8qHHvzg1TnlzVIRTu"
+ + "W61l3MyQRSTuNwjXdt9T2FXZ3zWfcRpPG8Mn3JBtJ9PQ/nVCO7+Dl49z4f1B"
+ + "JG3Mt6XJ/wB5V/woqD4LwvDpurK45W5VT9QtFYPc1Wx6VXDfFi0M3hmG6A5t"
+ + "rhSfoRj/AAruaz9d01dY0O809v8AlvEVX2bt+uKFowZ4z4Zbd4h04/8ATRv/"
+ + "AEBq7+T53ufrXnXhffF4ls4JQVkildWB7EKwNehwnfLcD/aFXLcUThGs5bDU"
+ + "pYrgFWZ2dGHR1J6ip57C0voRHcQq6htwI+Ug4xkEVo+MJ0jksrYA+ZuMhPou"
+ + "MfzP6VnQyEqKqOqJejMmfSr/AE8NNbzC6hjG7aQVlA/kcVueFtR+12Mrpcea"
+ + "gk4Abdt4/rUiMeOeaqS6UhuVubSaWymxtdrbC+YvoR6+9FhHRPcCNGaRgiqN"
+ + "zFjgAVmya/pYkZftSnH8QQlT9D3rmdbefT4o7KO6ne3ky+yV9xBB9euO+Kw2"
+ + "mfruNAj0OW8t/K837TB5eM7/ADBjFVp3IAOQQwyCDkEexrz95W9vrirula1L"
+ + "YyiOQu9s2Q0YPT3GehpgdJK2apzt8hottQgv1k8pZEeMZIYg5GcZyKjuFkkK"
+ + "QxKXklYKijqSeAKdwPUvhdbeX4ZmutpH2y7eUZ9AAv8ANTRXSaJpqaPotnpy"
+ + "YP2eIKxHdv4j+JyaKwe5qi/RRRSGeaeJ/Dx03x7Yavbr/o967eZj+GQI38xz"
+ + "+dXdPffczD1cVu+Lzi0tT6Tj/wBBNc3oz7r5x6uKroIwPFt5BeazFbQKGa1B"
+ + "WSQdycfL+GP1qCCPgU3+yprC/ltrpcSqxOezAnhge9aMNv04rRaIh7jEiNSS"
+ + "FLeF55c7I1LNjrgVcjt/alu9O+12U1uSUEqFNyjlcjrRcVjzzVL6bU5xJIio"
+ + "qjCIo4Uf1NUDEfStiXTLizuHtboL5qc7l6OvZhTTZ+1K4WMZoSe1NFuSelbP"
+ + "2M9xT47As2FXJp3FYqaUptJ2fZu3IVwSR1r0L4f6FHqmsf2w8bC3sjhA2CGl"
+ + "x29duc/UisHQ/DlzreoiwtPl24NxPjKwL/Vj2H9K9m07T7bStPhsbOPy4IV2"
+ + "qO/uT6knkmoky4otUUUVBYUUUUAc54yP+hWv/XwB+hrntOTyNbSP+84rs9Z0"
+ + "4ajaqu7a8bh0OMjI9a5O6gvob3zjZAuDwyOMfryKaegEHjZTYva6qV8yFf3M"
+ + "qKMsueQw9uDmq+nPZahGJLSdHz2zyKsXEOpagyC4IWOM5WNOmfUnuaxtT8NO"
+ + "JPtFoGt5uu6PjP4U0xNHSx2bjtmrC2p/u1xEOr+J9MO1sXCj++OavxeO9Tj4"
+ + "m0vJ9jTuI09c8NrqUavGfKuI/wDVyhc49iO4rnToV/A/lXCI5xkPGCFI/HvW"
+ + "hL491BhiLSufc1l6hrXiTVZQIALaPGOFyfc0gHzadBZxGW9nSFBydxp+nafP"
+ + "rEii0RrOyP3rmRfncf7Cn+Z/Wo9K8NXEl0Lm+L3EgOQZTux9K7W0s5BgYNFw"
+ + "sbOg2tlpVilnYxCOMHJ7s7HqxPc1sqcjNZNnbsuM1qoMLUlD6KKKACiiigBC"
+ + "M1E9tG55UVNRQBWNlF2UVC+mxP8Aw1fooAx5NDgfqg/KoG8N2p/5ZL+Vb9FA"
+ + "HPjw1ag/6pfyqZNBt06IPyraooAzU0qJOiirCWcadBVqigBixhegp1LRQAUU"
+ + "UUAf/9mJAVYEEAECADgFAkJRtHAHCwkIBwMCChkYbGRhcDovL2tleXNlcnZl"
+ + "ci5wZ3AuY29tBRsDAAAAAxYCAQUeAQAAAAASCRCXELibyletfAdlR1BHAAEB"
+ + "SBIH/j+RGcMuHmVoZq4+XbmCunnbft4T0Ta4o6mxNkc6wk5P9PpcE9ixztjV"
+ + "ysMmv2i4Y746dCY9B1tfhQW10S39HzrYHh3I4a2wb9zQniZCf1XnbCe1eRss"
+ + "NhTpLVXXnXKEsc9EwD5MtiPICluZIXB08Zx2uJSZ+/i9TqSM5EUuJk+lXqgX"
+ + "GUiTaSXN63I/4BnbFzCw8SaST7d7nok45UC9I/+gcKVO+oYETgrsU7AL6uk1"
+ + "6YD9JpfYZHEFmpYoS+qQ3tLfPCG3gaS/djBZWWkNt5z7e6sbRko49XEj3EUh"
+ + "33HgjrOlL8uJNbhlZ5NeILcxHqGTHji+5wMEDBjfNT/C6m0=");
+
+ public override void PerformTest()
+ {
+ //
+ // RSA tests
+ //
+ PgpSecretKeyRing pgpPriv = new PgpSecretKeyRing(rsaKeyRing);
+ PgpSecretKey secretKey = pgpPriv.GetSecretKey();
+ PgpPrivateKey pgpPrivKey = secretKey.ExtractPrivateKey(rsaPass);
+
+ try
+ {
+ doTestSig(PublicKeyAlgorithmTag.Dsa, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey);
+
+ Fail("RSA wrong key test failed.");
+ }
+ catch (PgpException)
+ {
+ // expected
+ }
+
+ try
+ {
+ doTestSigV3(PublicKeyAlgorithmTag.Dsa, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey);
+
+ Fail("RSA V3 wrong key test failed.");
+ }
+ catch (PgpException)
+ {
+ // expected
+ }
+
+ //
+ // certifications
+ //
+ PgpSignatureGenerator sGen = new PgpSignatureGenerator(PublicKeyAlgorithmTag.RsaGeneral, HashAlgorithmTag.Sha1);
+
+ sGen.InitSign(PgpSignature.KeyRevocation, pgpPrivKey);
+
+ PgpSignature sig = sGen.GenerateCertification(secretKey.PublicKey);
+
+ sig.InitVerify(secretKey.PublicKey);
+
+ if (!sig.VerifyCertification(secretKey.PublicKey))
+ {
+ Fail("revocation verification failed.");
+ }
+
+ PgpSecretKeyRing pgpDSAPriv = new PgpSecretKeyRing(dsaKeyRing);
+ PgpSecretKey secretDSAKey = pgpDSAPriv.GetSecretKey();
+ PgpPrivateKey pgpPrivDSAKey = secretDSAKey.ExtractPrivateKey(dsaPass);
+
+ sGen = new PgpSignatureGenerator(PublicKeyAlgorithmTag.Dsa, HashAlgorithmTag.Sha1);
+
+ sGen.InitSign(PgpSignature.SubkeyBinding, pgpPrivDSAKey);
+
+ PgpSignatureSubpacketGenerator unhashedGen = new PgpSignatureSubpacketGenerator();
+ PgpSignatureSubpacketGenerator hashedGen = new PgpSignatureSubpacketGenerator();
+
+ hashedGen.SetSignatureExpirationTime(false, TEST_EXPIRATION_TIME);
+ hashedGen.SetSignerUserId(true, TEST_USER_ID);
+ hashedGen.SetPreferredCompressionAlgorithms(false, PREFERRED_COMPRESSION_ALGORITHMS);
+ hashedGen.SetPreferredHashAlgorithms(false, PREFERRED_HASH_ALGORITHMS);
+ hashedGen.SetPreferredSymmetricAlgorithms(false, PREFERRED_SYMMETRIC_ALGORITHMS);
+
+ sGen.SetHashedSubpackets(hashedGen.Generate());
+ sGen.SetUnhashedSubpackets(unhashedGen.Generate());
+
+ sig = sGen.GenerateCertification(secretDSAKey.PublicKey, secretKey.PublicKey);
+
+ byte[] sigBytes = sig.GetEncoded();
+
+ PgpObjectFactory f = new PgpObjectFactory(sigBytes);
+
+ sig = ((PgpSignatureList) f.NextPgpObject())[0];
+
+ sig.InitVerify(secretDSAKey.PublicKey);
+
+ if (!sig.VerifyCertification(secretDSAKey.PublicKey, secretKey.PublicKey))
+ {
+ Fail("subkey binding verification failed.");
+ }
+
+ PgpSignatureSubpacketVector hashedPcks = sig.GetHashedSubPackets();
+ PgpSignatureSubpacketVector unhashedPcks = sig.GetUnhashedSubPackets();
- byte[] sigBytes = sig.GetEncoded();
+ if (hashedPcks.Count != 6)
+ {
+ Fail("wrong number of hashed packets found.");
+ }
- PgpObjectFactory f = new PgpObjectFactory(sigBytes);
+ if (unhashedPcks.Count != 1)
+ {
+ Fail("wrong number of unhashed packets found.");
+ }
- sig = ((PgpSignatureList) f.NextPgpObject())[0];
+ if (!hashedPcks.GetSignerUserId().Equals(TEST_USER_ID))
+ {
+ Fail("test userid not matching");
+ }
- sig.InitVerify(secretDSAKey.PublicKey);
-
- if (!sig.VerifyCertification(secretDSAKey.PublicKey, secretKey.PublicKey))
- {
- Fail("subkey binding verification failed.");
- }
+ if (hashedPcks.GetSignatureExpirationTime() != TEST_EXPIRATION_TIME)
+ {
+ Fail("test signature expiration time not matching");
+ }
- PgpSignatureSubpacketVector hashedPcks = sig.GetHashedSubPackets();
- PgpSignatureSubpacketVector unhashedPcks = sig.GetUnhashedSubPackets();
+ if (unhashedPcks.GetIssuerKeyId() != secretDSAKey.KeyId)
+ {
+ Fail("wrong issuer key ID found in certification");
+ }
- if (hashedPcks.Count != 6)
- {
- Fail("wrong number of hashed packets found.");
- }
+ int[] prefAlgs = hashedPcks.GetPreferredCompressionAlgorithms();
+ preferredAlgorithmCheck("compression", PREFERRED_COMPRESSION_ALGORITHMS, prefAlgs);
- if (unhashedPcks.Count != 1)
- {
- Fail("wrong number of unhashed packets found.");
- }
+ prefAlgs = hashedPcks.GetPreferredHashAlgorithms();
+ preferredAlgorithmCheck("hash", PREFERRED_HASH_ALGORITHMS, prefAlgs);
- if (!hashedPcks.GetSignerUserId().Equals(TEST_USER_ID))
- {
- Fail("test userid not matching");
- }
+ prefAlgs = hashedPcks.GetPreferredSymmetricAlgorithms();
+ preferredAlgorithmCheck("symmetric", PREFERRED_SYMMETRIC_ALGORITHMS, prefAlgs);
- if (hashedPcks.GetSignatureExpirationTime() != TEST_EXPIRATION_TIME)
- {
- Fail("test signature expiration time not matching");
- }
+ SignatureSubpacketTag[] criticalHashed = hashedPcks.GetCriticalTags();
- if (unhashedPcks.GetIssuerKeyId() != secretDSAKey.KeyId)
- {
- Fail("wrong issuer key ID found in certification");
- }
+ if (criticalHashed.Length != 1)
+ {
+ Fail("wrong number of critical packets found.");
+ }
- int[] prefAlgs = hashedPcks.GetPreferredCompressionAlgorithms();
- preferredAlgorithmCheck("compression", PREFERRED_COMPRESSION_ALGORITHMS, prefAlgs);
+ if (criticalHashed[0] != SignatureSubpacketTag.SignerUserId)
+ {
+ Fail("wrong critical packet found in tag list.");
+ }
- prefAlgs = hashedPcks.GetPreferredHashAlgorithms();
- preferredAlgorithmCheck("hash", PREFERRED_HASH_ALGORITHMS, prefAlgs);
+ //
+ // no packets passed
+ //
+ sGen = new PgpSignatureGenerator(PublicKeyAlgorithmTag.Dsa, HashAlgorithmTag.Sha1);
- prefAlgs = hashedPcks.GetPreferredSymmetricAlgorithms();
- preferredAlgorithmCheck("symmetric", PREFERRED_SYMMETRIC_ALGORITHMS, prefAlgs);
+ sGen.InitSign(PgpSignature.SubkeyBinding, pgpPrivDSAKey);
- SignatureSubpacketTag[] criticalHashed = hashedPcks.GetCriticalTags();
+ sGen.SetHashedSubpackets(null);
+ sGen.SetUnhashedSubpackets(null);
- if (criticalHashed.Length != 1)
- {
- Fail("wrong number of critical packets found.");
- }
+ sig = sGen.GenerateCertification(TEST_USER_ID, secretKey.PublicKey);
- if (criticalHashed[0] != SignatureSubpacketTag.SignerUserId)
- {
- Fail("wrong critical packet found in tag list.");
- }
+ sig.InitVerify(secretDSAKey.PublicKey);
- //
- // no packets passed
- //
- sGen = new PgpSignatureGenerator(PublicKeyAlgorithmTag.Dsa, HashAlgorithmTag.Sha1);
+ if (!sig.VerifyCertification(TEST_USER_ID, secretKey.PublicKey))
+ {
+ Fail("subkey binding verification failed.");
+ }
- sGen.InitSign(PgpSignature.SubkeyBinding, pgpPrivDSAKey);
+ hashedPcks = sig.GetHashedSubPackets();
- sGen.SetHashedSubpackets(null);
- sGen.SetUnhashedSubpackets(null);
+ if (hashedPcks.Count != 1)
+ {
+ Fail("found wrong number of hashed packets");
+ }
- sig = sGen.GenerateCertification(TEST_USER_ID, secretKey.PublicKey);
+ unhashedPcks = sig.GetUnhashedSubPackets();
- sig.InitVerify(secretDSAKey.PublicKey);
+ if (unhashedPcks.Count != 1)
+ {
+ Fail("found wrong number of unhashed packets");
+ }
- if (!sig.VerifyCertification(TEST_USER_ID, secretKey.PublicKey))
- {
- Fail("subkey binding verification failed.");
- }
+ try
+ {
+ sig.VerifyCertification(secretKey.PublicKey);
- hashedPcks = sig.GetHashedSubPackets();
+ Fail("failed to detect non-key signature.");
+ }
+ catch (InvalidOperationException)
+ {
+ // expected
+ }
- if (hashedPcks.Count != 1)
- {
- Fail("found wrong number of hashed packets");
- }
+ //
+ // override hash packets
+ //
+ sGen = new PgpSignatureGenerator(PublicKeyAlgorithmTag.Dsa, HashAlgorithmTag.Sha1);
- unhashedPcks = sig.GetUnhashedSubPackets();
+ sGen.InitSign(PgpSignature.SubkeyBinding, pgpPrivDSAKey);
- if (unhashedPcks.Count != 1)
- {
- Fail("found wrong number of unhashed packets");
- }
+ hashedGen = new PgpSignatureSubpacketGenerator();
- try
- {
- sig.VerifyCertification(secretKey.PublicKey);
+ DateTime creationTime = new DateTime(1973, 7, 27);
+ hashedGen.SetSignatureCreationTime(false, creationTime);
- Fail("failed to detect non-key signature.");
- }
- catch (InvalidOperationException)
- {
- // expected
- }
+ sGen.SetHashedSubpackets(hashedGen.Generate());
- //
- // override hash packets
- //
- sGen = new PgpSignatureGenerator(PublicKeyAlgorithmTag.Dsa, HashAlgorithmTag.Sha1);
+ sGen.SetUnhashedSubpackets(null);
- sGen.InitSign(PgpSignature.SubkeyBinding, pgpPrivDSAKey);
+ sig = sGen.GenerateCertification(TEST_USER_ID, secretKey.PublicKey);
- hashedGen = new PgpSignatureSubpacketGenerator();
+ sig.InitVerify(secretDSAKey.PublicKey);
- DateTime creationTime = new DateTime(1973, 7, 27);
- hashedGen.SetSignatureCreationTime(false, creationTime);
+ if (!sig.VerifyCertification(TEST_USER_ID, secretKey.PublicKey))
+ {
+ Fail("subkey binding verification failed.");
+ }
- sGen.SetHashedSubpackets(hashedGen.Generate());
+ hashedPcks = sig.GetHashedSubPackets();
+
+ if (hashedPcks.Count != 1)
+ {
+ Fail("found wrong number of hashed packets in override test");
+ }
+
+ if (!hashedPcks.HasSubpacket(SignatureSubpacketTag.CreationTime))
+ {
+ Fail("hasSubpacket test for creation time failed");
+ }
- sGen.SetUnhashedSubpackets(null);
+ DateTime sigCreationTime = hashedPcks.GetSignatureCreationTime();
+ if (!sigCreationTime.Equals(creationTime))
+ {
+ Fail("creation of overridden date failed.");
+ }
- sig = sGen.GenerateCertification(TEST_USER_ID, secretKey.PublicKey);
+ prefAlgs = hashedPcks.GetPreferredCompressionAlgorithms();
+ preferredAlgorithmCheck("compression", NO_PREFERENCES, prefAlgs);
- sig.InitVerify(secretDSAKey.PublicKey);
+ prefAlgs = hashedPcks.GetPreferredHashAlgorithms();
+ preferredAlgorithmCheck("hash", NO_PREFERENCES, prefAlgs);
- if (!sig.VerifyCertification(TEST_USER_ID, secretKey.PublicKey))
- {
- Fail("subkey binding verification failed.");
- }
+ prefAlgs = hashedPcks.GetPreferredSymmetricAlgorithms();
+ preferredAlgorithmCheck("symmetric", NO_PREFERENCES, prefAlgs);
- hashedPcks = sig.GetHashedSubPackets();
-
- if (hashedPcks.Count != 1)
- {
- Fail("found wrong number of hashed packets in override test");
- }
-
- if (!hashedPcks.HasSubpacket(SignatureSubpacketTag.CreationTime))
- {
- Fail("hasSubpacket test for creation time failed");
- }
+ if (hashedPcks.GetKeyExpirationTime() != 0)
+ {
+ Fail("unexpected key expiration time found");
+ }
- DateTime sigCreationTime = hashedPcks.GetSignatureCreationTime();
- if (!sigCreationTime.Equals(creationTime))
- {
- Fail("creation of overridden date failed.");
- }
-
- prefAlgs = hashedPcks.GetPreferredCompressionAlgorithms();
- preferredAlgorithmCheck("compression", NO_PREFERENCES, prefAlgs);
-
- prefAlgs = hashedPcks.GetPreferredHashAlgorithms();
- preferredAlgorithmCheck("hash", NO_PREFERENCES, prefAlgs);
-
- prefAlgs = hashedPcks.GetPreferredSymmetricAlgorithms();
- preferredAlgorithmCheck("symmetric", NO_PREFERENCES, prefAlgs);
-
- if (hashedPcks.GetKeyExpirationTime() != 0)
- {
- Fail("unexpected key expiration time found");
- }
-
- if (hashedPcks.GetSignatureExpirationTime() != 0)
- {
- Fail("unexpected signature expiration time found");
- }
-
- if (hashedPcks.GetSignerUserId() != null)
- {
- Fail("unexpected signer user ID found");
- }
-
- criticalHashed = hashedPcks.GetCriticalTags();
-
- if (criticalHashed.Length != 0)
- {
- Fail("critical packets found when none expected");
- }
-
- unhashedPcks = sig.GetUnhashedSubPackets();
-
- if (unhashedPcks.Count != 1)
- {
- Fail("found wrong number of unhashed packets in override test");
- }
-
- //
- // general signatures
- //
- doTestSig(PublicKeyAlgorithmTag.RsaGeneral, HashAlgorithmTag.Sha256, secretKey.PublicKey, pgpPrivKey);
- doTestSig(PublicKeyAlgorithmTag.RsaGeneral, HashAlgorithmTag.Sha384, secretKey.PublicKey, pgpPrivKey);
- doTestSig(PublicKeyAlgorithmTag.RsaGeneral, HashAlgorithmTag.Sha512, secretKey.PublicKey, pgpPrivKey);
- doTestSigV3(PublicKeyAlgorithmTag.RsaGeneral, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey);
- doTestTextSig(PublicKeyAlgorithmTag.RsaGeneral, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey, TEST_DATA_WITH_CRLF, TEST_DATA_WITH_CRLF);
- doTestTextSig(PublicKeyAlgorithmTag.RsaGeneral, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey, TEST_DATA, TEST_DATA_WITH_CRLF);
- doTestTextSigV3(PublicKeyAlgorithmTag.RsaGeneral, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey, TEST_DATA_WITH_CRLF, TEST_DATA_WITH_CRLF);
- doTestTextSigV3(PublicKeyAlgorithmTag.RsaGeneral, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey, TEST_DATA, TEST_DATA_WITH_CRLF);
-
- //
- // DSA Tests
- //
- pgpPriv = new PgpSecretKeyRing(dsaKeyRing);
- secretKey = pgpPriv.GetSecretKey();
- pgpPrivKey = secretKey.ExtractPrivateKey(dsaPass);
-
- try
- {
- doTestSig(PublicKeyAlgorithmTag.RsaGeneral, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey);
-
- Fail("DSA wrong key test failed.");
- }
- catch (PgpException)
- {
- // expected
- }
-
- try
- {
- doTestSigV3(PublicKeyAlgorithmTag.RsaGeneral, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey);
-
- Fail("DSA V3 wrong key test failed.");
- }
- catch (PgpException)
- {
- // expected
- }
-
- doTestSig(PublicKeyAlgorithmTag.Dsa, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey);
- doTestSigV3(PublicKeyAlgorithmTag.Dsa, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey);
- doTestTextSig(PublicKeyAlgorithmTag.Dsa, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey, TEST_DATA_WITH_CRLF, TEST_DATA_WITH_CRLF);
- doTestTextSig(PublicKeyAlgorithmTag.Dsa, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey, TEST_DATA, TEST_DATA_WITH_CRLF);
- doTestTextSigV3(PublicKeyAlgorithmTag.Dsa, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey, TEST_DATA_WITH_CRLF, TEST_DATA_WITH_CRLF);
- doTestTextSigV3(PublicKeyAlgorithmTag.Dsa, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey, TEST_DATA, TEST_DATA_WITH_CRLF);
-
- // special cases
- //
- doTestMissingSubpackets(nullPacketsSubKeyBinding);
-
- doTestMissingSubpackets(generateV3BinarySig(pgpPrivKey, PublicKeyAlgorithmTag.Dsa, HashAlgorithmTag.Sha1));
-
- // keyflags
- doTestKeyFlagsValues();
- }
-
- private void doTestKeyFlagsValues()
- {
- checkValue(KeyFlags.CertifyOther, 0x01);
- checkValue(KeyFlags.SignData, 0x02);
- checkValue(KeyFlags.EncryptComms, 0x04);
- checkValue(KeyFlags.EncryptStorage, 0x08);
- checkValue(KeyFlags.Split, 0x10);
- checkValue(KeyFlags.Authentication, 0x20);
- checkValue(KeyFlags.Shared, 0x80);
-
- // yes this actually happens
- checkValue(new byte[] { 4, 0, 0, 0 }, 0x04);
- checkValue(new byte[] { 4, 0, 0 }, 0x04);
- checkValue(new byte[] { 4, 0 }, 0x04);
- checkValue(new byte[] { 4 }, 0x04);
- }
-
- private void checkValue(int flag, int val)
- {
- KeyFlags f = new KeyFlags(true, flag);
-
- if (f.Flags != val)
- {
- Fail("flag value mismatch");
- }
- }
-
- private void checkValue(byte[] flag, int val)
- {
- KeyFlags f = new KeyFlags(true, flag);
-
- if (f.Flags != val)
- {
- Fail("flag value mismatch");
- }
- }
-
- private void doTestMissingSubpackets(byte[] signature)
- {
- PgpObjectFactory f = new PgpObjectFactory(signature);
- object obj = f.NextPgpObject();
-
- while (!(obj is PgpSignatureList))
- {
- obj = f.NextPgpObject();
- if (obj is PgpLiteralData)
- {
- Stream input = ((PgpLiteralData)obj).GetDataStream();
- Streams.Drain(input);
- }
- }
-
- PgpSignature sig = ((PgpSignatureList)obj)[0];
-
- if (sig.Version > 3)
- {
- PgpSignatureSubpacketVector v = sig.GetHashedSubPackets();
-
- if (v.GetKeyExpirationTime() != 0)
- {
- Fail("key expiration time not zero for missing subpackets");
- }
-
- if (!sig.HasSubpackets)
- {
- Fail("HasSubpackets property was false with packets");
- }
- }
- else
- {
- if (sig.GetHashedSubPackets() != null)
- {
- Fail("hashed sub packets found when none expected");
- }
-
- if (sig.GetUnhashedSubPackets() != null)
- {
- Fail("unhashed sub packets found when none expected");
- }
-
- if (sig.HasSubpackets)
- {
- Fail("HasSubpackets property was true with no packets");
- }
- }
- }
-
- private void preferredAlgorithmCheck(
- string type,
- int[] expected,
- int[] prefAlgs)
- {
- if (expected == null)
- {
- if (prefAlgs != null)
- {
- Fail("preferences for " + type + " found when none expected");
- }
- }
- else
- {
- if (prefAlgs.Length != expected.Length)
- {
- Fail("wrong number of preferred " + type + " algorithms found");
- }
-
- for (int i = 0; i != expected.Length; i++)
- {
- if (expected[i] != prefAlgs[i])
- {
- Fail("wrong algorithm found for " + type + ": expected " + expected[i] + " got " + prefAlgs);
- }
- }
- }
- }
-
- private void doTestSig(
- PublicKeyAlgorithmTag encAlgorithm,
- HashAlgorithmTag hashAlgorithm,
- PgpPublicKey pubKey,
- PgpPrivateKey privKey)
- {
- MemoryStream bOut = new MemoryStream();
- MemoryStream testIn = new MemoryStream(TEST_DATA, false);
- PgpSignatureGenerator sGen = new PgpSignatureGenerator(encAlgorithm, hashAlgorithm);
-
- sGen.InitSign(PgpSignature.BinaryDocument, privKey);
- sGen.GenerateOnePassVersion(false).Encode(bOut);
-
- PgpLiteralDataGenerator lGen = new PgpLiteralDataGenerator();
- Stream lOut = lGen.Open(
- new UncloseableStream(bOut),
- PgpLiteralData.Binary,
- "_CONSOLE",
- TEST_DATA.Length * 2,
- DateTime.UtcNow);
-
- int ch;
- while ((ch = testIn.ReadByte()) >= 0)
- {
- lOut.WriteByte((byte)ch);
- sGen.Update((byte)ch);
- }
-
- lOut.Write(TEST_DATA, 0, TEST_DATA.Length);
- sGen.Update(TEST_DATA);
-
- lGen.Close();
-
- sGen.Generate().Encode(bOut);
-
- verifySignature(bOut.ToArray(), hashAlgorithm, pubKey, TEST_DATA);
- }
-
- private void doTestTextSig(
- PublicKeyAlgorithmTag encAlgorithm,
- HashAlgorithmTag hashAlgorithm,
- PgpPublicKey pubKey,
- PgpPrivateKey privKey,
- byte[] data,
- byte[] canonicalData)
- {
- PgpSignatureGenerator sGen = new PgpSignatureGenerator(encAlgorithm, HashAlgorithmTag.Sha1);
- MemoryStream bOut = new MemoryStream();
- MemoryStream testIn = new MemoryStream(data, false);
- DateTime creationTime = DateTime.UtcNow;
-
- sGen.InitSign(PgpSignature.CanonicalTextDocument, privKey);
- sGen.GenerateOnePassVersion(false).Encode(bOut);
-
- PgpLiteralDataGenerator lGen = new PgpLiteralDataGenerator();
- Stream lOut = lGen.Open(
- new UncloseableStream(bOut),
- PgpLiteralData.Text,
- "_CONSOLE",
- data.Length * 2,
- creationTime);
-
- int ch;
- while ((ch = testIn.ReadByte()) >= 0)
- {
- lOut.WriteByte((byte)ch);
- sGen.Update((byte)ch);
- }
-
- lOut.Write(data, 0, data.Length);
- sGen.Update(data);
-
- lGen.Close();
-
- PgpSignature sig = sGen.Generate();
-
- if (sig.CreationTime == DateTimeUtilities.UnixMsToDateTime(0))
- {
- Fail("creation time not set in v4 signature");
- }
-
- sig.Encode(bOut);
-
- verifySignature(bOut.ToArray(), hashAlgorithm, pubKey, canonicalData);
- }
-
- private void doTestSigV3(
- PublicKeyAlgorithmTag encAlgorithm,
- HashAlgorithmTag hashAlgorithm,
- PgpPublicKey pubKey,
- PgpPrivateKey privKey)
- {
- byte[] bytes = generateV3BinarySig(privKey, encAlgorithm, hashAlgorithm);
-
- verifySignature(bytes, hashAlgorithm, pubKey, TEST_DATA);
- }
-
- private byte[] generateV3BinarySig(
- PgpPrivateKey privKey,
- PublicKeyAlgorithmTag encAlgorithm,
- HashAlgorithmTag hashAlgorithm)
- {
- MemoryStream bOut = new MemoryStream();
- MemoryStream testIn = new MemoryStream(TEST_DATA, false);
- PgpV3SignatureGenerator sGen = new PgpV3SignatureGenerator(encAlgorithm, hashAlgorithm);
-
- sGen.InitSign(PgpSignature.BinaryDocument, privKey);
- sGen.GenerateOnePassVersion(false).Encode(bOut);
-
- PgpLiteralDataGenerator lGen = new PgpLiteralDataGenerator();
- Stream lOut = lGen.Open(
- new UncloseableStream(bOut),
- PgpLiteralData.Binary,
- "_CONSOLE",
- TEST_DATA.Length * 2,
- DateTime.UtcNow);
-
- int ch;
- while ((ch = testIn.ReadByte()) >= 0)
- {
- lOut.WriteByte((byte)ch);
- sGen.Update((byte)ch);
- }
-
- lOut.Write(TEST_DATA, 0, TEST_DATA.Length);
- sGen.Update(TEST_DATA);
-
- lGen.Close();
-
- sGen.Generate().Encode(bOut);
-
- return bOut.ToArray();
- }
-
- private void doTestTextSigV3(
- PublicKeyAlgorithmTag encAlgorithm,
- HashAlgorithmTag hashAlgorithm,
- PgpPublicKey pubKey,
- PgpPrivateKey privKey,
- byte[] data,
- byte[] canonicalData)
- {
- PgpV3SignatureGenerator sGen = new PgpV3SignatureGenerator(encAlgorithm, HashAlgorithmTag.Sha1);
- MemoryStream bOut = new MemoryStream();
- MemoryStream testIn = new MemoryStream(data, false);
-
- sGen.InitSign(PgpSignature.CanonicalTextDocument, privKey);
- sGen.GenerateOnePassVersion(false).Encode(bOut);
-
- PgpLiteralDataGenerator lGen = new PgpLiteralDataGenerator();
- Stream lOut = lGen.Open(
- new UncloseableStream(bOut),
- PgpLiteralData.Text,
- "_CONSOLE",
- data.Length * 2,
- DateTime.UtcNow);
-
- int ch;
- while ((ch = testIn.ReadByte()) >= 0)
- {
- lOut.WriteByte((byte)ch);
- sGen.Update((byte)ch);
- }
-
- lOut.Write(data, 0, data.Length);
- sGen.Update(data);
-
- lGen.Close();
-
- PgpSignature sig = sGen.Generate();
-
- if (sig.CreationTime == DateTimeUtilities.UnixMsToDateTime(0))
- {
- Fail("creation time not set in v3 signature");
- }
-
- sig.Encode(bOut);
-
- verifySignature(bOut.ToArray(), hashAlgorithm, pubKey, canonicalData);
- }
-
- private void verifySignature(
- byte[] encodedSig,
- HashAlgorithmTag hashAlgorithm,
- PgpPublicKey pubKey,
- byte[] original)
- {
- PgpObjectFactory pgpFact = new PgpObjectFactory(encodedSig);
- PgpOnePassSignatureList p1 = (PgpOnePassSignatureList)pgpFact.NextPgpObject();
- PgpOnePassSignature ops = p1[0];
- PgpLiteralData p2 = (PgpLiteralData)pgpFact.NextPgpObject();
- Stream dIn = p2.GetInputStream();
-
- ops.InitVerify(pubKey);
-
- int ch;
- while ((ch = dIn.ReadByte()) >= 0)
- {
- ops.Update((byte)ch);
- }
-
- PgpSignatureList p3 = (PgpSignatureList)pgpFact.NextPgpObject();
- PgpSignature sig = p3[0];
-
- DateTime creationTime = sig.CreationTime;
-
- // Check creationTime is recent
- if (creationTime.CompareTo(DateTime.UtcNow) > 0
- || creationTime.CompareTo(DateTime.UtcNow.AddMinutes(-10)) < 0)
- {
- Fail("bad creation time in signature: " + creationTime);
- }
-
- if (sig.KeyId != pubKey.KeyId)
- {
- Fail("key id mismatch in signature");
- }
-
- if (!ops.Verify(sig))
- {
- Fail("Failed generated signature check - " + hashAlgorithm);
- }
-
- sig.InitVerify(pubKey);
-
- for (int i = 0; i != original.Length; i++)
- {
- sig.Update(original[i]);
- }
-
- sig.Update(original);
-
- if (!sig.Verify())
- {
- Fail("Failed generated signature check against original data");
- }
- }
-
- public override string Name
- {
- get { return "PGPSignatureTest"; }
- }
-
- public static void Main(
- string[] args)
- {
- RunTest(new PgpSignatureTest());
- }
-
- [Test]
- public void TestFunction()
- {
- string resultText = Perform().ToString();
-
- Assert.AreEqual(Name + ": Okay", resultText);
- }
- }
+ if (hashedPcks.GetSignatureExpirationTime() != 0)
+ {
+ Fail("unexpected signature expiration time found");
+ }
+
+ if (hashedPcks.GetSignerUserId() != null)
+ {
+ Fail("unexpected signer user ID found");
+ }
+
+ criticalHashed = hashedPcks.GetCriticalTags();
+
+ if (criticalHashed.Length != 0)
+ {
+ Fail("critical packets found when none expected");
+ }
+
+ unhashedPcks = sig.GetUnhashedSubPackets();
+
+ if (unhashedPcks.Count != 1)
+ {
+ Fail("found wrong number of unhashed packets in override test");
+ }
+
+ //
+ // general signatures
+ //
+ doTestSig(PublicKeyAlgorithmTag.RsaGeneral, HashAlgorithmTag.Sha256, secretKey.PublicKey, pgpPrivKey);
+ doTestSig(PublicKeyAlgorithmTag.RsaGeneral, HashAlgorithmTag.Sha384, secretKey.PublicKey, pgpPrivKey);
+ doTestSig(PublicKeyAlgorithmTag.RsaGeneral, HashAlgorithmTag.Sha512, secretKey.PublicKey, pgpPrivKey);
+ doTestSigV3(PublicKeyAlgorithmTag.RsaGeneral, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey);
+ doTestTextSig(PublicKeyAlgorithmTag.RsaGeneral, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey, TEST_DATA_WITH_CRLF, TEST_DATA_WITH_CRLF);
+ doTestTextSig(PublicKeyAlgorithmTag.RsaGeneral, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey, TEST_DATA, TEST_DATA_WITH_CRLF);
+ doTestTextSigV3(PublicKeyAlgorithmTag.RsaGeneral, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey, TEST_DATA_WITH_CRLF, TEST_DATA_WITH_CRLF);
+ doTestTextSigV3(PublicKeyAlgorithmTag.RsaGeneral, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey, TEST_DATA, TEST_DATA_WITH_CRLF);
+
+ //
+ // DSA Tests
+ //
+ pgpPriv = new PgpSecretKeyRing(dsaKeyRing);
+ secretKey = pgpPriv.GetSecretKey();
+ pgpPrivKey = secretKey.ExtractPrivateKey(dsaPass);
+
+ try
+ {
+ doTestSig(PublicKeyAlgorithmTag.RsaGeneral, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey);
+
+ Fail("DSA wrong key test failed.");
+ }
+ catch (PgpException)
+ {
+ // expected
+ }
+
+ try
+ {
+ doTestSigV3(PublicKeyAlgorithmTag.RsaGeneral, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey);
+
+ Fail("DSA V3 wrong key test failed.");
+ }
+ catch (PgpException)
+ {
+ // expected
+ }
+
+ doTestSig(PublicKeyAlgorithmTag.Dsa, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey);
+ doTestSigV3(PublicKeyAlgorithmTag.Dsa, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey);
+ doTestTextSig(PublicKeyAlgorithmTag.Dsa, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey, TEST_DATA_WITH_CRLF, TEST_DATA_WITH_CRLF);
+ doTestTextSig(PublicKeyAlgorithmTag.Dsa, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey, TEST_DATA, TEST_DATA_WITH_CRLF);
+ doTestTextSigV3(PublicKeyAlgorithmTag.Dsa, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey, TEST_DATA_WITH_CRLF, TEST_DATA_WITH_CRLF);
+ doTestTextSigV3(PublicKeyAlgorithmTag.Dsa, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey, TEST_DATA, TEST_DATA_WITH_CRLF);
+
+ // special cases
+ //
+ doTestMissingSubpackets(nullPacketsSubKeyBinding);
+
+ doTestMissingSubpackets(generateV3BinarySig(pgpPrivKey, PublicKeyAlgorithmTag.Dsa, HashAlgorithmTag.Sha1));
+
+ // keyflags
+ doTestKeyFlagsValues();
+
+ // TODO Seems to depend on some other functionality that's yet to be ported
+ //doTestUserAttributeEncoding();
+ }
+
+ //private void doTestUserAttributeEncoding()
+ //{
+ // PgpPublicKeyRing pkr = new PgpPublicKeyRing(okAttr);
+
+ // CheckUserAttribute("normal", pkr, pkr.GetPublicKey());
+
+ // pkr = new PgpPublicKeyRing(attrLongLength);
+
+ // CheckUserAttribute("long", pkr, pkr.GetPublicKey());
+ //}
+
+ //private void CheckUserAttribute(String type, PgpPublicKeyRing pkr, PgpPublicKey masterPk)
+ //{
+ // foreach (PgpUserAttributeSubpacketVector attr in pkr.GetPublicKey().GetUserAttributes())
+ // {
+ // foreach (PgpSignature sig in masterPk.GetSignaturesForUserAttribute(attr))
+ // {
+ // sig.InitVerify(masterPk);
+ // if (!sig.VerifyCertification(attr, masterPk))
+ // {
+ // Fail("user attribute sig failed to verify on " + type);
+ // }
+ // }
+ // }
+ //}
+
+ private void doTestKeyFlagsValues()
+ {
+ checkValue(KeyFlags.CertifyOther, 0x01);
+ checkValue(KeyFlags.SignData, 0x02);
+ checkValue(KeyFlags.EncryptComms, 0x04);
+ checkValue(KeyFlags.EncryptStorage, 0x08);
+ checkValue(KeyFlags.Split, 0x10);
+ checkValue(KeyFlags.Authentication, 0x20);
+ checkValue(KeyFlags.Shared, 0x80);
+
+ // yes this actually happens
+ checkValue(new byte[] { 4, 0, 0, 0 }, 0x04);
+ checkValue(new byte[] { 4, 0, 0 }, 0x04);
+ checkValue(new byte[] { 4, 0 }, 0x04);
+ checkValue(new byte[] { 4 }, 0x04);
+ }
+
+ private void checkValue(int flag, int val)
+ {
+ KeyFlags f = new KeyFlags(true, flag);
+
+ if (f.Flags != val)
+ {
+ Fail("flag value mismatch");
+ }
+ }
+
+ private void checkValue(byte[] flag, int val)
+ {
+ KeyFlags f = new KeyFlags(true, flag);
+
+ if (f.Flags != val)
+ {
+ Fail("flag value mismatch");
+ }
+ }
+
+ private void doTestMissingSubpackets(byte[] signature)
+ {
+ PgpObjectFactory f = new PgpObjectFactory(signature);
+ object obj = f.NextPgpObject();
+
+ while (!(obj is PgpSignatureList))
+ {
+ obj = f.NextPgpObject();
+ if (obj is PgpLiteralData)
+ {
+ Stream input = ((PgpLiteralData)obj).GetDataStream();
+ Streams.Drain(input);
+ }
+ }
+
+ PgpSignature sig = ((PgpSignatureList)obj)[0];
+
+ if (sig.Version > 3)
+ {
+ PgpSignatureSubpacketVector v = sig.GetHashedSubPackets();
+
+ if (v.GetKeyExpirationTime() != 0)
+ {
+ Fail("key expiration time not zero for missing subpackets");
+ }
+
+ if (!sig.HasSubpackets)
+ {
+ Fail("HasSubpackets property was false with packets");
+ }
+ }
+ else
+ {
+ if (sig.GetHashedSubPackets() != null)
+ {
+ Fail("hashed sub packets found when none expected");
+ }
+
+ if (sig.GetUnhashedSubPackets() != null)
+ {
+ Fail("unhashed sub packets found when none expected");
+ }
+
+ if (sig.HasSubpackets)
+ {
+ Fail("HasSubpackets property was true with no packets");
+ }
+ }
+ }
+
+ private void preferredAlgorithmCheck(
+ string type,
+ int[] expected,
+ int[] prefAlgs)
+ {
+ if (expected == null)
+ {
+ if (prefAlgs != null)
+ {
+ Fail("preferences for " + type + " found when none expected");
+ }
+ }
+ else
+ {
+ if (prefAlgs.Length != expected.Length)
+ {
+ Fail("wrong number of preferred " + type + " algorithms found");
+ }
+
+ for (int i = 0; i != expected.Length; i++)
+ {
+ if (expected[i] != prefAlgs[i])
+ {
+ Fail("wrong algorithm found for " + type + ": expected " + expected[i] + " got " + prefAlgs);
+ }
+ }
+ }
+ }
+
+ private void doTestSig(
+ PublicKeyAlgorithmTag encAlgorithm,
+ HashAlgorithmTag hashAlgorithm,
+ PgpPublicKey pubKey,
+ PgpPrivateKey privKey)
+ {
+ MemoryStream bOut = new MemoryStream();
+ MemoryStream testIn = new MemoryStream(TEST_DATA, false);
+ PgpSignatureGenerator sGen = new PgpSignatureGenerator(encAlgorithm, hashAlgorithm);
+
+ sGen.InitSign(PgpSignature.BinaryDocument, privKey);
+ sGen.GenerateOnePassVersion(false).Encode(bOut);
+
+ PgpLiteralDataGenerator lGen = new PgpLiteralDataGenerator();
+ Stream lOut = lGen.Open(
+ new UncloseableStream(bOut),
+ PgpLiteralData.Binary,
+ "_CONSOLE",
+ TEST_DATA.Length * 2,
+ DateTime.UtcNow);
+
+ int ch;
+ while ((ch = testIn.ReadByte()) >= 0)
+ {
+ lOut.WriteByte((byte)ch);
+ sGen.Update((byte)ch);
+ }
+
+ lOut.Write(TEST_DATA, 0, TEST_DATA.Length);
+ sGen.Update(TEST_DATA);
+
+ lGen.Close();
+
+ sGen.Generate().Encode(bOut);
+
+ verifySignature(bOut.ToArray(), hashAlgorithm, pubKey, TEST_DATA);
+ }
+
+ private void doTestTextSig(
+ PublicKeyAlgorithmTag encAlgorithm,
+ HashAlgorithmTag hashAlgorithm,
+ PgpPublicKey pubKey,
+ PgpPrivateKey privKey,
+ byte[] data,
+ byte[] canonicalData)
+ {
+ PgpSignatureGenerator sGen = new PgpSignatureGenerator(encAlgorithm, HashAlgorithmTag.Sha1);
+ MemoryStream bOut = new MemoryStream();
+ MemoryStream testIn = new MemoryStream(data, false);
+ DateTime creationTime = DateTime.UtcNow;
+
+ sGen.InitSign(PgpSignature.CanonicalTextDocument, privKey);
+ sGen.GenerateOnePassVersion(false).Encode(bOut);
+
+ PgpLiteralDataGenerator lGen = new PgpLiteralDataGenerator();
+ Stream lOut = lGen.Open(
+ new UncloseableStream(bOut),
+ PgpLiteralData.Text,
+ "_CONSOLE",
+ data.Length * 2,
+ creationTime);
+
+ int ch;
+ while ((ch = testIn.ReadByte()) >= 0)
+ {
+ lOut.WriteByte((byte)ch);
+ sGen.Update((byte)ch);
+ }
+
+ lOut.Write(data, 0, data.Length);
+ sGen.Update(data);
+
+ lGen.Close();
+
+ PgpSignature sig = sGen.Generate();
+
+ if (sig.CreationTime == DateTimeUtilities.UnixMsToDateTime(0))
+ {
+ Fail("creation time not set in v4 signature");
+ }
+
+ sig.Encode(bOut);
+
+ verifySignature(bOut.ToArray(), hashAlgorithm, pubKey, canonicalData);
+ }
+
+ private void doTestSigV3(
+ PublicKeyAlgorithmTag encAlgorithm,
+ HashAlgorithmTag hashAlgorithm,
+ PgpPublicKey pubKey,
+ PgpPrivateKey privKey)
+ {
+ byte[] bytes = generateV3BinarySig(privKey, encAlgorithm, hashAlgorithm);
+
+ verifySignature(bytes, hashAlgorithm, pubKey, TEST_DATA);
+ }
+
+ private byte[] generateV3BinarySig(
+ PgpPrivateKey privKey,
+ PublicKeyAlgorithmTag encAlgorithm,
+ HashAlgorithmTag hashAlgorithm)
+ {
+ MemoryStream bOut = new MemoryStream();
+ MemoryStream testIn = new MemoryStream(TEST_DATA, false);
+ PgpV3SignatureGenerator sGen = new PgpV3SignatureGenerator(encAlgorithm, hashAlgorithm);
+
+ sGen.InitSign(PgpSignature.BinaryDocument, privKey);
+ sGen.GenerateOnePassVersion(false).Encode(bOut);
+
+ PgpLiteralDataGenerator lGen = new PgpLiteralDataGenerator();
+ Stream lOut = lGen.Open(
+ new UncloseableStream(bOut),
+ PgpLiteralData.Binary,
+ "_CONSOLE",
+ TEST_DATA.Length * 2,
+ DateTime.UtcNow);
+
+ int ch;
+ while ((ch = testIn.ReadByte()) >= 0)
+ {
+ lOut.WriteByte((byte)ch);
+ sGen.Update((byte)ch);
+ }
+
+ lOut.Write(TEST_DATA, 0, TEST_DATA.Length);
+ sGen.Update(TEST_DATA);
+
+ lGen.Close();
+
+ sGen.Generate().Encode(bOut);
+
+ return bOut.ToArray();
+ }
+
+ private void doTestTextSigV3(
+ PublicKeyAlgorithmTag encAlgorithm,
+ HashAlgorithmTag hashAlgorithm,
+ PgpPublicKey pubKey,
+ PgpPrivateKey privKey,
+ byte[] data,
+ byte[] canonicalData)
+ {
+ PgpV3SignatureGenerator sGen = new PgpV3SignatureGenerator(encAlgorithm, HashAlgorithmTag.Sha1);
+ MemoryStream bOut = new MemoryStream();
+ MemoryStream testIn = new MemoryStream(data, false);
+
+ sGen.InitSign(PgpSignature.CanonicalTextDocument, privKey);
+ sGen.GenerateOnePassVersion(false).Encode(bOut);
+
+ PgpLiteralDataGenerator lGen = new PgpLiteralDataGenerator();
+ Stream lOut = lGen.Open(
+ new UncloseableStream(bOut),
+ PgpLiteralData.Text,
+ "_CONSOLE",
+ data.Length * 2,
+ DateTime.UtcNow);
+
+ int ch;
+ while ((ch = testIn.ReadByte()) >= 0)
+ {
+ lOut.WriteByte((byte)ch);
+ sGen.Update((byte)ch);
+ }
+
+ lOut.Write(data, 0, data.Length);
+ sGen.Update(data);
+
+ lGen.Close();
+
+ PgpSignature sig = sGen.Generate();
+
+ if (sig.CreationTime == DateTimeUtilities.UnixMsToDateTime(0))
+ {
+ Fail("creation time not set in v3 signature");
+ }
+
+ sig.Encode(bOut);
+
+ verifySignature(bOut.ToArray(), hashAlgorithm, pubKey, canonicalData);
+ }
+
+ private void verifySignature(
+ byte[] encodedSig,
+ HashAlgorithmTag hashAlgorithm,
+ PgpPublicKey pubKey,
+ byte[] original)
+ {
+ PgpObjectFactory pgpFact = new PgpObjectFactory(encodedSig);
+ PgpOnePassSignatureList p1 = (PgpOnePassSignatureList)pgpFact.NextPgpObject();
+ PgpOnePassSignature ops = p1[0];
+ PgpLiteralData p2 = (PgpLiteralData)pgpFact.NextPgpObject();
+ Stream dIn = p2.GetInputStream();
+
+ ops.InitVerify(pubKey);
+
+ int ch;
+ while ((ch = dIn.ReadByte()) >= 0)
+ {
+ ops.Update((byte)ch);
+ }
+
+ PgpSignatureList p3 = (PgpSignatureList)pgpFact.NextPgpObject();
+ PgpSignature sig = p3[0];
+
+ DateTime creationTime = sig.CreationTime;
+
+ // Check creationTime is recent
+ if (creationTime.CompareTo(DateTime.UtcNow) > 0
+ || creationTime.CompareTo(DateTime.UtcNow.AddMinutes(-10)) < 0)
+ {
+ Fail("bad creation time in signature: " + creationTime);
+ }
+
+ if (sig.KeyId != pubKey.KeyId)
+ {
+ Fail("key id mismatch in signature");
+ }
+
+ if (!ops.Verify(sig))
+ {
+ Fail("Failed generated signature check - " + hashAlgorithm);
+ }
+
+ sig.InitVerify(pubKey);
+
+ for (int i = 0; i != original.Length; i++)
+ {
+ sig.Update(original[i]);
+ }
+
+ sig.Update(original);
+
+ if (!sig.Verify())
+ {
+ Fail("Failed generated signature check against original data");
+ }
+ }
+
+ public override string Name
+ {
+ get { return "PGPSignatureTest"; }
+ }
+
+ public static void Main(
+ string[] args)
+ {
+ RunTest(new PgpSignatureTest());
+ }
+
+ [Test]
+ public void TestFunction()
+ {
+ string resultText = Perform().ToString();
+
+ Assert.AreEqual(Name + ": Okay", resultText);
+ }
+ }
}
|