summary refs log tree commit diff
path: root/Crypto/src/asn1/ocsp
diff options
context:
space:
mode:
Diffstat (limited to 'Crypto/src/asn1/ocsp')
-rw-r--r--Crypto/src/asn1/ocsp/BasicOCSPResponse.cs131
-rw-r--r--Crypto/src/asn1/ocsp/CertID.cs98
-rw-r--r--Crypto/src/asn1/ocsp/CertStatus.cs94
-rw-r--r--Crypto/src/asn1/ocsp/CrlID.cs82
-rw-r--r--Crypto/src/asn1/ocsp/OCSPObjectIdentifiers.cs23
-rw-r--r--Crypto/src/asn1/ocsp/OCSPRequest.cs89
-rw-r--r--Crypto/src/asn1/ocsp/OCSPResponse.cs90
-rw-r--r--Crypto/src/asn1/ocsp/OCSPResponseStatus.cs41
-rw-r--r--Crypto/src/asn1/ocsp/Request.cs90
-rw-r--r--Crypto/src/asn1/ocsp/ResponderID.cs107
-rw-r--r--Crypto/src/asn1/ocsp/ResponseBytes.cs82
-rw-r--r--Crypto/src/asn1/ocsp/ResponseData.cs158
-rw-r--r--Crypto/src/asn1/ocsp/RevokedInfo.cs96
-rw-r--r--Crypto/src/asn1/ocsp/ServiceLocator.cs95
-rw-r--r--Crypto/src/asn1/ocsp/Signature.cs110
-rw-r--r--Crypto/src/asn1/ocsp/SingleResponse.cs137
-rw-r--r--Crypto/src/asn1/ocsp/TBSRequest.cs151
17 files changed, 1674 insertions, 0 deletions
diff --git a/Crypto/src/asn1/ocsp/BasicOCSPResponse.cs b/Crypto/src/asn1/ocsp/BasicOCSPResponse.cs
new file mode 100644
index 000000000..dd666addf
--- /dev/null
+++ b/Crypto/src/asn1/ocsp/BasicOCSPResponse.cs
@@ -0,0 +1,131 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Ocsp
+{
+    public class BasicOcspResponse
+        : Asn1Encodable
+    {
+        private readonly ResponseData			tbsResponseData;
+        private readonly AlgorithmIdentifier	signatureAlgorithm;
+        private readonly DerBitString			signature;
+        private readonly Asn1Sequence			certs;
+
+		public static BasicOcspResponse GetInstance(
+			Asn1TaggedObject	obj,
+			bool				explicitly)
+		{
+			return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+		}
+
+		public static BasicOcspResponse GetInstance(
+			object obj)
+		{
+			if (obj == null || obj is BasicOcspResponse)
+			{
+				return (BasicOcspResponse)obj;
+			}
+
+			if (obj is Asn1Sequence)
+			{
+				return new BasicOcspResponse((Asn1Sequence)obj);
+			}
+
+			throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+		}
+
+		public BasicOcspResponse(
+            ResponseData		tbsResponseData,
+            AlgorithmIdentifier	signatureAlgorithm,
+            DerBitString		signature,
+            Asn1Sequence		certs)
+        {
+            this.tbsResponseData = tbsResponseData;
+            this.signatureAlgorithm = signatureAlgorithm;
+            this.signature = signature;
+            this.certs = certs;
+        }
+
+		private BasicOcspResponse(
+            Asn1Sequence seq)
+        {
+            this.tbsResponseData = ResponseData.GetInstance(seq[0]);
+            this.signatureAlgorithm = AlgorithmIdentifier.GetInstance(seq[1]);
+            this.signature = (DerBitString)seq[2];
+
+			if (seq.Count > 3)
+            {
+                this.certs = Asn1Sequence.GetInstance((Asn1TaggedObject)seq[3], true);
+            }
+        }
+
+		[Obsolete("Use TbsResponseData property instead")]
+		public ResponseData GetTbsResponseData()
+        {
+            return tbsResponseData;
+        }
+
+		public ResponseData TbsResponseData
+		{
+			get { return tbsResponseData; }
+		}
+
+		[Obsolete("Use SignatureAlgorithm property instead")]
+		public AlgorithmIdentifier GetSignatureAlgorithm()
+        {
+            return signatureAlgorithm;
+        }
+
+		public AlgorithmIdentifier SignatureAlgorithm
+		{
+			get { return signatureAlgorithm; }
+		}
+
+		[Obsolete("Use Signature property instead")]
+		public DerBitString GetSignature()
+        {
+            return signature;
+        }
+
+		public DerBitString Signature
+		{
+			get { return signature; }
+		}
+
+		[Obsolete("Use Certs property instead")]
+		public Asn1Sequence GetCerts()
+        {
+            return certs;
+        }
+
+		public Asn1Sequence Certs
+		{
+			get { return certs; }
+		}
+
+		/**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         * BasicOcspResponse       ::= Sequence {
+         *      tbsResponseData      ResponseData,
+         *      signatureAlgorithm   AlgorithmIdentifier,
+         *      signature            BIT STRING,
+         *      certs                [0] EXPLICIT Sequence OF Certificate OPTIONAL }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector(
+				tbsResponseData, signatureAlgorithm, signature);
+
+			if (certs != null)
+            {
+                v.Add(new DerTaggedObject(true, 0, certs));
+            }
+
+			return new DerSequence(v);
+        }
+    }
+}
diff --git a/Crypto/src/asn1/ocsp/CertID.cs b/Crypto/src/asn1/ocsp/CertID.cs
new file mode 100644
index 000000000..4b251095b
--- /dev/null
+++ b/Crypto/src/asn1/ocsp/CertID.cs
@@ -0,0 +1,98 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Ocsp
+{
+    public class CertID
+        : Asn1Encodable
+    {
+        private readonly AlgorithmIdentifier    hashAlgorithm;
+        private readonly Asn1OctetString        issuerNameHash;
+        private readonly Asn1OctetString        issuerKeyHash;
+        private readonly DerInteger             serialNumber;
+
+		public static CertID GetInstance(
+			Asn1TaggedObject	obj,
+			bool				explicitly)
+		{
+			return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+		}
+
+		public static CertID GetInstance(
+			object obj)
+		{
+			if (obj == null || obj is CertID)
+			{
+				return (CertID)obj;
+			}
+
+			if (obj is Asn1Sequence)
+			{
+				return new CertID((Asn1Sequence)obj);
+			}
+
+			throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+		}
+
+		public CertID(
+            AlgorithmIdentifier hashAlgorithm,
+            Asn1OctetString     issuerNameHash,
+            Asn1OctetString     issuerKeyHash,
+            DerInteger          serialNumber)
+        {
+            this.hashAlgorithm = hashAlgorithm;
+            this.issuerNameHash = issuerNameHash;
+            this.issuerKeyHash = issuerKeyHash;
+            this.serialNumber = serialNumber;
+        }
+
+		private CertID(
+            Asn1Sequence seq)
+        {
+			if (seq.Count != 4)
+				throw new ArgumentException("Wrong number of elements in sequence", "seq");
+
+			this.hashAlgorithm = AlgorithmIdentifier.GetInstance(seq[0]);
+            this.issuerNameHash = Asn1OctetString.GetInstance(seq[1]);
+            this.issuerKeyHash = Asn1OctetString.GetInstance(seq[2]);
+            this.serialNumber = DerInteger.GetInstance(seq[3]);
+        }
+
+		public AlgorithmIdentifier HashAlgorithm
+		{
+			get { return hashAlgorithm; }
+		}
+
+		public Asn1OctetString IssuerNameHash
+		{
+			get { return issuerNameHash; }
+		}
+
+		public Asn1OctetString IssuerKeyHash
+		{
+			get { return issuerKeyHash; }
+		}
+
+		public DerInteger SerialNumber
+		{
+			get { return serialNumber; }
+		}
+
+		/**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         * CertID          ::=     Sequence {
+         *     hashAlgorithm       AlgorithmIdentifier,
+         *     issuerNameHash      OCTET STRING, -- Hash of Issuer's DN
+         *     issuerKeyHash       OCTET STRING, -- Hash of Issuers public key
+         *     serialNumber        CertificateSerialNumber }
+         * </pre>
+         */
+		public override Asn1Object ToAsn1Object()
+		{
+			return new DerSequence(hashAlgorithm, issuerNameHash, issuerKeyHash, serialNumber);
+		}
+	}
+}
diff --git a/Crypto/src/asn1/ocsp/CertStatus.cs b/Crypto/src/asn1/ocsp/CertStatus.cs
new file mode 100644
index 000000000..d5b1a94a2
--- /dev/null
+++ b/Crypto/src/asn1/ocsp/CertStatus.cs
@@ -0,0 +1,94 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Ocsp
+{
+    public class CertStatus
+        : Asn1Encodable, IAsn1Choice
+    {
+        private readonly int			tagNo;
+        private readonly Asn1Encodable	value;
+
+		/**
+         * create a CertStatus object with a tag of zero.
+         */
+        public CertStatus()
+        {
+            tagNo = 0;
+            value = DerNull.Instance;
+        }
+
+		public CertStatus(
+            RevokedInfo info)
+        {
+            tagNo = 1;
+            value = info;
+        }
+
+		public CertStatus(
+            int				tagNo,
+            Asn1Encodable	value)
+        {
+            this.tagNo = tagNo;
+            this.value = value;
+        }
+
+		public CertStatus(
+            Asn1TaggedObject choice)
+        {
+            this.tagNo = choice.TagNo;
+
+			switch (choice.TagNo)
+            {
+				case 1:
+					value = RevokedInfo.GetInstance(choice, false);
+					break;
+				case 0:
+				case 2:
+					value = DerNull.Instance;
+					break;
+            }
+        }
+
+		public static CertStatus GetInstance(
+            object obj)
+        {
+            if (obj == null || obj is CertStatus)
+            {
+                return (CertStatus)obj;
+            }
+
+			if (obj is Asn1TaggedObject)
+            {
+                return new CertStatus((Asn1TaggedObject)obj);
+            }
+
+			throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+        }
+
+		public int TagNo
+		{
+			get { return tagNo; }
+		}
+
+		public Asn1Encodable Status
+		{
+			get { return value; }
+		}
+
+		/**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         *  CertStatus ::= CHOICE {
+         *                  good        [0]     IMPLICIT Null,
+         *                  revoked     [1]     IMPLICIT RevokedInfo,
+         *                  unknown     [2]     IMPLICIT UnknownInfo }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            return new DerTaggedObject(false, tagNo, value);
+        }
+    }
+}
diff --git a/Crypto/src/asn1/ocsp/CrlID.cs b/Crypto/src/asn1/ocsp/CrlID.cs
new file mode 100644
index 000000000..cfb3d6fcb
--- /dev/null
+++ b/Crypto/src/asn1/ocsp/CrlID.cs
@@ -0,0 +1,82 @@
+using System;
+using System.Collections;
+
+namespace Org.BouncyCastle.Asn1.Ocsp
+{
+    public class CrlID
+        : Asn1Encodable
+    {
+        private readonly DerIA5String		crlUrl;
+        private readonly DerInteger			crlNum;
+        private readonly DerGeneralizedTime	crlTime;
+
+		// TODO Add GetInstance method(s) and amke this private?
+		public CrlID(
+            Asn1Sequence seq)
+        {
+			foreach (Asn1TaggedObject o in seq)
+			{
+				switch (o.TagNo)
+                {
+                case 0:
+                    crlUrl = DerIA5String.GetInstance(o, true);
+                    break;
+                case 1:
+                    crlNum = DerInteger.GetInstance(o, true);
+                    break;
+                case 2:
+                    crlTime = DerGeneralizedTime.GetInstance(o, true);
+                    break;
+                default:
+                    throw new ArgumentException("unknown tag number: " + o.TagNo);
+                }
+            }
+        }
+
+		public DerIA5String CrlUrl
+		{
+			get { return crlUrl; }
+		}
+
+		public DerInteger CrlNum
+		{
+			get { return crlNum; }
+		}
+
+		public DerGeneralizedTime CrlTime
+		{
+			get { return crlTime; }
+		}
+
+		/**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         * CrlID ::= Sequence {
+         *     crlUrl               [0]     EXPLICIT IA5String OPTIONAL,
+         *     crlNum               [1]     EXPLICIT Integer OPTIONAL,
+         *     crlTime              [2]     EXPLICIT GeneralizedTime OPTIONAL }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector();
+
+			if (crlUrl != null)
+            {
+                v.Add(new DerTaggedObject(true, 0, crlUrl));
+            }
+
+			if (crlNum != null)
+            {
+                v.Add(new DerTaggedObject(true, 1, crlNum));
+            }
+
+			if (crlTime != null)
+            {
+                v.Add(new DerTaggedObject(true, 2, crlTime));
+            }
+
+			return new DerSequence(v);
+        }
+    }
+}
diff --git a/Crypto/src/asn1/ocsp/OCSPObjectIdentifiers.cs b/Crypto/src/asn1/ocsp/OCSPObjectIdentifiers.cs
new file mode 100644
index 000000000..a37c8552d
--- /dev/null
+++ b/Crypto/src/asn1/ocsp/OCSPObjectIdentifiers.cs
@@ -0,0 +1,23 @@
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Ocsp
+{
+    public abstract class OcspObjectIdentifiers
+    {
+        internal const string PkixOcspId = "1.3.6.1.5.5.7.48.1";
+
+		public static readonly DerObjectIdentifier PkixOcsp = new DerObjectIdentifier(PkixOcspId);
+        public static readonly DerObjectIdentifier PkixOcspBasic = new DerObjectIdentifier(PkixOcspId + ".1");
+
+		//
+		// extensions
+		//
+		public static readonly DerObjectIdentifier PkixOcspNonce = new DerObjectIdentifier(PkixOcsp + ".2");
+		public static readonly DerObjectIdentifier PkixOcspCrl = new DerObjectIdentifier(PkixOcsp + ".3");
+
+		public static readonly DerObjectIdentifier PkixOcspResponse = new DerObjectIdentifier(PkixOcsp + ".4");
+		public static readonly DerObjectIdentifier PkixOcspNocheck = new DerObjectIdentifier(PkixOcsp + ".5");
+		public static readonly DerObjectIdentifier PkixOcspArchiveCutoff = new DerObjectIdentifier(PkixOcsp + ".6");
+		public static readonly DerObjectIdentifier PkixOcspServiceLocator = new DerObjectIdentifier(PkixOcsp + ".7");
+	}
+}
diff --git a/Crypto/src/asn1/ocsp/OCSPRequest.cs b/Crypto/src/asn1/ocsp/OCSPRequest.cs
new file mode 100644
index 000000000..1e804d78e
--- /dev/null
+++ b/Crypto/src/asn1/ocsp/OCSPRequest.cs
@@ -0,0 +1,89 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Ocsp
+{
+    public class OcspRequest
+        : Asn1Encodable
+    {
+        private readonly TbsRequest	tbsRequest;
+        private readonly Signature	optionalSignature;
+
+		public static OcspRequest GetInstance(
+			Asn1TaggedObject	obj,
+			bool				explicitly)
+		{
+			return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+		}
+
+		public static OcspRequest GetInstance(
+			object obj)
+		{
+			if (obj == null || obj is OcspRequest)
+			{
+				return (OcspRequest)obj;
+			}
+
+			if (obj is Asn1Sequence)
+			{
+				return new OcspRequest((Asn1Sequence)obj);
+			}
+
+			throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+		}
+
+		public OcspRequest(
+            TbsRequest	tbsRequest,
+            Signature	optionalSignature)
+        {
+			if (tbsRequest == null)
+				throw new ArgumentNullException("tbsRequest");
+
+			this.tbsRequest = tbsRequest;
+            this.optionalSignature = optionalSignature;
+        }
+
+		private OcspRequest(
+            Asn1Sequence seq)
+        {
+            tbsRequest = TbsRequest.GetInstance(seq[0]);
+
+			if (seq.Count == 2)
+            {
+                optionalSignature = Signature.GetInstance(
+					(Asn1TaggedObject)seq[1], true);
+            }
+        }
+
+		public TbsRequest TbsRequest
+		{
+			get { return tbsRequest; }
+		}
+
+		public Signature OptionalSignature
+		{
+			get { return optionalSignature; }
+		}
+
+		/**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         * OcspRequest     ::=     Sequence {
+         *     tbsRequest                  TBSRequest,
+         *     optionalSignature   [0]     EXPLICIT Signature OPTIONAL }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector(tbsRequest);
+
+			if (optionalSignature != null)
+            {
+                v.Add(new DerTaggedObject(true, 0, optionalSignature));
+            }
+
+			return new DerSequence(v);
+        }
+    }
+}
diff --git a/Crypto/src/asn1/ocsp/OCSPResponse.cs b/Crypto/src/asn1/ocsp/OCSPResponse.cs
new file mode 100644
index 000000000..e9aad8100
--- /dev/null
+++ b/Crypto/src/asn1/ocsp/OCSPResponse.cs
@@ -0,0 +1,90 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Ocsp
+{
+    public class OcspResponse
+        : Asn1Encodable
+    {
+        private readonly OcspResponseStatus	responseStatus;
+        private readonly ResponseBytes		responseBytes;
+
+		public static OcspResponse GetInstance(
+			Asn1TaggedObject	obj,
+			bool				explicitly)
+		{
+			return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+		}
+
+		public static OcspResponse GetInstance(
+			object obj)
+		{
+			if (obj == null || obj is OcspResponse)
+			{
+				return (OcspResponse)obj;
+			}
+
+			if (obj is Asn1Sequence)
+			{
+				return new OcspResponse((Asn1Sequence)obj);
+			}
+
+			throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+		}
+
+		public OcspResponse(
+            OcspResponseStatus	responseStatus,
+            ResponseBytes		responseBytes)
+        {
+			if (responseStatus == null)
+				throw new ArgumentNullException("responseStatus");
+
+			this.responseStatus = responseStatus;
+            this.responseBytes = responseBytes;
+        }
+
+		private OcspResponse(
+            Asn1Sequence seq)
+        {
+            responseStatus = new OcspResponseStatus(
+				DerEnumerated.GetInstance(seq[0]));
+
+			if (seq.Count == 2)
+            {
+                responseBytes = ResponseBytes.GetInstance(
+					(Asn1TaggedObject)seq[1], true);
+            }
+        }
+
+		public OcspResponseStatus ResponseStatus
+		{
+			get { return responseStatus; }
+		}
+
+		public ResponseBytes ResponseBytes
+		{
+			get { return responseBytes; }
+		}
+
+		/**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         * OcspResponse ::= Sequence {
+         *     responseStatus         OcspResponseStatus,
+         *     responseBytes          [0] EXPLICIT ResponseBytes OPTIONAL }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector(responseStatus);
+
+			if (responseBytes != null)
+            {
+                v.Add(new DerTaggedObject(true, 0, responseBytes));
+            }
+
+			return new DerSequence(v);
+        }
+    }
+}
diff --git a/Crypto/src/asn1/ocsp/OCSPResponseStatus.cs b/Crypto/src/asn1/ocsp/OCSPResponseStatus.cs
new file mode 100644
index 000000000..653317e33
--- /dev/null
+++ b/Crypto/src/asn1/ocsp/OCSPResponseStatus.cs
@@ -0,0 +1,41 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Ocsp
+{
+    public class OcspResponseStatus
+        : DerEnumerated
+    {
+        public const int Successful = 0;
+        public const int MalformedRequest = 1;
+        public const int InternalError = 2;
+        public const int TryLater = 3;
+        public const int SignatureRequired = 5;
+        public const int Unauthorized = 6;
+
+		/**
+         * The OcspResponseStatus enumeration.
+         * <pre>
+         * OcspResponseStatus ::= Enumerated {
+         *     successful            (0),  --Response has valid confirmations
+         *     malformedRequest      (1),  --Illegal confirmation request
+         *     internalError         (2),  --Internal error in issuer
+         *     tryLater              (3),  --Try again later
+         *                                 --(4) is not used
+         *     sigRequired           (5),  --Must sign the request
+         *     unauthorized          (6)   --Request unauthorized
+         * }
+         * </pre>
+         */
+        public OcspResponseStatus(int value)
+			: base(value)
+        {
+        }
+
+		public OcspResponseStatus(DerEnumerated value)
+			: base(value.Value.IntValue)
+        {
+        }
+    }
+}
diff --git a/Crypto/src/asn1/ocsp/Request.cs b/Crypto/src/asn1/ocsp/Request.cs
new file mode 100644
index 000000000..116c15e73
--- /dev/null
+++ b/Crypto/src/asn1/ocsp/Request.cs
@@ -0,0 +1,90 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Ocsp
+{
+    public class Request
+        : Asn1Encodable
+    {
+        private readonly CertID			reqCert;
+        private readonly X509Extensions	singleRequestExtensions;
+
+		public static Request GetInstance(
+			Asn1TaggedObject	obj,
+			bool				explicitly)
+		{
+			return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+		}
+
+		public static Request GetInstance(
+			object obj)
+		{
+			if (obj == null || obj is Request)
+			{
+				return (Request)obj;
+			}
+
+			if (obj is Asn1Sequence)
+			{
+				return new Request((Asn1Sequence)obj);
+			}
+
+			throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+		}
+
+		public Request(
+            CertID			reqCert,
+            X509Extensions	singleRequestExtensions)
+        {
+			if (reqCert == null)
+				throw new ArgumentNullException("reqCert");
+
+			this.reqCert = reqCert;
+            this.singleRequestExtensions = singleRequestExtensions;
+        }
+
+		private Request(
+			Asn1Sequence seq)
+        {
+			reqCert = CertID.GetInstance(seq[0]);
+
+			if (seq.Count == 2)
+            {
+                singleRequestExtensions = X509Extensions.GetInstance(
+					(Asn1TaggedObject)seq[1], true);
+            }
+        }
+
+		public CertID ReqCert
+		{
+			get { return reqCert; }
+		}
+
+		public X509Extensions SingleRequestExtensions
+		{
+			get { return singleRequestExtensions; }
+		}
+
+		/**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         * Request         ::=     Sequence {
+         *     reqCert                     CertID,
+         *     singleRequestExtensions     [0] EXPLICIT Extensions OPTIONAL }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector(reqCert);
+
+			if (singleRequestExtensions != null)
+            {
+                v.Add(new DerTaggedObject(true, 0, singleRequestExtensions));
+            }
+
+			return new DerSequence(v);
+        }
+    }
+}
diff --git a/Crypto/src/asn1/ocsp/ResponderID.cs b/Crypto/src/asn1/ocsp/ResponderID.cs
new file mode 100644
index 000000000..143b17339
--- /dev/null
+++ b/Crypto/src/asn1/ocsp/ResponderID.cs
@@ -0,0 +1,107 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Ocsp
+{
+    public class ResponderID
+        : Asn1Encodable, IAsn1Choice
+    {
+        private readonly Asn1Encodable id;
+
+		public static ResponderID GetInstance(
+			object obj)
+		{
+			if (obj == null || obj is ResponderID)
+			{
+				return (ResponderID)obj;
+			}
+
+			if (obj is DerOctetString)
+			{
+				return new ResponderID((DerOctetString)obj);
+			}
+
+			if (obj is Asn1TaggedObject)
+			{
+				Asn1TaggedObject o = (Asn1TaggedObject)obj;
+
+				if (o.TagNo == 1)
+				{
+					return new ResponderID(X509Name.GetInstance(o, true));
+				}
+
+				return new ResponderID(Asn1OctetString.GetInstance(o, true));
+			}
+
+			return new ResponderID(X509Name.GetInstance(obj));
+		}
+
+		public ResponderID(
+            Asn1OctetString id)
+        {
+			if (id == null)
+				throw new ArgumentNullException("id");
+
+			this.id = id;
+        }
+
+		public ResponderID(
+            X509Name id)
+        {
+			if (id == null)
+				throw new ArgumentNullException("id");
+
+			this.id = id;
+        }
+
+		public static ResponderID GetInstance(
+			Asn1TaggedObject	obj,
+			bool				isExplicit)
+		{
+			return GetInstance(obj.GetObject()); // must be explicitly tagged
+		}
+
+		public virtual byte[] GetKeyHash()
+		{
+			if (id is Asn1OctetString)
+			{
+				return ((Asn1OctetString)id).GetOctets();
+			}
+
+			return null;
+		}
+
+		public virtual X509Name Name
+		{
+			get
+			{
+				if (id is Asn1OctetString)
+				{
+					return null;
+				}
+
+				return X509Name.GetInstance(id);
+			}
+		}
+
+		/**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         * ResponderID ::= CHOICE {
+         *      byName          [1] Name,
+         *      byKey           [2] KeyHash }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            if (id is Asn1OctetString)
+            {
+                return new DerTaggedObject(true, 2, id);
+            }
+
+			return new DerTaggedObject(true, 1, id);
+        }
+    }
+}
diff --git a/Crypto/src/asn1/ocsp/ResponseBytes.cs b/Crypto/src/asn1/ocsp/ResponseBytes.cs
new file mode 100644
index 000000000..2ce59faea
--- /dev/null
+++ b/Crypto/src/asn1/ocsp/ResponseBytes.cs
@@ -0,0 +1,82 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Ocsp
+{
+    public class ResponseBytes
+        : Asn1Encodable
+    {
+        private readonly DerObjectIdentifier responseType;
+        private readonly Asn1OctetString response;
+
+		public static ResponseBytes GetInstance(
+			Asn1TaggedObject	obj,
+			bool				explicitly)
+		{
+			return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+		}
+
+		public static ResponseBytes GetInstance(
+			object obj)
+		{
+			if (obj == null || obj is ResponseBytes)
+			{
+				return (ResponseBytes)obj;
+			}
+
+			if (obj is Asn1Sequence)
+			{
+				return new ResponseBytes((Asn1Sequence)obj);
+			}
+
+			throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+		}
+
+		public ResponseBytes(
+            DerObjectIdentifier	responseType,
+            Asn1OctetString		response)
+        {
+			if (responseType == null)
+				throw new ArgumentNullException("responseType");
+			if (response == null)
+				throw new ArgumentNullException("response");
+
+			this.responseType = responseType;
+            this.response = response;
+        }
+
+		private ResponseBytes(
+            Asn1Sequence seq)
+        {
+			if (seq.Count != 2)
+				throw new ArgumentException("Wrong number of elements in sequence", "seq");
+
+			this.responseType = DerObjectIdentifier.GetInstance(seq[0]);
+            this.response = Asn1OctetString.GetInstance(seq[1]);
+        }
+
+		public DerObjectIdentifier ResponseType
+		{
+			get { return responseType; }
+		}
+
+		public Asn1OctetString Response
+		{
+			get { return response; }
+		}
+
+		/**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         * ResponseBytes ::=       Sequence {
+         *     responseType   OBJECT IDENTIFIER,
+         *     response       OCTET STRING }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+			return new DerSequence(responseType, response);
+        }
+    }
+}
diff --git a/Crypto/src/asn1/ocsp/ResponseData.cs b/Crypto/src/asn1/ocsp/ResponseData.cs
new file mode 100644
index 000000000..173829db8
--- /dev/null
+++ b/Crypto/src/asn1/ocsp/ResponseData.cs
@@ -0,0 +1,158 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Ocsp
+{
+	public class ResponseData
+		: Asn1Encodable
+	{
+		private static readonly DerInteger V1 = new DerInteger(0);
+
+		private readonly bool                versionPresent;
+		private readonly DerInteger          version;
+		private readonly ResponderID         responderID;
+		private readonly DerGeneralizedTime  producedAt;
+		private readonly Asn1Sequence        responses;
+		private readonly X509Extensions      responseExtensions;
+
+		public static ResponseData GetInstance(
+			Asn1TaggedObject	obj,
+			bool				explicitly)
+		{
+			return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+		}
+
+		public static ResponseData GetInstance(
+			object  obj)
+		{
+			if (obj == null || obj is ResponseData)
+			{
+				return (ResponseData)obj;
+			}
+
+			if (obj is Asn1Sequence)
+			{
+				return new ResponseData((Asn1Sequence)obj);
+			}
+
+			throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+		}
+
+		public ResponseData(
+			DerInteger          version,
+			ResponderID         responderID,
+			DerGeneralizedTime  producedAt,
+			Asn1Sequence        responses,
+			X509Extensions      responseExtensions)
+		{
+			this.version = version;
+			this.responderID = responderID;
+			this.producedAt = producedAt;
+			this.responses = responses;
+			this.responseExtensions = responseExtensions;
+		}
+
+		public ResponseData(
+			ResponderID         responderID,
+			DerGeneralizedTime  producedAt,
+			Asn1Sequence        responses,
+			X509Extensions      responseExtensions)
+			: this(V1, responderID, producedAt, responses, responseExtensions)
+		{
+		}
+
+		private ResponseData(
+			Asn1Sequence seq)
+		{
+			int index = 0;
+
+			Asn1Encodable enc = seq[0];
+			if (enc is Asn1TaggedObject)
+			{
+				Asn1TaggedObject o = (Asn1TaggedObject)enc;
+
+				if (o.TagNo == 0)
+				{
+					this.versionPresent = true;
+					this.version = DerInteger.GetInstance(o, true);
+					index++;
+				}
+				else
+				{
+					this.version = V1;
+				}
+			}
+			else
+			{
+				this.version = V1;
+			}
+
+			this.responderID = ResponderID.GetInstance(seq[index++]);
+			this.producedAt = (DerGeneralizedTime)seq[index++];
+			this.responses = (Asn1Sequence)seq[index++];
+
+			if (seq.Count > index)
+			{
+				this.responseExtensions = X509Extensions.GetInstance(
+					(Asn1TaggedObject)seq[index], true);
+			}
+		}
+
+		public DerInteger Version
+		{
+			get { return version; }
+		}
+
+		public ResponderID ResponderID
+		{
+			get { return responderID; }
+		}
+
+		public DerGeneralizedTime ProducedAt
+		{
+			get { return producedAt; }
+		}
+
+		public Asn1Sequence Responses
+		{
+			get { return responses; }
+		}
+
+		public X509Extensions ResponseExtensions
+		{
+			get { return responseExtensions; }
+		}
+
+		/**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         * ResponseData ::= Sequence {
+         *     version              [0] EXPLICIT Version DEFAULT v1,
+         *     responderID              ResponderID,
+         *     producedAt               GeneralizedTime,
+         *     responses                Sequence OF SingleResponse,
+         *     responseExtensions   [1] EXPLICIT Extensions OPTIONAL }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector();
+
+			if (versionPresent || !version.Equals(V1))
+			{
+				v.Add(new DerTaggedObject(true, 0, version));
+			}
+
+			v.Add(responderID, producedAt, responses);
+
+			if (responseExtensions != null)
+            {
+                v.Add(new DerTaggedObject(true, 1, responseExtensions));
+            }
+
+			return new DerSequence(v);
+        }
+    }
+}
diff --git a/Crypto/src/asn1/ocsp/RevokedInfo.cs b/Crypto/src/asn1/ocsp/RevokedInfo.cs
new file mode 100644
index 000000000..7d9d590e3
--- /dev/null
+++ b/Crypto/src/asn1/ocsp/RevokedInfo.cs
@@ -0,0 +1,96 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Ocsp
+{
+    public class RevokedInfo
+        : Asn1Encodable
+    {
+        private readonly DerGeneralizedTime revocationTime;
+        private readonly CrlReason revocationReason;
+
+		public static RevokedInfo GetInstance(
+			Asn1TaggedObject	obj,
+			bool				explicitly)
+		{
+			return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+		}
+
+		public static RevokedInfo GetInstance(
+			object obj)
+		{
+			if (obj == null || obj is RevokedInfo)
+			{
+				return (RevokedInfo) obj;
+			}
+
+			if (obj is Asn1Sequence)
+			{
+				return new RevokedInfo((Asn1Sequence) obj);
+			}
+
+			throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+		}
+
+		public RevokedInfo(
+			DerGeneralizedTime revocationTime)
+			: this(revocationTime, null)
+		{
+		}
+
+		public RevokedInfo(
+            DerGeneralizedTime  revocationTime,
+            CrlReason           revocationReason)
+        {
+			if (revocationTime == null)
+				throw new ArgumentNullException("revocationTime");
+
+			this.revocationTime = revocationTime;
+            this.revocationReason = revocationReason;
+        }
+
+		private RevokedInfo(
+            Asn1Sequence seq)
+        {
+            this.revocationTime = (DerGeneralizedTime) seq[0];
+
+			if (seq.Count > 1)
+            {
+                this.revocationReason = new CrlReason(
+					DerEnumerated.GetInstance((Asn1TaggedObject) seq[1], true));
+            }
+        }
+
+		public DerGeneralizedTime RevocationTime
+		{
+			get { return revocationTime; }
+		}
+
+		public CrlReason RevocationReason
+		{
+			get { return revocationReason; }
+		}
+
+		/**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         * RevokedInfo ::= Sequence {
+         *      revocationTime              GeneralizedTime,
+         *      revocationReason    [0]     EXPLICIT CRLReason OPTIONAL }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+			Asn1EncodableVector v = new Asn1EncodableVector(revocationTime);
+
+			if (revocationReason != null)
+            {
+                v.Add(new DerTaggedObject(true, 0, revocationReason));
+            }
+
+			return new DerSequence(v);
+        }
+    }
+}
diff --git a/Crypto/src/asn1/ocsp/ServiceLocator.cs b/Crypto/src/asn1/ocsp/ServiceLocator.cs
new file mode 100644
index 000000000..56bc49ded
--- /dev/null
+++ b/Crypto/src/asn1/ocsp/ServiceLocator.cs
@@ -0,0 +1,95 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Ocsp
+{
+    public class ServiceLocator
+        : Asn1Encodable
+    {
+        private readonly X509Name issuer;
+        private readonly Asn1Object locator;
+
+		public static ServiceLocator GetInstance(
+			Asn1TaggedObject	obj,
+			bool				explicitly)
+		{
+			return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+		}
+
+		public static ServiceLocator GetInstance(
+			object obj)
+		{
+			if (obj == null || obj is ServiceLocator)
+			{
+				return (ServiceLocator) obj;
+			}
+
+			if (obj is Asn1Sequence)
+			{
+				return new ServiceLocator((Asn1Sequence) obj);
+			}
+
+			throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+		}
+
+		public ServiceLocator(
+			X509Name	issuer)
+			: this(issuer, null)
+		{
+		}
+
+		public ServiceLocator(
+			X509Name	issuer,
+			Asn1Object	locator)
+		{
+			if (issuer == null)
+				throw new ArgumentNullException("issuer");
+
+			this.issuer = issuer;
+			this.locator = locator;
+		}
+
+		private ServiceLocator(
+			Asn1Sequence seq)
+		{
+			this.issuer = X509Name.GetInstance(seq[0]);
+
+			if (seq.Count > 1)
+			{
+				this.locator = seq[1].ToAsn1Object();
+			}
+		}
+
+		public X509Name Issuer
+		{
+			get { return issuer; }
+		}
+
+		public Asn1Object Locator
+		{
+			get { return locator; }
+		}
+
+		/**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         * ServiceLocator ::= Sequence {
+         *     issuer    Name,
+         *     locator   AuthorityInfoAccessSyntax OPTIONAL }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector(issuer);
+
+			if (locator != null)
+            {
+                v.Add(locator);
+            }
+
+			return new DerSequence(v);
+        }
+    }
+}
diff --git a/Crypto/src/asn1/ocsp/Signature.cs b/Crypto/src/asn1/ocsp/Signature.cs
new file mode 100644
index 000000000..a07e7a709
--- /dev/null
+++ b/Crypto/src/asn1/ocsp/Signature.cs
@@ -0,0 +1,110 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Ocsp
+{
+    public class Signature
+        : Asn1Encodable
+    {
+        internal AlgorithmIdentifier	signatureAlgorithm;
+        internal DerBitString			signatureValue;
+        internal Asn1Sequence			certs;
+
+		public static Signature GetInstance(
+			Asn1TaggedObject	obj,
+			bool				explicitly)
+		{
+			return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+		}
+
+		public static Signature GetInstance(
+			object  obj)
+		{
+			if (obj == null || obj is Signature)
+			{
+				return (Signature)obj;
+			}
+
+			if (obj is Asn1Sequence)
+			{
+				return new Signature((Asn1Sequence)obj);
+			}
+
+			throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+		}
+
+		public Signature(
+            AlgorithmIdentifier signatureAlgorithm,
+            DerBitString        signatureValue)
+			: this(signatureAlgorithm, signatureValue, null)
+        {
+        }
+
+		public Signature(
+            AlgorithmIdentifier	signatureAlgorithm,
+            DerBitString		signatureValue,
+            Asn1Sequence		certs)
+        {
+			if (signatureAlgorithm == null)
+				throw new ArgumentException("signatureAlgorithm");
+			if (signatureValue == null)
+				throw new ArgumentException("signatureValue");
+
+			this.signatureAlgorithm = signatureAlgorithm;
+            this.signatureValue = signatureValue;
+            this.certs = certs;
+        }
+
+		private Signature(
+            Asn1Sequence seq)
+        {
+            signatureAlgorithm = AlgorithmIdentifier.GetInstance(seq[0]);
+            signatureValue = (DerBitString)seq[1];
+
+			if (seq.Count == 3)
+            {
+                certs = Asn1Sequence.GetInstance(
+					(Asn1TaggedObject)seq[2], true);
+            }
+        }
+
+		public AlgorithmIdentifier SignatureAlgorithm
+		{
+			get { return signatureAlgorithm; }
+		}
+
+		public DerBitString SignatureValue
+		{
+			get { return signatureValue; }
+		}
+
+		public Asn1Sequence Certs
+		{
+			get { return certs; }
+		}
+
+		/**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         * Signature       ::=     Sequence {
+         *     signatureAlgorithm      AlgorithmIdentifier,
+         *     signature               BIT STRING,
+         *     certs               [0] EXPLICIT Sequence OF Certificate OPTIONAL}
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector(
+				signatureAlgorithm, signatureValue);
+
+			if (certs != null)
+            {
+                v.Add(new DerTaggedObject(true, 0, certs));
+            }
+
+			return new DerSequence(v);
+        }
+    }
+}
diff --git a/Crypto/src/asn1/ocsp/SingleResponse.cs b/Crypto/src/asn1/ocsp/SingleResponse.cs
new file mode 100644
index 000000000..93d4c21d6
--- /dev/null
+++ b/Crypto/src/asn1/ocsp/SingleResponse.cs
@@ -0,0 +1,137 @@
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+using System;
+
+namespace Org.BouncyCastle.Asn1.Ocsp
+{
+    public class SingleResponse
+        : Asn1Encodable
+    {
+        private readonly CertID              certID;
+        private readonly CertStatus          certStatus;
+        private readonly DerGeneralizedTime  thisUpdate;
+        private readonly DerGeneralizedTime  nextUpdate;
+        private readonly X509Extensions      singleExtensions;
+
+		public SingleResponse(
+            CertID              certID,
+            CertStatus          certStatus,
+            DerGeneralizedTime  thisUpdate,
+            DerGeneralizedTime  nextUpdate,
+            X509Extensions      singleExtensions)
+        {
+            this.certID = certID;
+            this.certStatus = certStatus;
+            this.thisUpdate = thisUpdate;
+            this.nextUpdate = nextUpdate;
+            this.singleExtensions = singleExtensions;
+        }
+
+		public SingleResponse(
+            Asn1Sequence seq)
+        {
+            this.certID = CertID.GetInstance(seq[0]);
+            this.certStatus = CertStatus.GetInstance(seq[1]);
+            this.thisUpdate = (DerGeneralizedTime)seq[2];
+
+			if (seq.Count > 4)
+            {
+                this.nextUpdate = DerGeneralizedTime.GetInstance(
+					(Asn1TaggedObject) seq[3], true);
+                this.singleExtensions = X509Extensions.GetInstance(
+					(Asn1TaggedObject) seq[4], true);
+            }
+            else if (seq.Count > 3)
+            {
+                Asn1TaggedObject o = (Asn1TaggedObject) seq[3];
+
+				if (o.TagNo == 0)
+                {
+                    this.nextUpdate = DerGeneralizedTime.GetInstance(o, true);
+                }
+                else
+                {
+                    this.singleExtensions = X509Extensions.GetInstance(o, true);
+                }
+            }
+        }
+
+		public static SingleResponse GetInstance(
+            Asn1TaggedObject	obj,
+            bool				explicitly)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+        }
+
+		public static SingleResponse GetInstance(
+            object obj)
+        {
+            if (obj == null || obj is SingleResponse)
+            {
+                return (SingleResponse)obj;
+            }
+
+			if (obj is Asn1Sequence)
+            {
+                return new SingleResponse((Asn1Sequence)obj);
+            }
+
+			throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+        }
+
+		public CertID CertId
+		{
+			get { return certID; }
+		}
+
+		public CertStatus CertStatus
+		{
+			get { return certStatus; }
+		}
+
+		public DerGeneralizedTime ThisUpdate
+		{
+			get { return thisUpdate; }
+		}
+
+		public DerGeneralizedTime NextUpdate
+		{
+			get { return nextUpdate; }
+		}
+
+		public X509Extensions SingleExtensions
+		{
+			get { return singleExtensions; }
+		}
+
+		/**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         *  SingleResponse ::= Sequence {
+         *          certID                       CertID,
+         *          certStatus                   CertStatus,
+         *          thisUpdate                   GeneralizedTime,
+         *          nextUpdate         [0]       EXPLICIT GeneralizedTime OPTIONAL,
+         *          singleExtensions   [1]       EXPLICIT Extensions OPTIONAL }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector(
+				certID, certStatus, thisUpdate);
+
+			if (nextUpdate != null)
+            {
+                v.Add(new DerTaggedObject(true, 0, nextUpdate));
+            }
+
+			if (singleExtensions != null)
+            {
+                v.Add(new DerTaggedObject(true, 1, singleExtensions));
+            }
+
+			return new DerSequence(v);
+        }
+    }
+}
diff --git a/Crypto/src/asn1/ocsp/TBSRequest.cs b/Crypto/src/asn1/ocsp/TBSRequest.cs
new file mode 100644
index 000000000..6bf75eb96
--- /dev/null
+++ b/Crypto/src/asn1/ocsp/TBSRequest.cs
@@ -0,0 +1,151 @@
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+using System;
+
+namespace Org.BouncyCastle.Asn1.Ocsp
+{
+    public class TbsRequest
+        : Asn1Encodable
+    {
+		private static readonly DerInteger V1 = new DerInteger(0);
+
+		private readonly DerInteger      version;
+        private readonly GeneralName     requestorName;
+        private readonly Asn1Sequence    requestList;
+        private readonly X509Extensions  requestExtensions;
+
+		private bool versionSet;
+
+		public static TbsRequest GetInstance(
+			Asn1TaggedObject	obj,
+			bool				explicitly)
+		{
+			return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+		}
+
+		public static TbsRequest GetInstance(
+			object obj)
+		{
+			if (obj == null || obj is TbsRequest)
+			{
+				return (TbsRequest)obj;
+			}
+
+			if (obj is Asn1Sequence)
+			{
+				return new TbsRequest((Asn1Sequence)obj);
+			}
+
+			throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+		}
+
+		public TbsRequest(
+            GeneralName     requestorName,
+            Asn1Sequence    requestList,
+            X509Extensions  requestExtensions)
+        {
+            this.version = V1;
+            this.requestorName = requestorName;
+            this.requestList = requestList;
+            this.requestExtensions = requestExtensions;
+        }
+
+		private TbsRequest(
+            Asn1Sequence seq)
+        {
+            int index = 0;
+
+			Asn1Encodable enc = seq[0];
+			if (enc is Asn1TaggedObject)
+            {
+                Asn1TaggedObject o = (Asn1TaggedObject) enc;
+
+				if (o.TagNo == 0)
+                {
+					versionSet = true;
+					version = DerInteger.GetInstance(o, true);
+                    index++;
+                }
+                else
+                {
+                    version = V1;
+                }
+            }
+            else
+            {
+                version = V1;
+            }
+
+			if (seq[index] is Asn1TaggedObject)
+            {
+                requestorName = GeneralName.GetInstance((Asn1TaggedObject) seq[index++], true);
+            }
+
+			requestList = (Asn1Sequence) seq[index++];
+
+			if (seq.Count == (index + 1))
+            {
+                requestExtensions = X509Extensions.GetInstance((Asn1TaggedObject) seq[index], true);
+            }
+        }
+
+		public DerInteger Version
+		{
+			get { return version; }
+		}
+
+		public GeneralName RequestorName
+		{
+			get { return requestorName; }
+		}
+
+		public Asn1Sequence RequestList
+		{
+			get { return requestList; }
+		}
+
+		public X509Extensions RequestExtensions
+		{
+			get { return requestExtensions; }
+		}
+
+		/**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         * TBSRequest      ::=     Sequence {
+         *     version             [0]     EXPLICIT Version DEFAULT v1,
+         *     requestorName       [1]     EXPLICIT GeneralName OPTIONAL,
+         *     requestList                 Sequence OF Request,
+         *     requestExtensions   [2]     EXPLICIT Extensions OPTIONAL }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector();
+
+			//
+			// if default don't include - unless explicitly provided. Not strictly correct
+			// but required for some requests
+			//
+			if (!version.Equals(V1) || versionSet)
+			{
+                v.Add(new DerTaggedObject(true, 0, version));
+            }
+
+			if (requestorName != null)
+            {
+                v.Add(new DerTaggedObject(true, 1, requestorName));
+            }
+
+			v.Add(requestList);
+
+			if (requestExtensions != null)
+            {
+                v.Add(new DerTaggedObject(true, 2, requestExtensions));
+            }
+
+			return new DerSequence(v);
+        }
+    }
+}