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