X509CertificateParser.cs 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. using System;
  3. using System.Collections;
  4. using System.IO;
  5. using System.Text;
  6. using Org.BouncyCastle.Asn1;
  7. using Org.BouncyCastle.Asn1.Pkcs;
  8. using Org.BouncyCastle.Asn1.X509;
  9. using Org.BouncyCastle.Security.Certificates;
  10. using Org.BouncyCastle.Utilities;
  11. using Org.BouncyCastle.Utilities.Encoders;
  12. using Org.BouncyCastle.Utilities.IO;
  13. namespace Org.BouncyCastle.X509
  14. {
  15. /**
  16. * class for dealing with X509 certificates.
  17. * <p>
  18. * At the moment this will deal with "-----BEGIN CERTIFICATE-----" to "-----END CERTIFICATE-----"
  19. * base 64 encoded certs, as well as the BER binaries of certificates and some classes of PKCS#7
  20. * objects.</p>
  21. */
  22. public class X509CertificateParser
  23. {
  24. private static readonly PemParser PemCertParser = new PemParser("CERTIFICATE");
  25. private Asn1Set sData;
  26. private int sDataObjectCount;
  27. private Stream currentStream;
  28. private X509Certificate ReadDerCertificate(
  29. Asn1InputStream dIn)
  30. {
  31. Asn1Sequence seq = (Asn1Sequence)dIn.ReadObject();
  32. if (seq.Count > 1 && seq[0] is DerObjectIdentifier)
  33. {
  34. if (seq[0].Equals(PkcsObjectIdentifiers.SignedData))
  35. {
  36. sData = SignedData.GetInstance(
  37. Asn1Sequence.GetInstance((Asn1TaggedObject) seq[1], true)).Certificates;
  38. return GetCertificate();
  39. }
  40. }
  41. return CreateX509Certificate(X509CertificateStructure.GetInstance(seq));
  42. }
  43. private X509Certificate GetCertificate()
  44. {
  45. if (sData != null)
  46. {
  47. while (sDataObjectCount < sData.Count)
  48. {
  49. object obj = sData[sDataObjectCount++];
  50. if (obj is Asn1Sequence)
  51. {
  52. return CreateX509Certificate(
  53. X509CertificateStructure.GetInstance(obj));
  54. }
  55. }
  56. }
  57. return null;
  58. }
  59. private X509Certificate ReadPemCertificate(
  60. Stream inStream)
  61. {
  62. Asn1Sequence seq = PemCertParser.ReadPemObject(inStream);
  63. return seq == null
  64. ? null
  65. : CreateX509Certificate(X509CertificateStructure.GetInstance(seq));
  66. }
  67. protected virtual X509Certificate CreateX509Certificate(
  68. X509CertificateStructure c)
  69. {
  70. return new X509Certificate(c);
  71. }
  72. /// <summary>
  73. /// Create loading data from byte array.
  74. /// </summary>
  75. /// <param name="input"></param>
  76. public X509Certificate ReadCertificate(
  77. byte[] input)
  78. {
  79. return ReadCertificate(new MemoryStream(input, false));
  80. }
  81. /// <summary>
  82. /// Create loading data from byte array.
  83. /// </summary>
  84. /// <param name="input"></param>
  85. public ICollection ReadCertificates(
  86. byte[] input)
  87. {
  88. return ReadCertificates(new MemoryStream(input, false));
  89. }
  90. /**
  91. * Generates a certificate object and initializes it with the data
  92. * read from the input stream inStream.
  93. */
  94. public X509Certificate ReadCertificate(
  95. Stream inStream)
  96. {
  97. if (inStream == null)
  98. throw new ArgumentNullException("inStream");
  99. if (!inStream.CanRead)
  100. throw new ArgumentException("inStream must be read-able", "inStream");
  101. if (currentStream == null)
  102. {
  103. currentStream = inStream;
  104. sData = null;
  105. sDataObjectCount = 0;
  106. }
  107. else if (currentStream != inStream) // reset if input stream has changed
  108. {
  109. currentStream = inStream;
  110. sData = null;
  111. sDataObjectCount = 0;
  112. }
  113. try
  114. {
  115. if (sData != null)
  116. {
  117. if (sDataObjectCount != sData.Count)
  118. {
  119. return GetCertificate();
  120. }
  121. sData = null;
  122. sDataObjectCount = 0;
  123. return null;
  124. }
  125. PushbackStream pis = new PushbackStream(inStream);
  126. int tag = pis.ReadByte();
  127. if (tag < 0)
  128. return null;
  129. pis.Unread(tag);
  130. if (tag != 0x30) // assume ascii PEM encoded.
  131. {
  132. return ReadPemCertificate(pis);
  133. }
  134. return ReadDerCertificate(new Asn1InputStream(pis));
  135. }
  136. catch (Exception e)
  137. {
  138. throw new CertificateException("Failed to read certificate", e);
  139. }
  140. }
  141. /**
  142. * Returns a (possibly empty) collection view of the certificates
  143. * read from the given input stream inStream.
  144. */
  145. public ICollection ReadCertificates(
  146. Stream inStream)
  147. {
  148. X509Certificate cert;
  149. IList certs = Org.BouncyCastle.Utilities.Platform.CreateArrayList();
  150. while ((cert = ReadCertificate(inStream)) != null)
  151. {
  152. certs.Add(cert);
  153. }
  154. return certs;
  155. }
  156. }
  157. }
  158. #endif