diff --git a/Crypto/src/openpgp/PgpPublicKey.cs b/Crypto/src/openpgp/PgpPublicKey.cs
new file mode 100644
index 000000000..b0720146c
--- /dev/null
+++ b/Crypto/src/openpgp/PgpPublicKey.cs
@@ -0,0 +1,890 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.IO;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp
+{
+ /// <remarks>General class to handle a PGP public key object.</remarks>
+ public class PgpPublicKey
+ {
+ private static readonly int[] MasterKeyCertificationTypes = new int[]
+ {
+ PgpSignature.PositiveCertification,
+ PgpSignature.CasualCertification,
+ PgpSignature.NoCertification,
+ PgpSignature.DefaultCertification
+ };
+
+ private long keyId;
+ private byte[] fingerprint;
+ private int keyStrength;
+
+ internal PublicKeyPacket publicPk;
+ internal TrustPacket trustPk;
+ internal IList keySigs = Platform.CreateArrayList();
+ internal IList ids = Platform.CreateArrayList();
+ internal IList idTrusts = Platform.CreateArrayList();
+ internal IList idSigs = Platform.CreateArrayList();
+ internal IList subSigs;
+
+ private void Init()
+ {
+ IBcpgKey key = publicPk.Key;
+
+ if (publicPk.Version <= 3)
+ {
+ RsaPublicBcpgKey rK = (RsaPublicBcpgKey) key;
+
+ this.keyId = rK.Modulus.LongValue;
+
+ try
+ {
+ IDigest digest = DigestUtilities.GetDigest("MD5");
+
+ byte[] bytes = rK.Modulus.ToByteArrayUnsigned();
+ digest.BlockUpdate(bytes, 0, bytes.Length);
+
+ bytes = rK.PublicExponent.ToByteArrayUnsigned();
+ digest.BlockUpdate(bytes, 0, bytes.Length);
+
+ this.fingerprint = DigestUtilities.DoFinal(digest);
+ }
+ //catch (NoSuchAlgorithmException)
+ catch (Exception e)
+ {
+ throw new IOException("can't find MD5", e);
+ }
+
+ this.keyStrength = rK.Modulus.BitLength;
+ }
+ else
+ {
+ byte[] kBytes = publicPk.GetEncodedContents();
+
+ try
+ {
+ IDigest digest = DigestUtilities.GetDigest("SHA1");
+
+ digest.Update(0x99);
+ digest.Update((byte)(kBytes.Length >> 8));
+ digest.Update((byte)kBytes.Length);
+ digest.BlockUpdate(kBytes, 0, kBytes.Length);
+ this.fingerprint = DigestUtilities.DoFinal(digest);
+ }
+ catch (Exception e)
+ {
+ throw new IOException("can't find SHA1", e);
+ }
+
+ this.keyId = (long)(((ulong)fingerprint[fingerprint.Length - 8] << 56)
+ | ((ulong)fingerprint[fingerprint.Length - 7] << 48)
+ | ((ulong)fingerprint[fingerprint.Length - 6] << 40)
+ | ((ulong)fingerprint[fingerprint.Length - 5] << 32)
+ | ((ulong)fingerprint[fingerprint.Length - 4] << 24)
+ | ((ulong)fingerprint[fingerprint.Length - 3] << 16)
+ | ((ulong)fingerprint[fingerprint.Length - 2] << 8)
+ | (ulong)fingerprint[fingerprint.Length - 1]);
+
+ if (key is RsaPublicBcpgKey)
+ {
+ this.keyStrength = ((RsaPublicBcpgKey)key).Modulus.BitLength;
+ }
+ else if (key is DsaPublicBcpgKey)
+ {
+ this.keyStrength = ((DsaPublicBcpgKey)key).P.BitLength;
+ }
+ else if (key is ElGamalPublicBcpgKey)
+ {
+ this.keyStrength = ((ElGamalPublicBcpgKey)key).P.BitLength;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Create a PgpPublicKey from the passed in lightweight one.
+ /// </summary>
+ /// <remarks>
+ /// Note: the time passed in affects the value of the key's keyId, so you probably only want
+ /// to do this once for a lightweight key, or make sure you keep track of the time you used.
+ /// </remarks>
+ /// <param name="algorithm">Asymmetric algorithm type representing the public key.</param>
+ /// <param name="pubKey">Actual public key to associate.</param>
+ /// <param name="time">Date of creation.</param>
+ /// <exception cref="ArgumentException">If <c>pubKey</c> is not public.</exception>
+ /// <exception cref="PgpException">On key creation problem.</exception>
+ public PgpPublicKey(
+ PublicKeyAlgorithmTag algorithm,
+ AsymmetricKeyParameter pubKey,
+ DateTime time)
+ {
+ if (pubKey.IsPrivate)
+ throw new ArgumentException("Expected a public key", "pubKey");
+
+ IBcpgKey bcpgKey;
+ if (pubKey is RsaKeyParameters)
+ {
+ RsaKeyParameters rK = (RsaKeyParameters) pubKey;
+
+ bcpgKey = new RsaPublicBcpgKey(rK.Modulus, rK.Exponent);
+ }
+ else if (pubKey is DsaPublicKeyParameters)
+ {
+ DsaPublicKeyParameters dK = (DsaPublicKeyParameters) pubKey;
+ DsaParameters dP = dK.Parameters;
+
+ bcpgKey = new DsaPublicBcpgKey(dP.P, dP.Q, dP.G, dK.Y);
+ }
+ else if (pubKey is ElGamalPublicKeyParameters)
+ {
+ ElGamalPublicKeyParameters eK = (ElGamalPublicKeyParameters) pubKey;
+ ElGamalParameters eS = eK.Parameters;
+
+ bcpgKey = new ElGamalPublicBcpgKey(eS.P, eS.G, eK.Y);
+ }
+ else
+ {
+ throw new PgpException("unknown key class");
+ }
+
+ this.publicPk = new PublicKeyPacket(algorithm, time, bcpgKey);
+ this.ids = Platform.CreateArrayList();
+ this.idSigs = Platform.CreateArrayList();
+
+ try
+ {
+ Init();
+ }
+ catch (IOException e)
+ {
+ throw new PgpException("exception calculating keyId", e);
+ }
+ }
+
+ /// <summary>Constructor for a sub-key.</summary>
+ internal PgpPublicKey(
+ PublicKeyPacket publicPk,
+ TrustPacket trustPk,
+ IList sigs)
+ {
+ this.publicPk = publicPk;
+ this.trustPk = trustPk;
+ this.subSigs = sigs;
+
+ Init();
+ }
+
+ internal PgpPublicKey(
+ PgpPublicKey key,
+ TrustPacket trust,
+ IList subSigs)
+ {
+ this.publicPk = key.publicPk;
+ this.trustPk = trust;
+ this.subSigs = subSigs;
+
+ this.fingerprint = key.fingerprint;
+ this.keyId = key.keyId;
+ this.keyStrength = key.keyStrength;
+ }
+
+ /// <summary>Copy constructor.</summary>
+ /// <param name="pubKey">The public key to copy.</param>
+ internal PgpPublicKey(
+ PgpPublicKey pubKey)
+ {
+ this.publicPk = pubKey.publicPk;
+
+ this.keySigs = Platform.CreateArrayList(pubKey.keySigs);
+ this.ids = Platform.CreateArrayList(pubKey.ids);
+ this.idTrusts = Platform.CreateArrayList(pubKey.idTrusts);
+ this.idSigs = Platform.CreateArrayList(pubKey.idSigs.Count);
+ for (int i = 0; i != pubKey.idSigs.Count; i++)
+ {
+ this.idSigs.Add(Platform.CreateArrayList((IList)pubKey.idSigs[i]));
+ }
+
+ if (pubKey.subSigs != null)
+ {
+ this.subSigs = Platform.CreateArrayList(pubKey.subSigs.Count);
+ for (int i = 0; i != pubKey.subSigs.Count; i++)
+ {
+ this.subSigs.Add(pubKey.subSigs[i]);
+ }
+ }
+
+ this.fingerprint = pubKey.fingerprint;
+ this.keyId = pubKey.keyId;
+ this.keyStrength = pubKey.keyStrength;
+ }
+
+ internal PgpPublicKey(
+ PublicKeyPacket publicPk,
+ TrustPacket trustPk,
+ IList keySigs,
+ IList ids,
+ IList idTrusts,
+ IList idSigs)
+ {
+ this.publicPk = publicPk;
+ this.trustPk = trustPk;
+ this.keySigs = keySigs;
+ this.ids = ids;
+ this.idTrusts = idTrusts;
+ this.idSigs = idSigs;
+
+ Init();
+ }
+
+ internal PgpPublicKey(
+ PublicKeyPacket publicPk,
+ IList ids,
+ IList idSigs)
+ {
+ this.publicPk = publicPk;
+ this.ids = ids;
+ this.idSigs = idSigs;
+ Init();
+ }
+
+ /// <summary>The version of this key.</summary>
+ public int Version
+ {
+ get { return publicPk.Version; }
+ }
+
+ /// <summary>The creation time of this key.</summary>
+ public DateTime CreationTime
+ {
+ get { return publicPk.GetTime(); }
+ }
+
+ /// <summary>The number of valid days from creation time - zero means no expiry.</summary>
+ public int ValidDays
+ {
+ get
+ {
+ if (publicPk.Version > 3)
+ {
+ return (int)(GetValidSeconds() / (24 * 60 * 60));
+ }
+
+ return publicPk.ValidDays;
+ }
+ }
+
+ /// <summary>Return the trust data associated with the public key, if present.</summary>
+ /// <returns>A byte array with trust data, null otherwise.</returns>
+ public byte[] GetTrustData()
+ {
+ if (trustPk == null)
+ {
+ return null;
+ }
+
+ return trustPk.GetLevelAndTrustAmount();
+ }
+
+ /// <summary>The number of valid seconds from creation time - zero means no expiry.</summary>
+ public long GetValidSeconds()
+ {
+ if (publicPk.Version > 3)
+ {
+ if (IsMasterKey)
+ {
+ for (int i = 0; i != MasterKeyCertificationTypes.Length; i++)
+ {
+ long seconds = GetExpirationTimeFromSig(true, MasterKeyCertificationTypes[i]);
+
+ if (seconds >= 0)
+ {
+ return seconds;
+ }
+ }
+ }
+ else
+ {
+ long seconds = GetExpirationTimeFromSig(false, PgpSignature.SubkeyBinding);
+
+ if (seconds >= 0)
+ {
+ return seconds;
+ }
+ }
+
+ return 0;
+ }
+
+ return (long) publicPk.ValidDays * 24 * 60 * 60;
+ }
+
+ private long GetExpirationTimeFromSig(
+ bool selfSigned,
+ int signatureType)
+ {
+ foreach (PgpSignature sig in GetSignaturesOfType(signatureType))
+ {
+ if (!selfSigned || sig.KeyId == KeyId)
+ {
+ PgpSignatureSubpacketVector hashed = sig.GetHashedSubPackets();
+
+ if (hashed != null)
+ {
+ return hashed.GetKeyExpirationTime();
+ }
+
+ return 0;
+ }
+ }
+
+ return -1;
+ }
+
+ /// <summary>The keyId associated with the public key.</summary>
+ public long KeyId
+ {
+ get { return keyId; }
+ }
+
+ /// <summary>The fingerprint of the key</summary>
+ public byte[] GetFingerprint()
+ {
+ return (byte[]) fingerprint.Clone();
+ }
+
+ /// <summary>
+ /// Check if this key has an algorithm type that makes it suitable to use for encryption.
+ /// </summary>
+ /// <remarks>
+ /// Note: with version 4 keys KeyFlags subpackets should also be considered when present for
+ /// determining the preferred use of the key.
+ /// </remarks>
+ /// <returns>
+ /// <c>true</c> if this key algorithm is suitable for encryption.
+ /// </returns>
+ public bool IsEncryptionKey
+ {
+ get
+ {
+ switch (publicPk.Algorithm)
+ {
+ case PublicKeyAlgorithmTag.ElGamalEncrypt:
+ case PublicKeyAlgorithmTag.ElGamalGeneral:
+ case PublicKeyAlgorithmTag.RsaEncrypt:
+ case PublicKeyAlgorithmTag.RsaGeneral:
+ return true;
+ default:
+ return false;
+ }
+ }
+ }
+
+ /// <summary>True, if this is a master key.</summary>
+ public bool IsMasterKey
+ {
+ get { return subSigs == null; }
+ }
+
+ /// <summary>The algorithm code associated with the public key.</summary>
+ public PublicKeyAlgorithmTag Algorithm
+ {
+ get { return publicPk.Algorithm; }
+ }
+
+ /// <summary>The strength of the key in bits.</summary>
+ public int BitStrength
+ {
+ get { return keyStrength; }
+ }
+
+ /// <summary>The public key contained in the object.</summary>
+ /// <returns>A lightweight public key.</returns>
+ /// <exception cref="PgpException">If the key algorithm is not recognised.</exception>
+ public AsymmetricKeyParameter GetKey()
+ {
+ try
+ {
+ switch (publicPk.Algorithm)
+ {
+ case PublicKeyAlgorithmTag.RsaEncrypt:
+ case PublicKeyAlgorithmTag.RsaGeneral:
+ case PublicKeyAlgorithmTag.RsaSign:
+ RsaPublicBcpgKey rsaK = (RsaPublicBcpgKey) publicPk.Key;
+ return new RsaKeyParameters(false, rsaK.Modulus, rsaK.PublicExponent);
+ case PublicKeyAlgorithmTag.Dsa:
+ DsaPublicBcpgKey dsaK = (DsaPublicBcpgKey) publicPk.Key;
+ return new DsaPublicKeyParameters(dsaK.Y, new DsaParameters(dsaK.P, dsaK.Q, dsaK.G));
+ case PublicKeyAlgorithmTag.ElGamalEncrypt:
+ case PublicKeyAlgorithmTag.ElGamalGeneral:
+ ElGamalPublicBcpgKey elK = (ElGamalPublicBcpgKey) publicPk.Key;
+ return new ElGamalPublicKeyParameters(elK.Y, new ElGamalParameters(elK.P, elK.G));
+ default:
+ throw new PgpException("unknown public key algorithm encountered");
+ }
+ }
+ catch (PgpException e)
+ {
+ throw e;
+ }
+ catch (Exception e)
+ {
+ throw new PgpException("exception constructing public key", e);
+ }
+ }
+
+ /// <summary>Allows enumeration of any user IDs associated with the key.</summary>
+ /// <returns>An <c>IEnumerable</c> of <c>string</c> objects.</returns>
+ public IEnumerable GetUserIds()
+ {
+ IList temp = Platform.CreateArrayList();
+
+ foreach (object o in ids)
+ {
+ if (o is string)
+ {
+ temp.Add(o);
+ }
+ }
+
+ return new EnumerableProxy(temp);
+ }
+
+ /// <summary>Allows enumeration of any user attribute vectors associated with the key.</summary>
+ /// <returns>An <c>IEnumerable</c> of <c>PgpUserAttributeSubpacketVector</c> objects.</returns>
+ public IEnumerable GetUserAttributes()
+ {
+ IList temp = Platform.CreateArrayList();
+
+ foreach (object o in ids)
+ {
+ if (o is PgpUserAttributeSubpacketVector)
+ {
+ temp.Add(o);
+ }
+ }
+
+ return new EnumerableProxy(temp);
+ }
+
+ /// <summary>Allows enumeration of any signatures associated with the passed in id.</summary>
+ /// <param name="id">The ID to be matched.</param>
+ /// <returns>An <c>IEnumerable</c> of <c>PgpSignature</c> objects.</returns>
+ public IEnumerable GetSignaturesForId(
+ string id)
+ {
+ if (id == null)
+ throw new ArgumentNullException("id");
+
+ for (int i = 0; i != ids.Count; i++)
+ {
+ if (id.Equals(ids[i]))
+ {
+ return new EnumerableProxy((IList)idSigs[i]);
+ }
+ }
+
+ return null;
+ }
+
+ /// <summary>Allows enumeration of signatures associated with the passed in user attributes.</summary>
+ /// <param name="userAttributes">The vector of user attributes to be matched.</param>
+ /// <returns>An <c>IEnumerable</c> of <c>PgpSignature</c> objects.</returns>
+ public IEnumerable GetSignaturesForUserAttribute(
+ PgpUserAttributeSubpacketVector userAttributes)
+ {
+ for (int i = 0; i != ids.Count; i++)
+ {
+ if (userAttributes.Equals(ids[i]))
+ {
+ return new EnumerableProxy((IList) idSigs[i]);
+ }
+ }
+
+ return null;
+ }
+
+ /// <summary>Allows enumeration of signatures of the passed in type that are on this key.</summary>
+ /// <param name="signatureType">The type of the signature to be returned.</param>
+ /// <returns>An <c>IEnumerable</c> of <c>PgpSignature</c> objects.</returns>
+ public IEnumerable GetSignaturesOfType(
+ int signatureType)
+ {
+ IList temp = Platform.CreateArrayList();
+
+ foreach (PgpSignature sig in GetSignatures())
+ {
+ if (sig.SignatureType == signatureType)
+ {
+ temp.Add(sig);
+ }
+ }
+
+ return new EnumerableProxy(temp);
+ }
+
+ /// <summary>Allows enumeration of all signatures/certifications associated with this key.</summary>
+ /// <returns>An <c>IEnumerable</c> with all signatures/certifications.</returns>
+ public IEnumerable GetSignatures()
+ {
+ IList sigs;
+ if (subSigs != null)
+ {
+ sigs = subSigs;
+ }
+ else
+ {
+ sigs = Platform.CreateArrayList(keySigs);
+
+ foreach (ICollection extraSigs in idSigs)
+ {
+ CollectionUtilities.AddRange(sigs, extraSigs);
+ }
+ }
+
+ return new EnumerableProxy(sigs);
+ }
+
+ public byte[] GetEncoded()
+ {
+ MemoryStream bOut = new MemoryStream();
+ Encode(bOut);
+ return bOut.ToArray();
+ }
+
+ public void Encode(
+ Stream outStr)
+ {
+ BcpgOutputStream bcpgOut = BcpgOutputStream.Wrap(outStr);
+
+ bcpgOut.WritePacket(publicPk);
+ if (trustPk != null)
+ {
+ bcpgOut.WritePacket(trustPk);
+ }
+
+ if (subSigs == null) // not a sub-key
+ {
+ foreach (PgpSignature keySig in keySigs)
+ {
+ keySig.Encode(bcpgOut);
+ }
+
+ for (int i = 0; i != ids.Count; i++)
+ {
+ if (ids[i] is string)
+ {
+ string id = (string) ids[i];
+
+ bcpgOut.WritePacket(new UserIdPacket(id));
+ }
+ else
+ {
+ PgpUserAttributeSubpacketVector v = (PgpUserAttributeSubpacketVector)ids[i];
+ bcpgOut.WritePacket(new UserAttributePacket(v.ToSubpacketArray()));
+ }
+
+ if (idTrusts[i] != null)
+ {
+ bcpgOut.WritePacket((ContainedPacket)idTrusts[i]);
+ }
+
+ foreach (PgpSignature sig in (IList) idSigs[i])
+ {
+ sig.Encode(bcpgOut);
+ }
+ }
+ }
+ else
+ {
+ foreach (PgpSignature subSig in subSigs)
+ {
+ subSig.Encode(bcpgOut);
+ }
+ }
+ }
+
+ /// <summary>Check whether this (sub)key has a revocation signature on it.</summary>
+ /// <returns>True, if this (sub)key has been revoked.</returns>
+ public bool IsRevoked()
+ {
+ int ns = 0;
+ bool revoked = false;
+ if (IsMasterKey) // Master key
+ {
+ while (!revoked && (ns < keySigs.Count))
+ {
+ if (((PgpSignature)keySigs[ns++]).SignatureType == PgpSignature.KeyRevocation)
+ {
+ revoked = true;
+ }
+ }
+ }
+ else // Sub-key
+ {
+ while (!revoked && (ns < subSigs.Count))
+ {
+ if (((PgpSignature)subSigs[ns++]).SignatureType == PgpSignature.SubkeyRevocation)
+ {
+ revoked = true;
+ }
+ }
+ }
+ return revoked;
+ }
+
+ /// <summary>Add a certification for an id to the given public key.</summary>
+ /// <param name="key">The key the certification is to be added to.</param>
+ /// <param name="id">The ID the certification is associated with.</param>
+ /// <param name="certification">The new certification.</param>
+ /// <returns>The re-certified key.</returns>
+ public static PgpPublicKey AddCertification(
+ PgpPublicKey key,
+ string id,
+ PgpSignature certification)
+ {
+ return AddCert(key, id, certification);
+ }
+
+ /// <summary>Add a certification for the given UserAttributeSubpackets to the given public key.</summary>
+ /// <param name="key">The key the certification is to be added to.</param>
+ /// <param name="userAttributes">The attributes the certification is associated with.</param>
+ /// <param name="certification">The new certification.</param>
+ /// <returns>The re-certified key.</returns>
+ public static PgpPublicKey AddCertification(
+ PgpPublicKey key,
+ PgpUserAttributeSubpacketVector userAttributes,
+ PgpSignature certification)
+ {
+ return AddCert(key, userAttributes, certification);
+ }
+
+ private static PgpPublicKey AddCert(
+ PgpPublicKey key,
+ object id,
+ PgpSignature certification)
+ {
+ PgpPublicKey returnKey = new PgpPublicKey(key);
+ IList sigList = null;
+
+ for (int i = 0; i != returnKey.ids.Count; i++)
+ {
+ if (id.Equals(returnKey.ids[i]))
+ {
+ sigList = (IList) returnKey.idSigs[i];
+ }
+ }
+
+ if (sigList != null)
+ {
+ sigList.Add(certification);
+ }
+ else
+ {
+ sigList = Platform.CreateArrayList();
+ sigList.Add(certification);
+ returnKey.ids.Add(id);
+ returnKey.idTrusts.Add(null);
+ returnKey.idSigs.Add(sigList);
+ }
+
+ return returnKey;
+ }
+
+ /// <summary>
+ /// Remove any certifications associated with a user attribute subpacket on a key.
+ /// </summary>
+ /// <param name="key">The key the certifications are to be removed from.</param>
+ /// <param name="userAttributes">The attributes to be removed.</param>
+ /// <returns>
+ /// The re-certified key, or null if the user attribute subpacket was not found on the key.
+ /// </returns>
+ public static PgpPublicKey RemoveCertification(
+ PgpPublicKey key,
+ PgpUserAttributeSubpacketVector userAttributes)
+ {
+ return RemoveCert(key, userAttributes);
+ }
+
+ /// <summary>Remove any certifications associated with a given ID on a key.</summary>
+ /// <param name="key">The key the certifications are to be removed from.</param>
+ /// <param name="id">The ID that is to be removed.</param>
+ /// <returns>The re-certified key, or null if the ID was not found on the key.</returns>
+ public static PgpPublicKey RemoveCertification(
+ PgpPublicKey key,
+ string id)
+ {
+ return RemoveCert(key, id);
+ }
+
+ private static PgpPublicKey RemoveCert(
+ PgpPublicKey key,
+ object id)
+ {
+ PgpPublicKey returnKey = new PgpPublicKey(key);
+ bool found = false;
+
+ for (int i = 0; i < returnKey.ids.Count; i++)
+ {
+ if (id.Equals(returnKey.ids[i]))
+ {
+ found = true;
+ returnKey.ids.RemoveAt(i);
+ returnKey.idTrusts.RemoveAt(i);
+ returnKey.idSigs.RemoveAt(i);
+ }
+ }
+
+ return found ? returnKey : null;
+ }
+
+ /// <summary>Remove a certification associated with a given ID on a key.</summary>
+ /// <param name="key">The key the certifications are to be removed from.</param>
+ /// <param name="id">The ID that the certfication is to be removed from.</param>
+ /// <param name="certification">The certfication to be removed.</param>
+ /// <returns>The re-certified key, or null if the certification was not found.</returns>
+ public static PgpPublicKey RemoveCertification(
+ PgpPublicKey key,
+ string id,
+ PgpSignature certification)
+ {
+ return RemoveCert(key, id, certification);
+ }
+
+ /// <summary>Remove a certification associated with a given user attributes on a key.</summary>
+ /// <param name="key">The key the certifications are to be removed from.</param>
+ /// <param name="userAttributes">The user attributes that the certfication is to be removed from.</param>
+ /// <param name="certification">The certification to be removed.</param>
+ /// <returns>The re-certified key, or null if the certification was not found.</returns>
+ public static PgpPublicKey RemoveCertification(
+ PgpPublicKey key,
+ PgpUserAttributeSubpacketVector userAttributes,
+ PgpSignature certification)
+ {
+ return RemoveCert(key, userAttributes, certification);
+ }
+
+ private static PgpPublicKey RemoveCert(
+ PgpPublicKey key,
+ object id,
+ PgpSignature certification)
+ {
+ PgpPublicKey returnKey = new PgpPublicKey(key);
+ bool found = false;
+
+ for (int i = 0; i < returnKey.ids.Count; i++)
+ {
+ if (id.Equals(returnKey.ids[i]))
+ {
+ IList certs = (IList) returnKey.idSigs[i];
+ found = certs.Contains(certification);
+
+ if (found)
+ {
+ certs.Remove(certification);
+ }
+ }
+ }
+
+ return found ? returnKey : null;
+ }
+
+ /// <summary>Add a revocation or some other key certification to a key.</summary>
+ /// <param name="key">The key the revocation is to be added to.</param>
+ /// <param name="certification">The key signature to be added.</param>
+ /// <returns>The new changed public key object.</returns>
+ public static PgpPublicKey AddCertification(
+ PgpPublicKey key,
+ PgpSignature certification)
+ {
+ if (key.IsMasterKey)
+ {
+ if (certification.SignatureType == PgpSignature.SubkeyRevocation)
+ {
+ throw new ArgumentException("signature type incorrect for master key revocation.");
+ }
+ }
+ else
+ {
+ if (certification.SignatureType == PgpSignature.KeyRevocation)
+ {
+ throw new ArgumentException("signature type incorrect for sub-key revocation.");
+ }
+ }
+
+ PgpPublicKey returnKey = new PgpPublicKey(key);
+
+ if (returnKey.subSigs != null)
+ {
+ returnKey.subSigs.Add(certification);
+ }
+ else
+ {
+ returnKey.keySigs.Add(certification);
+ }
+
+ return returnKey;
+ }
+
+ /// <summary>Remove a certification from the key.</summary>
+ /// <param name="key">The key the certifications are to be removed from.</param>
+ /// <param name="certification">The certfication to be removed.</param>
+ /// <returns>The modified key, null if the certification was not found.</returns>
+ public static PgpPublicKey RemoveCertification(
+ PgpPublicKey key,
+ PgpSignature certification)
+ {
+ PgpPublicKey returnKey = new PgpPublicKey(key);
+ IList sigs = returnKey.subSigs != null
+ ? returnKey.subSigs
+ : returnKey.keySigs;
+
+// bool found = sigs.Remove(certification);
+ int pos = sigs.IndexOf(certification);
+ bool found = pos >= 0;
+
+ if (found)
+ {
+ sigs.RemoveAt(pos);
+ }
+ else
+ {
+ foreach (String id in key.GetUserIds())
+ {
+ foreach (object sig in key.GetSignaturesForId(id))
+ {
+ // TODO Is this the right type of equality test?
+ if (certification == sig)
+ {
+ found = true;
+ returnKey = PgpPublicKey.RemoveCertification(returnKey, id, certification);
+ }
+ }
+ }
+
+ if (!found)
+ {
+ foreach (PgpUserAttributeSubpacketVector id in key.GetUserAttributes())
+ {
+ foreach (object sig in key.GetSignaturesForUserAttribute(id))
+ {
+ // TODO Is this the right type of equality test?
+ if (certification == sig)
+ {
+ found = true;
+ returnKey = PgpPublicKey.RemoveCertification(returnKey, id, certification);
+ }
+ }
+ }
+ }
+ }
+
+ return returnKey;
+ }
+ }
+}
|