PageRenderTime 32ms CodeModel.GetById 18ms app.highlight 11ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/bouncycastle/openpgp/PgpPublicKeyRingBundle.cs

https://bitbucket.org/festevezga/socketex
C# | 280 lines | 190 code | 44 blank | 46 comment | 15 complexity | f6bd20818b6726ce9ed58186cac3c595 MD5 | raw file
  1using System;
  2using System.Collections;
  3using System.Globalization;
  4using System.IO;
  5
  6using Org.BouncyCastle.Utilities;
  7using Org.BouncyCastle.Utilities.Collections;
  8
  9namespace Org.BouncyCastle.Bcpg.OpenPgp
 10{
 11	/// <remarks>
 12	/// Often a PGP key ring file is made up of a succession of master/sub-key key rings.
 13	/// If you want to read an entire public key file in one hit this is the class for you.
 14	/// </remarks>
 15    public class PgpPublicKeyRingBundle
 16    {
 17        private readonly IDictionary pubRings;
 18        private readonly IList order;
 19
 20		private PgpPublicKeyRingBundle(
 21            IDictionary	pubRings,
 22            IList       order)
 23        {
 24            this.pubRings = pubRings;
 25            this.order = order;
 26        }
 27
 28		public PgpPublicKeyRingBundle(
 29            byte[] encoding)
 30            : this(new MemoryStream(encoding, false))
 31        {
 32        }
 33
 34		/// <summary>Build a PgpPublicKeyRingBundle from the passed in input stream.</summary>
 35		/// <param name="inputStream">Input stream containing data.</param>
 36		/// <exception cref="IOException">If a problem parsing the stream occurs.</exception>
 37		/// <exception cref="PgpException">If an object is encountered which isn't a PgpPublicKeyRing.</exception>
 38		public PgpPublicKeyRingBundle(
 39            Stream inputStream)
 40			: this(new PgpObjectFactory(inputStream).AllPgpObjects())
 41		{
 42        }
 43
 44		public PgpPublicKeyRingBundle(
 45            IEnumerable e)
 46        {
 47			this.pubRings = Platform.CreateHashtable();
 48			this.order = Platform.CreateArrayList();
 49
 50			foreach (object obj in e)
 51            {
 52				PgpPublicKeyRing pgpPub = obj as PgpPublicKeyRing;
 53
 54				if (pgpPub == null)
 55				{
 56					throw new PgpException(obj.GetType().FullName + " found where PgpPublicKeyRing expected");
 57				}
 58
 59				long key = pgpPub.GetPublicKey().KeyId;
 60                pubRings.Add(key, pgpPub);
 61				order.Add(key);
 62            }
 63        }
 64
 65		[Obsolete("Use 'Count' property instead")]
 66		public int Size
 67		{
 68			get { return order.Count; }
 69		}
 70
 71		/// <summary>Return the number of key rings in this collection.</summary>
 72        public int Count
 73        {
 74			get { return order.Count; }
 75        }
 76
 77		/// <summary>Allow enumeration of the public key rings making up this collection.</summary>
 78        public IEnumerable GetKeyRings()
 79        {
 80			return new EnumerableProxy(pubRings.Values);
 81        }
 82
 83		/// <summary>Allow enumeration of the key rings associated with the passed in userId.</summary>
 84		/// <param name="userId">The user ID to be matched.</param>
 85		/// <returns>An <c>IEnumerable</c> of key rings which matched (possibly none).</returns>
 86		public IEnumerable GetKeyRings(
 87			string userId)
 88		{
 89			return GetKeyRings(userId, false, false);
 90		}
 91
 92		/// <summary>Allow enumeration of the key rings associated with the passed in userId.</summary>
 93		/// <param name="userId">The user ID to be matched.</param>
 94		/// <param name="matchPartial">If true, userId need only be a substring of an actual ID string to match.</param>
 95		/// <returns>An <c>IEnumerable</c> of key rings which matched (possibly none).</returns>
 96        public IEnumerable GetKeyRings(
 97            string	userId,
 98            bool	matchPartial)
 99        {
100			return GetKeyRings(userId, matchPartial, false);
101        }
102
103		/// <summary>Allow enumeration of the key rings associated with the passed in userId.</summary>
104		/// <param name="userId">The user ID to be matched.</param>
105		/// <param name="matchPartial">If true, userId need only be a substring of an actual ID string to match.</param>
106		/// <param name="ignoreCase">If true, case is ignored in user ID comparisons.</param>
107		/// <returns>An <c>IEnumerable</c> of key rings which matched (possibly none).</returns>
108		public IEnumerable GetKeyRings(
109			string	userId,
110			bool	matchPartial,
111			bool	ignoreCase)
112		{
113			IList rings = Platform.CreateArrayList();
114
115			if (ignoreCase)
116			{
117				userId = userId.ToLower(CultureInfo.InvariantCulture);
118			}
119
120			foreach (PgpPublicKeyRing pubRing in GetKeyRings())
121			{
122				foreach (string nextUserID in pubRing.GetPublicKey().GetUserIds())
123				{
124					string next = nextUserID;
125					if (ignoreCase)
126					{
127						next = next.ToLower(CultureInfo.InvariantCulture);
128					}
129
130					if (matchPartial)
131					{
132						if (next.IndexOf(userId) > -1)
133						{
134							rings.Add(pubRing);
135						}
136					}
137					else
138					{
139						if (next.Equals(userId))
140						{
141							rings.Add(pubRing);
142						}
143					}
144				}
145			}
146
147			return new EnumerableProxy(rings);
148		}
149
150		/// <summary>Return the PGP public key associated with the given key id.</summary>
151		/// <param name="keyId">The ID of the public key to return.</param>
152        public PgpPublicKey GetPublicKey(
153            long keyId)
154        {
155            foreach (PgpPublicKeyRing pubRing in GetKeyRings())
156            {
157                PgpPublicKey pub = pubRing.GetPublicKey(keyId);
158
159				if (pub != null)
160                {
161                    return pub;
162                }
163            }
164
165			return null;
166        }
167
168		/// <summary>Return the public key ring which contains the key referred to by keyId</summary>
169		/// <param name="keyId">key ID to match against</param>
170        public PgpPublicKeyRing GetPublicKeyRing(
171            long keyId)
172        {
173            if (pubRings.Contains(keyId))
174            {
175                return (PgpPublicKeyRing)pubRings[keyId];
176            }
177
178			foreach (PgpPublicKeyRing pubRing in GetKeyRings())
179            {
180                PgpPublicKey pub = pubRing.GetPublicKey(keyId);
181
182                if (pub != null)
183                {
184                    return pubRing;
185                }
186            }
187
188			return null;
189        }
190
191		/// <summary>
192		/// Return true if a key matching the passed in key ID is present, false otherwise.
193		/// </summary>
194		/// <param name="keyID">key ID to look for.</param>
195		public bool Contains(
196			long keyID)
197		{
198			return GetPublicKey(keyID) != null;
199		}
200
201		public byte[] GetEncoded()
202        {
203            MemoryStream bOut = new MemoryStream();
204
205			Encode(bOut);
206
207			return bOut.ToArray();
208        }
209
210		public void Encode(
211            Stream outStr)
212        {
213			BcpgOutputStream bcpgOut = BcpgOutputStream.Wrap(outStr);
214
215			foreach (long key in order)
216            {
217                PgpPublicKeyRing sec = (PgpPublicKeyRing) pubRings[key];
218
219				sec.Encode(bcpgOut);
220            }
221        }
222
223		/// <summary>
224		/// Return a new bundle containing the contents of the passed in bundle and
225		/// the passed in public key ring.
226		/// </summary>
227		/// <param name="bundle">The <c>PgpPublicKeyRingBundle</c> the key ring is to be added to.</param>
228		/// <param name="publicKeyRing">The key ring to be added.</param>
229		/// <returns>A new <c>PgpPublicKeyRingBundle</c> merging the current one with the passed in key ring.</returns>
230		/// <exception cref="ArgumentException">If the keyId for the passed in key ring is already present.</exception>
231        public static PgpPublicKeyRingBundle AddPublicKeyRing(
232            PgpPublicKeyRingBundle  bundle,
233            PgpPublicKeyRing        publicKeyRing)
234        {
235            long key = publicKeyRing.GetPublicKey().KeyId;
236
237			if (bundle.pubRings.Contains(key))
238            {
239                throw new ArgumentException("Bundle already contains a key with a keyId for the passed in ring.");
240            }
241
242			IDictionary newPubRings = Platform.CreateHashtable(bundle.pubRings);
243            IList newOrder = Platform.CreateArrayList(bundle.order);
244
245			newPubRings[key] = publicKeyRing;
246
247			newOrder.Add(key);
248
249			return new PgpPublicKeyRingBundle(newPubRings, newOrder);
250        }
251
252		/// <summary>
253		/// Return a new bundle containing the contents of the passed in bundle with
254		/// the passed in public key ring removed.
255		/// </summary>
256		/// <param name="bundle">The <c>PgpPublicKeyRingBundle</c> the key ring is to be removed from.</param>
257		/// <param name="publicKeyRing">The key ring to be removed.</param>
258		/// <returns>A new <c>PgpPublicKeyRingBundle</c> not containing the passed in key ring.</returns>
259		/// <exception cref="ArgumentException">If the keyId for the passed in key ring is not present.</exception>
260        public static PgpPublicKeyRingBundle RemovePublicKeyRing(
261            PgpPublicKeyRingBundle	bundle,
262            PgpPublicKeyRing		publicKeyRing)
263        {
264            long key = publicKeyRing.GetPublicKey().KeyId;
265
266			if (!bundle.pubRings.Contains(key))
267            {
268                throw new ArgumentException("Bundle does not contain a key with a keyId for the passed in ring.");
269            }
270
271			IDictionary newPubRings = Platform.CreateHashtable(bundle.pubRings);
272            IList newOrder = Platform.CreateArrayList(bundle.order);
273
274			newPubRings.Remove(key);
275			newOrder.Remove(key);
276
277			return new PgpPublicKeyRingBundle(newPubRings, newOrder);
278        }
279    }
280}