summary refs log tree commit diff
path: root/crypto/src/ocsp
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/src/ocsp')
-rw-r--r--crypto/src/ocsp/BasicOCSPResp.cs220
-rw-r--r--crypto/src/ocsp/BasicOCSPRespGenerator.cs318
-rw-r--r--crypto/src/ocsp/CertificateID.cs141
-rw-r--r--crypto/src/ocsp/CertificateStatus.cs9
-rw-r--r--crypto/src/ocsp/OCSPException.cs28
-rw-r--r--crypto/src/ocsp/OCSPReq.cs268
-rw-r--r--crypto/src/ocsp/OCSPReqGenerator.cs243
-rw-r--r--crypto/src/ocsp/OCSPResp.cs100
-rw-r--r--crypto/src/ocsp/OCSPRespGenerator.cs54
-rw-r--r--crypto/src/ocsp/OCSPRespStatus.cs22
-rw-r--r--crypto/src/ocsp/OCSPUtil.cs132
-rw-r--r--crypto/src/ocsp/Req.cs38
-rw-r--r--crypto/src/ocsp/RespData.cs60
-rw-r--r--crypto/src/ocsp/RespID.cs72
-rw-r--r--crypto/src/ocsp/RevokedStatus.cs58
-rw-r--r--crypto/src/ocsp/SingleResp.cs81
-rw-r--r--crypto/src/ocsp/UnknownStatus.cs15
17 files changed, 1859 insertions, 0 deletions
diff --git a/crypto/src/ocsp/BasicOCSPResp.cs b/crypto/src/ocsp/BasicOCSPResp.cs
new file mode 100644
index 000000000..4253726bb
--- /dev/null
+++ b/crypto/src/ocsp/BasicOCSPResp.cs
@@ -0,0 +1,220 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Ocsp;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Security.Certificates;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.X509;
+using Org.BouncyCastle.X509.Store;
+
+namespace Org.BouncyCastle.Ocsp
+{
+	/// <remarks>
+	/// <code>
+	/// BasicOcspResponse ::= SEQUENCE {
+	///		tbsResponseData		ResponseData,
+	///		signatureAlgorithm	AlgorithmIdentifier,
+	///		signature			BIT STRING,
+	///		certs				[0] EXPLICIT SEQUENCE OF Certificate OPTIONAL
+	/// }
+	/// </code>
+	/// </remarks>
+	public class BasicOcspResp
+		: X509ExtensionBase
+	{
+		private readonly BasicOcspResponse	resp;
+		private readonly ResponseData		data;
+//		private readonly X509Certificate[]	chain;
+
+		public BasicOcspResp(
+			BasicOcspResponse resp)
+		{
+			this.resp = resp;
+			this.data = resp.TbsResponseData;
+		}
+
+		/// <returns>The DER encoding of the tbsResponseData field.</returns>
+		/// <exception cref="OcspException">In the event of an encoding error.</exception>
+		public byte[] GetTbsResponseData()
+		{
+			try
+			{
+				return data.GetDerEncoded();
+			}
+			catch (IOException e)
+			{
+				throw new OcspException("problem encoding tbsResponseData", e);
+			}
+		}
+
+		public int Version
+		{
+			get { return data.Version.Value.IntValue + 1; }
+		}
+
+		public RespID ResponderId
+		{
+			get { return new RespID(data.ResponderID); }
+		}
+
+		public DateTime ProducedAt
+		{
+			get { return data.ProducedAt.ToDateTime(); }
+		}
+
+		public SingleResp[] Responses
+		{
+			get
+			{
+				Asn1Sequence s = data.Responses;
+				SingleResp[] rs = new SingleResp[s.Count];
+
+				for (int i = 0; i != rs.Length; i++)
+				{
+					rs[i] = new SingleResp(SingleResponse.GetInstance(s[i]));
+				}
+
+				return rs;
+			}
+		}
+
+		public X509Extensions ResponseExtensions
+		{
+			get { return data.ResponseExtensions; }
+		}
+
+		protected override X509Extensions GetX509Extensions()
+		{
+			return ResponseExtensions;
+		}
+
+		public string SignatureAlgName
+		{
+			get { return OcspUtilities.GetAlgorithmName(resp.SignatureAlgorithm.ObjectID); }
+		}
+
+		public string SignatureAlgOid
+		{
+			get { return resp.SignatureAlgorithm.ObjectID.Id; }
+		}
+
+		[Obsolete("RespData class is no longer required as all functionality is available on this class")]
+		public RespData GetResponseData()
+		{
+			return new RespData(data);
+		}
+
+		public byte[] GetSignature()
+		{
+			return resp.Signature.GetBytes();
+		}
+
+		private IList GetCertList()
+		{
+			// load the certificates and revocation lists if we have any
+
+			IList certs = Platform.CreateArrayList();
+			Asn1Sequence s = resp.Certs;
+
+			if (s != null)
+			{
+				foreach (Asn1Encodable ae in s)
+				{
+					try
+					{
+						certs.Add(new X509CertificateParser().ReadCertificate(ae.GetEncoded()));
+					}
+					catch (IOException ex)
+					{
+						throw new OcspException("can't re-encode certificate!", ex);
+					}
+					catch (CertificateException ex)
+					{
+						throw new OcspException("can't re-encode certificate!", ex);
+					}
+				}
+			}
+
+			return certs;
+		}
+
+		public X509Certificate[] GetCerts()
+		{
+			IList certs = GetCertList();
+            X509Certificate[] result = new X509Certificate[certs.Count];
+            for (int i = 0; i < certs.Count; ++i)
+            {
+                result[i] = (X509Certificate)certs[i];
+            }
+            return result;
+		}
+
+		/// <returns>The certificates, if any, associated with the response.</returns>
+		/// <exception cref="OcspException">In the event of an encoding error.</exception>
+		public IX509Store GetCertificates(
+			string type)
+		{
+			try
+			{
+				return X509StoreFactory.Create(
+					"Certificate/" + type,
+					new X509CollectionStoreParameters(this.GetCertList()));
+			}
+			catch (Exception e)
+			{
+				throw new OcspException("can't setup the CertStore", e);
+			}
+		}
+
+		/// <summary>
+		/// Verify the signature against the tbsResponseData object we contain.
+		/// </summary>
+		public bool Verify(
+			AsymmetricKeyParameter publicKey)
+		{
+			try
+			{
+				ISigner signature = SignerUtilities.GetSigner(this.SignatureAlgName);
+				signature.Init(false, publicKey);
+				byte[] bs = data.GetDerEncoded();
+				signature.BlockUpdate(bs, 0, bs.Length);
+
+				return signature.VerifySignature(this.GetSignature());
+			}
+			catch (Exception e)
+			{
+				throw new OcspException("exception processing sig: " + e, e);
+			}
+		}
+
+		/// <returns>The ASN.1 encoded representation of this object.</returns>
+		public byte[] GetEncoded()
+		{
+			return resp.GetEncoded();
+		}
+
+		public override bool Equals(
+			object obj)
+		{
+			if (obj == this)
+				return true;
+
+			BasicOcspResp other = obj as BasicOcspResp;
+
+			if (other == null)
+				return false;
+
+			return resp.Equals(other.resp);
+		}
+
+		public override int GetHashCode()
+		{
+			return resp.GetHashCode();
+		}
+	}
+}
diff --git a/crypto/src/ocsp/BasicOCSPRespGenerator.cs b/crypto/src/ocsp/BasicOCSPRespGenerator.cs
new file mode 100644
index 000000000..5ff4bd9cc
--- /dev/null
+++ b/crypto/src/ocsp/BasicOCSPRespGenerator.cs
@@ -0,0 +1,318 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Ocsp;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Security.Certificates;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.X509;
+
+namespace Org.BouncyCastle.Ocsp
+{
+	/**
+	 * Generator for basic OCSP response objects.
+	 */
+	public class BasicOcspRespGenerator
+	{
+		private readonly IList list = Platform.CreateArrayList();
+
+		private X509Extensions responseExtensions;
+		private RespID responderID;
+
+		private class ResponseObject
+		{
+			internal CertificateID         certId;
+			internal CertStatus            certStatus;
+			internal DerGeneralizedTime    thisUpdate;
+			internal DerGeneralizedTime    nextUpdate;
+			internal X509Extensions        extensions;
+
+			public ResponseObject(
+				CertificateID		certId,
+				CertificateStatus	certStatus,
+				DateTime			thisUpdate,
+				X509Extensions		extensions)
+				: this(certId, certStatus, new DerGeneralizedTime(thisUpdate), null, extensions)
+			{
+			}
+
+			public ResponseObject(
+				CertificateID		certId,
+				CertificateStatus	certStatus,
+				DateTime			thisUpdate,
+				DateTime			nextUpdate,
+				X509Extensions		extensions)
+				: this(certId, certStatus, new DerGeneralizedTime(thisUpdate), new DerGeneralizedTime(nextUpdate), extensions)
+			{
+			}
+
+			private ResponseObject(
+				CertificateID		certId,
+				CertificateStatus	certStatus,
+				DerGeneralizedTime	thisUpdate,
+				DerGeneralizedTime	nextUpdate,
+				X509Extensions		extensions)
+			{
+				this.certId = certId;
+
+				if (certStatus == null)
+				{
+					this.certStatus = new CertStatus();
+				}
+				else if (certStatus is UnknownStatus)
+				{
+					this.certStatus = new CertStatus(2, DerNull.Instance);
+				}
+				else
+				{
+					RevokedStatus rs = (RevokedStatus) certStatus;
+					CrlReason revocationReason = rs.HasRevocationReason
+						?	new CrlReason(rs.RevocationReason)
+						:	null;
+
+					this.certStatus = new CertStatus(
+						new RevokedInfo(new DerGeneralizedTime(rs.RevocationTime), revocationReason));
+				}
+
+				this.thisUpdate = thisUpdate;
+				this.nextUpdate = nextUpdate;
+
+				this.extensions = extensions;
+			}
+
+			public SingleResponse ToResponse()
+			{
+				return new SingleResponse(certId.ToAsn1Object(), certStatus, thisUpdate, nextUpdate, extensions);
+			}
+		}
+
+		/**
+		 * basic constructor
+		 */
+		public BasicOcspRespGenerator(
+			RespID responderID)
+		{
+			this.responderID = responderID;
+		}
+
+		/**
+		 * construct with the responderID to be the SHA-1 keyHash of the passed in public key.
+		 */
+		public BasicOcspRespGenerator(
+			AsymmetricKeyParameter publicKey)
+		{
+			this.responderID = new RespID(publicKey);
+		}
+
+		/**
+		 * Add a response for a particular Certificate ID.
+		 *
+		 * @param certID certificate ID details
+		 * @param certStatus status of the certificate - null if okay
+		 */
+		public void AddResponse(
+			CertificateID		certID,
+			CertificateStatus	certStatus)
+		{
+			list.Add(new ResponseObject(certID, certStatus, DateTime.UtcNow, null));
+		}
+
+		/**
+		 * Add a response for a particular Certificate ID.
+		 *
+		 * @param certID certificate ID details
+		 * @param certStatus status of the certificate - null if okay
+		 * @param singleExtensions optional extensions
+		 */
+		public void AddResponse(
+			CertificateID		certID,
+			CertificateStatus	certStatus,
+			X509Extensions		singleExtensions)
+		{
+			list.Add(new ResponseObject(certID, certStatus, DateTime.UtcNow, singleExtensions));
+		}
+
+		/**
+		 * Add a response for a particular Certificate ID.
+		 *
+		 * @param certID certificate ID details
+		 * @param nextUpdate date when next update should be requested
+		 * @param certStatus status of the certificate - null if okay
+		 * @param singleExtensions optional extensions
+		 */
+		public void AddResponse(
+			CertificateID		certID,
+			CertificateStatus	certStatus,
+			DateTime			nextUpdate,
+			X509Extensions		singleExtensions)
+		{
+			list.Add(new ResponseObject(certID, certStatus, DateTime.UtcNow, nextUpdate, singleExtensions));
+		}
+
+		/**
+		 * Add a response for a particular Certificate ID.
+		 *
+		 * @param certID certificate ID details
+		 * @param thisUpdate date this response was valid on
+		 * @param nextUpdate date when next update should be requested
+		 * @param certStatus status of the certificate - null if okay
+		 * @param singleExtensions optional extensions
+		 */
+		public void AddResponse(
+			CertificateID		certID,
+			CertificateStatus	certStatus,
+			DateTime			thisUpdate,
+			DateTime			nextUpdate,
+			X509Extensions		singleExtensions)
+		{
+			list.Add(new ResponseObject(certID, certStatus, thisUpdate, nextUpdate, singleExtensions));
+		}
+
+		/**
+		 * Set the extensions for the response.
+		 *
+		 * @param responseExtensions the extension object to carry.
+		 */
+		public void SetResponseExtensions(
+			X509Extensions responseExtensions)
+		{
+			this.responseExtensions = responseExtensions;
+		}
+
+		private BasicOcspResp GenerateResponse(
+			string					signatureName,
+			AsymmetricKeyParameter	privateKey,
+			X509Certificate[]		chain,
+			DateTime				producedAt,
+			SecureRandom			random)
+		{
+			DerObjectIdentifier signingAlgorithm;
+			try
+			{
+				signingAlgorithm = OcspUtilities.GetAlgorithmOid(signatureName);
+			}
+			catch (Exception e)
+			{
+				throw new ArgumentException("unknown signing algorithm specified", e);
+			}
+
+			Asn1EncodableVector responses = new Asn1EncodableVector();
+
+			foreach (ResponseObject respObj in list)
+			{
+				try
+				{
+					responses.Add(respObj.ToResponse());
+				}
+				catch (Exception e)
+				{
+					throw new OcspException("exception creating Request", e);
+				}
+			}
+
+			ResponseData tbsResp = new ResponseData(responderID.ToAsn1Object(), new DerGeneralizedTime(producedAt), new DerSequence(responses), responseExtensions);
+
+			ISigner sig = null;
+
+			try
+			{
+				sig = SignerUtilities.GetSigner(signatureName);
+
+				if (random != null)
+				{
+					sig.Init(true, new ParametersWithRandom(privateKey, random));
+				}
+				else
+				{
+					sig.Init(true, privateKey);
+				}
+			}
+			catch (Exception e)
+			{
+				throw new OcspException("exception creating signature: " + e, e);
+			}
+
+			DerBitString bitSig = null;
+
+			try
+			{
+				byte[] encoded = tbsResp.GetDerEncoded();
+				sig.BlockUpdate(encoded, 0, encoded.Length);
+
+				bitSig = new DerBitString(sig.GenerateSignature());
+			}
+			catch (Exception e)
+			{
+				throw new OcspException("exception processing TBSRequest: " + e, e);
+			}
+
+			AlgorithmIdentifier sigAlgId = OcspUtilities.GetSigAlgID(signingAlgorithm);
+
+			DerSequence chainSeq = null;
+			if (chain != null && chain.Length > 0)
+			{
+				Asn1EncodableVector v = new Asn1EncodableVector();
+				try
+				{
+					for (int i = 0; i != chain.Length; i++)
+					{
+						v.Add(
+							X509CertificateStructure.GetInstance(
+								Asn1Object.FromByteArray(chain[i].GetEncoded())));
+					}
+				}
+				catch (IOException e)
+				{
+					throw new OcspException("error processing certs", e);
+				}
+				catch (CertificateEncodingException e)
+				{
+					throw new OcspException("error encoding certs", e);
+				}
+
+				chainSeq = new DerSequence(v);
+			}
+
+			return new BasicOcspResp(new BasicOcspResponse(tbsResp, sigAlgId, bitSig, chainSeq));
+		}
+
+		public BasicOcspResp Generate(
+			string					signingAlgorithm,
+			AsymmetricKeyParameter	privateKey,
+			X509Certificate[]		chain,
+			DateTime				thisUpdate)
+		{
+			return Generate(signingAlgorithm, privateKey, chain, thisUpdate, null);
+		}
+
+		public BasicOcspResp Generate(
+			string					signingAlgorithm,
+			AsymmetricKeyParameter	privateKey,
+			X509Certificate[]		chain,
+			DateTime				producedAt,
+			SecureRandom			random)
+		{
+			if (signingAlgorithm == null)
+			{
+				throw new ArgumentException("no signing algorithm specified");
+			}
+
+			return GenerateResponse(signingAlgorithm, privateKey, chain, producedAt, random);
+		}
+
+		/**
+		 * Return an IEnumerable of the signature names supported by the generator.
+		 *
+		 * @return an IEnumerable containing recognised names.
+		 */
+		public IEnumerable SignatureAlgNames
+		{
+			get { return OcspUtilities.AlgNames; }
+		}
+	}
+}
diff --git a/crypto/src/ocsp/CertificateID.cs b/crypto/src/ocsp/CertificateID.cs
new file mode 100644
index 000000000..a8f035759
--- /dev/null
+++ b/crypto/src/ocsp/CertificateID.cs
@@ -0,0 +1,141 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Ocsp;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.X509;
+
+namespace Org.BouncyCastle.Ocsp
+{
+	public class CertificateID
+	{
+		public const string HashSha1 = "1.3.14.3.2.26";
+
+		private readonly CertID id;
+
+		public CertificateID(
+			CertID id)
+		{
+			if (id == null)
+				throw new ArgumentNullException("id");
+
+			this.id = id;
+		}
+
+		/**
+		 * create from an issuer certificate and the serial number of the
+		 * certificate it signed.
+		 * @exception OcspException if any problems occur creating the id fields.
+		 */
+		public CertificateID(
+			string			hashAlgorithm,
+			X509Certificate	issuerCert,
+			BigInteger		serialNumber)
+		{
+			AlgorithmIdentifier hashAlg = new AlgorithmIdentifier(
+				new DerObjectIdentifier(hashAlgorithm), DerNull.Instance);
+
+			this.id = CreateCertID(hashAlg, issuerCert, new DerInteger(serialNumber));
+		}
+
+		public string HashAlgOid
+		{
+			get { return id.HashAlgorithm.ObjectID.Id; }
+		}
+
+		public byte[] GetIssuerNameHash()
+		{
+			return id.IssuerNameHash.GetOctets();
+		}
+
+		public byte[] GetIssuerKeyHash()
+		{
+			return id.IssuerKeyHash.GetOctets();
+		}
+
+		/**
+		 * return the serial number for the certificate associated
+		 * with this request.
+		 */
+		public BigInteger SerialNumber
+		{
+			get { return id.SerialNumber.Value; }
+		}
+
+		public bool MatchesIssuer(
+			X509Certificate	issuerCert)
+		{
+			return CreateCertID(id.HashAlgorithm, issuerCert, id.SerialNumber).Equals(id);
+		}
+
+		public CertID ToAsn1Object()
+		{
+			return id;
+		}
+
+		public override bool Equals(
+			object obj)
+		{
+			if (obj == this)
+				return true;
+
+			CertificateID other = obj as CertificateID;
+
+			if (other == null)
+				return false;
+
+			return id.ToAsn1Object().Equals(other.id.ToAsn1Object());
+		}
+
+		public override int GetHashCode()
+		{
+			return id.ToAsn1Object().GetHashCode();
+		}
+
+
+		/**
+		 * Create a new CertificateID for a new serial number derived from a previous one
+		 * calculated for the same CA certificate.
+		 *
+		 * @param original the previously calculated CertificateID for the CA.
+		 * @param newSerialNumber the serial number for the new certificate of interest.
+		 *
+		 * @return a new CertificateID for newSerialNumber
+		 */
+		public static CertificateID DeriveCertificateID(CertificateID original, BigInteger newSerialNumber)
+		{
+			return new CertificateID(new CertID(original.id.HashAlgorithm, original.id.IssuerNameHash,
+				original.id.IssuerKeyHash, new DerInteger(newSerialNumber)));
+		}
+
+        private static CertID CreateCertID(
+			AlgorithmIdentifier	hashAlg,
+			X509Certificate		issuerCert,
+			DerInteger			serialNumber)
+		{
+			try
+			{
+				String hashAlgorithm = hashAlg.ObjectID.Id;
+
+				X509Name issuerName = PrincipalUtilities.GetSubjectX509Principal(issuerCert);
+				byte[] issuerNameHash = DigestUtilities.CalculateDigest(
+					hashAlgorithm, issuerName.GetEncoded());
+
+				AsymmetricKeyParameter issuerKey = issuerCert.GetPublicKey();
+				SubjectPublicKeyInfo info = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(issuerKey);
+				byte[] issuerKeyHash = DigestUtilities.CalculateDigest(
+					hashAlgorithm, info.PublicKeyData.GetBytes());
+
+				return new CertID(hashAlg, new DerOctetString(issuerNameHash),
+					new DerOctetString(issuerKeyHash), serialNumber);
+			}
+			catch (Exception e)
+			{
+				throw new OcspException("problem creating ID: " + e, e);
+			}
+		}
+	}
+}
diff --git a/crypto/src/ocsp/CertificateStatus.cs b/crypto/src/ocsp/CertificateStatus.cs
new file mode 100644
index 000000000..edfcc2582
--- /dev/null
+++ b/crypto/src/ocsp/CertificateStatus.cs
@@ -0,0 +1,9 @@
+using System;
+
+namespace Org.BouncyCastle.Ocsp
+{
+	public abstract class CertificateStatus
+	{
+		public static readonly CertificateStatus Good = null;
+	}
+}
diff --git a/crypto/src/ocsp/OCSPException.cs b/crypto/src/ocsp/OCSPException.cs
new file mode 100644
index 000000000..db53e559a
--- /dev/null
+++ b/crypto/src/ocsp/OCSPException.cs
@@ -0,0 +1,28 @@
+using System;
+
+namespace Org.BouncyCastle.Ocsp
+{
+#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT)
+    [Serializable]
+#endif
+    public class OcspException
+		: Exception
+	{
+		public OcspException()
+		{
+		}
+
+		public OcspException(
+			string message)
+			: base(message)
+		{
+		}
+
+		public OcspException(
+			string		message,
+			Exception	e)
+			: base(message, e)
+		{
+		}
+	}
+}
diff --git a/crypto/src/ocsp/OCSPReq.cs b/crypto/src/ocsp/OCSPReq.cs
new file mode 100644
index 000000000..84808e50a
--- /dev/null
+++ b/crypto/src/ocsp/OCSPReq.cs
@@ -0,0 +1,268 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Ocsp;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Security.Certificates;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.X509;
+using Org.BouncyCastle.X509.Store;
+
+namespace Org.BouncyCastle.Ocsp
+{
+	/**
+	 * <pre>
+	 * OcspRequest     ::=     SEQUENCE {
+	 *       tbsRequest                  TBSRequest,
+	 *       optionalSignature   [0]     EXPLICIT Signature OPTIONAL }
+	 *
+	 *   TBSRequest      ::=     SEQUENCE {
+	 *       version             [0]     EXPLICIT Version DEFAULT v1,
+	 *       requestorName       [1]     EXPLICIT GeneralName OPTIONAL,
+	 *       requestList                 SEQUENCE OF Request,
+	 *       requestExtensions   [2]     EXPLICIT Extensions OPTIONAL }
+	 *
+	 *   Signature       ::=     SEQUENCE {
+	 *       signatureAlgorithm      AlgorithmIdentifier,
+	 *       signature               BIT STRING,
+	 *       certs               [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL}
+	 *
+	 *   Version         ::=             INTEGER  {  v1(0) }
+	 *
+	 *   Request         ::=     SEQUENCE {
+	 *       reqCert                     CertID,
+	 *       singleRequestExtensions     [0] EXPLICIT Extensions OPTIONAL }
+	 *
+	 *   CertID          ::=     SEQUENCE {
+	 *       hashAlgorithm       AlgorithmIdentifier,
+	 *       issuerNameHash      OCTET STRING, -- Hash of Issuer's DN
+	 *       issuerKeyHash       OCTET STRING, -- Hash of Issuers public key
+	 *       serialNumber        CertificateSerialNumber }
+	 * </pre>
+	 */
+	public class OcspReq
+		: X509ExtensionBase
+	{
+		private OcspRequest req;
+
+		public OcspReq(
+			OcspRequest req)
+		{
+			this.req = req;
+		}
+
+		public OcspReq(
+			byte[] req)
+			: this(new Asn1InputStream(req))
+		{
+		}
+
+		public OcspReq(
+			Stream inStr)
+			: this(new Asn1InputStream(inStr))
+		{
+		}
+
+		private OcspReq(
+			Asn1InputStream aIn)
+		{
+			try
+			{
+				this.req = OcspRequest.GetInstance(aIn.ReadObject());
+			}
+			catch (ArgumentException e)
+			{
+				throw new IOException("malformed request: " + e.Message);
+			}
+			catch (InvalidCastException e)
+			{
+				throw new IOException("malformed request: " + e.Message);
+			}
+		}
+
+		/**
+		 * Return the DER encoding of the tbsRequest field.
+		 * @return DER encoding of tbsRequest
+		 * @throws OcspException in the event of an encoding error.
+		 */
+		public byte[] GetTbsRequest()
+		{
+			try
+			{
+				return req.TbsRequest.GetEncoded();
+			}
+			catch (IOException e)
+			{
+				throw new OcspException("problem encoding tbsRequest", e);
+			}
+		}
+
+		public int Version
+		{
+			get { return req.TbsRequest.Version.Value.IntValue + 1; }
+		}
+
+		public GeneralName RequestorName
+		{
+			get { return GeneralName.GetInstance(req.TbsRequest.RequestorName); }
+		}
+
+		public Req[] GetRequestList()
+		{
+			Asn1Sequence seq = req.TbsRequest.RequestList;
+			Req[] requests = new Req[seq.Count];
+
+			for (int i = 0; i != requests.Length; i++)
+			{
+				requests[i] = new Req(Request.GetInstance(seq[i]));
+			}
+
+			return requests;
+		}
+
+		public X509Extensions RequestExtensions
+		{
+			get { return X509Extensions.GetInstance(req.TbsRequest.RequestExtensions); }
+		}
+
+		protected override X509Extensions GetX509Extensions()
+		{
+			return RequestExtensions;
+		}
+
+		/**
+		 * return the object identifier representing the signature algorithm
+		 */
+		public string SignatureAlgOid
+		{
+			get
+			{
+				if (!this.IsSigned)
+					return null;
+
+				return req.OptionalSignature.SignatureAlgorithm.ObjectID.Id;
+			}
+		}
+
+		public byte[] GetSignature()
+		{
+			if (!this.IsSigned)
+				return null;
+
+			return req.OptionalSignature.SignatureValue.GetBytes();
+		}
+
+		private IList GetCertList()
+		{
+			// load the certificates if we have any
+
+			IList certs = Platform.CreateArrayList();
+			Asn1Sequence s = req.OptionalSignature.Certs;
+
+			if (s != null)
+			{
+				foreach (Asn1Encodable ae in s)
+				{
+					try
+					{
+						certs.Add(new X509CertificateParser().ReadCertificate(ae.GetEncoded()));
+					}
+					catch (Exception e)
+					{
+						throw new OcspException("can't re-encode certificate!", e);
+					}
+				}
+			}
+
+			return certs;
+		}
+
+		public X509Certificate[] GetCerts()
+		{
+			if (!this.IsSigned)
+				return null;
+
+			IList certs = this.GetCertList();
+            X509Certificate[] result = new X509Certificate[certs.Count];
+            for (int i = 0; i < certs.Count; ++i)
+            {
+                result[i] = (X509Certificate)certs[i];
+            }
+            return result;
+		}
+
+		/**
+		 * If the request is signed return a possibly empty CertStore containing the certificates in the
+		 * request. If the request is not signed the method returns null.
+		 *
+		 * @return null if not signed, a CertStore otherwise
+		 * @throws OcspException
+		 */
+		public IX509Store GetCertificates(
+			string type)
+		{
+			if (!this.IsSigned)
+				return null;
+
+			try
+			{
+				return X509StoreFactory.Create(
+					"Certificate/" + type,
+					new X509CollectionStoreParameters(this.GetCertList()));
+			}
+			catch (Exception e)
+			{
+				throw new OcspException("can't setup the CertStore", e);
+			}
+		}
+
+		/**
+		 * Return whether or not this request is signed.
+		 *
+		 * @return true if signed false otherwise.
+		 */
+		public bool IsSigned
+		{
+			get { return req.OptionalSignature != null; }
+		}
+
+		/**
+		 * Verify the signature against the TBSRequest object we contain.
+		 */
+		public bool Verify(
+			AsymmetricKeyParameter publicKey)
+		{
+			if (!this.IsSigned)
+				throw new OcspException("attempt to Verify signature on unsigned object");
+
+			try
+			{
+				ISigner signature = SignerUtilities.GetSigner(this.SignatureAlgOid);
+
+				signature.Init(false, publicKey);
+
+				byte[] encoded = req.TbsRequest.GetEncoded();
+
+				signature.BlockUpdate(encoded, 0, encoded.Length);
+
+				return signature.VerifySignature(this.GetSignature());
+			}
+			catch (Exception e)
+			{
+				throw new OcspException("exception processing sig: " + e, e);
+			}
+		}
+
+		/**
+		 * return the ASN.1 encoded representation of this object.
+		 */
+		public byte[] GetEncoded()
+		{
+			return req.GetEncoded();
+		}
+	}
+}
diff --git a/crypto/src/ocsp/OCSPReqGenerator.cs b/crypto/src/ocsp/OCSPReqGenerator.cs
new file mode 100644
index 000000000..8032a4598
--- /dev/null
+++ b/crypto/src/ocsp/OCSPReqGenerator.cs
@@ -0,0 +1,243 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Ocsp;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Security.Certificates;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.X509;
+
+namespace Org.BouncyCastle.Ocsp
+{
+	public class OcspReqGenerator
+	{
+		private IList			list = Platform.CreateArrayList();
+		private GeneralName		requestorName = null;
+		private X509Extensions	requestExtensions = null;
+
+		private class RequestObject
+		{
+			internal CertificateID certId;
+			internal X509Extensions extensions;
+
+			public RequestObject(
+				CertificateID	certId,
+				X509Extensions	extensions)
+			{
+				this.certId = certId;
+				this.extensions = extensions;
+			}
+
+			public Request ToRequest()
+			{
+				return new Request(certId.ToAsn1Object(), extensions);
+			}
+		}
+
+		/**
+		 * Add a request for the given CertificateID.
+		 *
+		 * @param certId certificate ID of interest
+		 */
+		public void AddRequest(
+			CertificateID certId)
+		{
+			list.Add(new RequestObject(certId, null));
+		}
+
+		/**
+		 * Add a request with extensions
+		 *
+		 * @param certId certificate ID of interest
+		 * @param singleRequestExtensions the extensions to attach to the request
+		 */
+		public void AddRequest(
+			CertificateID   certId,
+			X509Extensions  singleRequestExtensions)
+		{
+			list.Add(new RequestObject(certId, singleRequestExtensions));
+		}
+
+		/**
+		* Set the requestor name to the passed in X509Principal
+		*
+		* @param requestorName a X509Principal representing the requestor name.
+		*/
+		public void SetRequestorName(
+		    X509Name requestorName)
+		{
+		    try
+		    {
+		        this.requestorName = new GeneralName(GeneralName.DirectoryName, requestorName);
+		    }
+		    catch (Exception e)
+		    {
+		        throw new ArgumentException("cannot encode principal", e);
+		    }
+		}
+
+		public void SetRequestorName(
+			GeneralName requestorName)
+		{
+			this.requestorName = requestorName;
+		}
+
+		public void SetRequestExtensions(
+			X509Extensions requestExtensions)
+		{
+			this.requestExtensions = requestExtensions;
+		}
+
+		private OcspReq GenerateRequest(
+			DerObjectIdentifier		signingAlgorithm,
+			AsymmetricKeyParameter	privateKey,
+			X509Certificate[]		chain,
+			SecureRandom			random)
+		{
+			Asn1EncodableVector requests = new Asn1EncodableVector();
+
+			foreach (RequestObject reqObj in list)
+			{
+				try
+				{
+					requests.Add(reqObj.ToRequest());
+				}
+				catch (Exception e)
+				{
+					throw new OcspException("exception creating Request", e);
+				}
+			}
+
+			TbsRequest tbsReq = new TbsRequest(requestorName, new DerSequence(requests), requestExtensions);
+
+			ISigner sig = null;
+			Signature signature = null;
+
+			if (signingAlgorithm != null)
+			{
+				if (requestorName == null)
+				{
+					throw new OcspException("requestorName must be specified if request is signed.");
+				}
+
+				try
+				{
+					sig = SignerUtilities.GetSigner(signingAlgorithm.Id);
+					if (random != null)
+					{
+						sig.Init(true, new ParametersWithRandom(privateKey, random));
+					}
+					else
+					{
+						sig.Init(true, privateKey);
+					}
+				}
+				catch (Exception e)
+				{
+					throw new OcspException("exception creating signature: " + e, e);
+				}
+
+				DerBitString bitSig = null;
+
+				try
+				{
+					byte[] encoded = tbsReq.GetEncoded();
+					sig.BlockUpdate(encoded, 0, encoded.Length);
+
+					bitSig = new DerBitString(sig.GenerateSignature());
+				}
+				catch (Exception e)
+				{
+					throw new OcspException("exception processing TBSRequest: " + e, e);
+				}
+
+				AlgorithmIdentifier sigAlgId = new AlgorithmIdentifier(signingAlgorithm, DerNull.Instance);
+
+				if (chain != null && chain.Length > 0)
+				{
+					Asn1EncodableVector v = new Asn1EncodableVector();
+					try
+					{
+						for (int i = 0; i != chain.Length; i++)
+						{
+							v.Add(
+								X509CertificateStructure.GetInstance(
+									Asn1Object.FromByteArray(chain[i].GetEncoded())));
+						}
+					}
+					catch (IOException e)
+					{
+						throw new OcspException("error processing certs", e);
+					}
+					catch (CertificateEncodingException e)
+					{
+						throw new OcspException("error encoding certs", e);
+					}
+
+					signature = new Signature(sigAlgId, bitSig, new DerSequence(v));
+				}
+				else
+				{
+					signature = new Signature(sigAlgId, bitSig);
+				}
+			}
+
+			return new OcspReq(new OcspRequest(tbsReq, signature));
+		}
+
+		/**
+		 * Generate an unsigned request
+		 *
+		 * @return the OcspReq
+		 * @throws OcspException
+		 */
+		public OcspReq Generate()
+		{
+			return GenerateRequest(null, null, null, null);
+		}
+
+		public OcspReq Generate(
+			string					signingAlgorithm,
+			AsymmetricKeyParameter	privateKey,
+			X509Certificate[]		chain)
+		{
+			return Generate(signingAlgorithm, privateKey, chain, null);
+		}
+
+		public OcspReq Generate(
+			string					signingAlgorithm,
+			AsymmetricKeyParameter	privateKey,
+			X509Certificate[]		chain,
+			SecureRandom			random)
+		{
+			if (signingAlgorithm == null)
+				throw new ArgumentException("no signing algorithm specified");
+
+			try
+			{
+				DerObjectIdentifier oid = OcspUtilities.GetAlgorithmOid(signingAlgorithm);
+
+				return GenerateRequest(oid, privateKey, chain, random);
+			}
+			catch (ArgumentException)
+			{
+				throw new ArgumentException("unknown signing algorithm specified: " + signingAlgorithm);
+			}
+		}
+
+		/**
+		 * Return an IEnumerable of the signature names supported by the generator.
+		 *
+		 * @return an IEnumerable containing recognised names.
+		 */
+		public IEnumerable SignatureAlgNames
+		{
+			get { return OcspUtilities.AlgNames; }
+		}
+	}
+}
diff --git a/crypto/src/ocsp/OCSPResp.cs b/crypto/src/ocsp/OCSPResp.cs
new file mode 100644
index 000000000..dc99c6a9a
--- /dev/null
+++ b/crypto/src/ocsp/OCSPResp.cs
@@ -0,0 +1,100 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Ocsp;
+
+namespace Org.BouncyCastle.Ocsp
+{
+	public class OcspResp
+	{
+		private OcspResponse resp;
+
+		public OcspResp(
+			OcspResponse resp)
+		{
+			this.resp = resp;
+		}
+
+		public OcspResp(
+			byte[] resp)
+			: this(new Asn1InputStream(resp))
+		{
+		}
+
+		public OcspResp(
+			Stream inStr)
+			: this(new Asn1InputStream(inStr))
+		{
+		}
+
+		private OcspResp(
+			Asn1InputStream aIn)
+		{
+			try
+			{
+				this.resp = OcspResponse.GetInstance(aIn.ReadObject());
+			}
+			catch (Exception e)
+			{
+				throw new IOException("malformed response: " + e.Message, e);
+			}
+		}
+
+		public int Status
+		{
+			get { return this.resp.ResponseStatus.Value.IntValue; }
+		}
+
+		public object GetResponseObject()
+		{
+			ResponseBytes rb = this.resp.ResponseBytes;
+
+			if (rb == null)
+				return null;
+
+			if (rb.ResponseType.Equals(OcspObjectIdentifiers.PkixOcspBasic))
+			{
+				try
+				{
+					return new BasicOcspResp(
+						BasicOcspResponse.GetInstance(
+							Asn1Object.FromByteArray(rb.Response.GetOctets())));
+				}
+				catch (Exception e)
+				{
+					throw new OcspException("problem decoding object: " + e, e);
+				}
+			}
+
+			return rb.Response;
+		}
+
+		/**
+		* return the ASN.1 encoded representation of this object.
+		*/
+		public byte[] GetEncoded()
+		{
+			return resp.GetEncoded();
+		}
+
+		public override bool Equals(
+			object obj)
+		{
+			if (obj == this)
+				return true;
+
+			OcspResp other = obj as OcspResp;
+
+			if (other == null)
+				return false;
+
+			return resp.Equals(other.resp);
+		}
+
+		public override int GetHashCode()
+		{
+			return resp.GetHashCode();
+		}
+	}
+}
diff --git a/crypto/src/ocsp/OCSPRespGenerator.cs b/crypto/src/ocsp/OCSPRespGenerator.cs
new file mode 100644
index 000000000..e0eb9ae90
--- /dev/null
+++ b/crypto/src/ocsp/OCSPRespGenerator.cs
@@ -0,0 +1,54 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Ocsp;
+
+namespace Org.BouncyCastle.Ocsp
+{
+	/**
+	 * base generator for an OCSP response - at the moment this only supports the
+	 * generation of responses containing BasicOCSP responses.
+	 */
+	public class OCSPRespGenerator
+	{
+		public const int Successful			= 0;	// Response has valid confirmations
+		public const int MalformedRequest	= 1;	// Illegal confirmation request
+		public const int InternalError		= 2;	// Internal error in issuer
+		public const int TryLater			= 3;	// Try again later
+		// (4) is not used
+		public const int SigRequired		= 5;	// Must sign the request
+		public const int Unauthorized		= 6;	// Request unauthorized
+
+		public OcspResp Generate(
+			int     status,
+			object  response)
+		{
+			if (response == null)
+			{
+				return new OcspResp(new OcspResponse(new OcspResponseStatus(status),null));
+			}
+			if (response is BasicOcspResp)
+			{
+				BasicOcspResp r = (BasicOcspResp)response;
+				Asn1OctetString octs;
+
+				try
+				{
+					octs = new DerOctetString(r.GetEncoded());
+				}
+				catch (Exception e)
+				{
+					throw new OcspException("can't encode object.", e);
+				}
+
+				ResponseBytes rb = new ResponseBytes(
+					OcspObjectIdentifiers.PkixOcspBasic, octs);
+
+				return new OcspResp(new OcspResponse(
+					new OcspResponseStatus(status), rb));
+			}
+
+			throw new OcspException("unknown response object");
+		}
+	}
+}
diff --git a/crypto/src/ocsp/OCSPRespStatus.cs b/crypto/src/ocsp/OCSPRespStatus.cs
new file mode 100644
index 000000000..9c00c7035
--- /dev/null
+++ b/crypto/src/ocsp/OCSPRespStatus.cs
@@ -0,0 +1,22 @@
+using System;
+
+namespace Org.BouncyCastle.Ocsp
+{
+	[Obsolete("Use version with correct spelling 'OcspRespStatus'")]
+	public abstract class OcscpRespStatus : OcspRespStatus
+	{
+	}
+
+	public abstract class OcspRespStatus
+	{
+		/**
+		 * note 4 is not used.
+		 */
+		public const int Successful = 0;		// --Response has valid confirmations
+		public const int MalformedRequest = 1;	// --Illegal confirmation request
+		public const int InternalError = 2;		// --Internal error in issuer
+		public const int TryLater = 3;			// --Try again later
+		public const int SigRequired = 5;		// --Must sign the request
+		public const int Unauthorized = 6;		//  --Request unauthorized
+	}
+}
diff --git a/crypto/src/ocsp/OCSPUtil.cs b/crypto/src/ocsp/OCSPUtil.cs
new file mode 100644
index 000000000..cbc1e95f5
--- /dev/null
+++ b/crypto/src/ocsp/OCSPUtil.cs
@@ -0,0 +1,132 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.CryptoPro;
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.TeleTrust;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+
+namespace Org.BouncyCastle.Ocsp
+{
+	class OcspUtilities
+	{
+		private static readonly IDictionary algorithms = Platform.CreateHashtable();
+        private static readonly IDictionary oids = Platform.CreateHashtable();
+		private static readonly ISet noParams = new HashSet();
+
+		static OcspUtilities()
+		{
+			algorithms.Add("MD2WITHRSAENCRYPTION", PkcsObjectIdentifiers.MD2WithRsaEncryption);
+			algorithms.Add("MD2WITHRSA", PkcsObjectIdentifiers.MD2WithRsaEncryption);
+			algorithms.Add("MD5WITHRSAENCRYPTION", PkcsObjectIdentifiers.MD5WithRsaEncryption);
+			algorithms.Add("MD5WITHRSA", PkcsObjectIdentifiers.MD5WithRsaEncryption);
+			algorithms.Add("SHA1WITHRSAENCRYPTION", PkcsObjectIdentifiers.Sha1WithRsaEncryption);
+			algorithms.Add("SHA1WITHRSA", PkcsObjectIdentifiers.Sha1WithRsaEncryption);
+			algorithms.Add("SHA224WITHRSAENCRYPTION", PkcsObjectIdentifiers.Sha224WithRsaEncryption);
+			algorithms.Add("SHA224WITHRSA", PkcsObjectIdentifiers.Sha224WithRsaEncryption);
+			algorithms.Add("SHA256WITHRSAENCRYPTION", PkcsObjectIdentifiers.Sha256WithRsaEncryption);
+			algorithms.Add("SHA256WITHRSA", PkcsObjectIdentifiers.Sha256WithRsaEncryption);
+			algorithms.Add("SHA384WITHRSAENCRYPTION", PkcsObjectIdentifiers.Sha384WithRsaEncryption);
+			algorithms.Add("SHA384WITHRSA", PkcsObjectIdentifiers.Sha384WithRsaEncryption);
+			algorithms.Add("SHA512WITHRSAENCRYPTION", PkcsObjectIdentifiers.Sha512WithRsaEncryption);
+			algorithms.Add("SHA512WITHRSA", PkcsObjectIdentifiers.Sha512WithRsaEncryption);
+			algorithms.Add("RIPEMD160WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD160);
+			algorithms.Add("RIPEMD160WITHRSA", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD160);
+			algorithms.Add("RIPEMD128WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD128);
+			algorithms.Add("RIPEMD128WITHRSA", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD128);
+			algorithms.Add("RIPEMD256WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD256);
+			algorithms.Add("RIPEMD256WITHRSA", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD256);
+			algorithms.Add("SHA1WITHDSA", X9ObjectIdentifiers.IdDsaWithSha1);
+			algorithms.Add("DSAWITHSHA1", X9ObjectIdentifiers.IdDsaWithSha1);
+			algorithms.Add("SHA224WITHDSA", NistObjectIdentifiers.DsaWithSha224);
+			algorithms.Add("SHA256WITHDSA", NistObjectIdentifiers.DsaWithSha256);
+			algorithms.Add("SHA1WITHECDSA", X9ObjectIdentifiers.ECDsaWithSha1);
+			algorithms.Add("ECDSAWITHSHA1", X9ObjectIdentifiers.ECDsaWithSha1);
+			algorithms.Add("SHA224WITHECDSA", X9ObjectIdentifiers.ECDsaWithSha224);
+			algorithms.Add("SHA256WITHECDSA", X9ObjectIdentifiers.ECDsaWithSha256);
+			algorithms.Add("SHA384WITHECDSA", X9ObjectIdentifiers.ECDsaWithSha384);
+			algorithms.Add("SHA512WITHECDSA", X9ObjectIdentifiers.ECDsaWithSha512);
+			algorithms.Add("GOST3411WITHGOST3410", CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x94);
+			algorithms.Add("GOST3411WITHGOST3410-94", CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x94);
+
+			oids.Add(PkcsObjectIdentifiers.MD2WithRsaEncryption, "MD2WITHRSA");
+			oids.Add(PkcsObjectIdentifiers.MD5WithRsaEncryption, "MD5WITHRSA");
+			oids.Add(PkcsObjectIdentifiers.Sha1WithRsaEncryption, "SHA1WITHRSA");
+			oids.Add(PkcsObjectIdentifiers.Sha224WithRsaEncryption, "SHA224WITHRSA");
+			oids.Add(PkcsObjectIdentifiers.Sha256WithRsaEncryption, "SHA256WITHRSA");
+			oids.Add(PkcsObjectIdentifiers.Sha384WithRsaEncryption, "SHA384WITHRSA");
+			oids.Add(PkcsObjectIdentifiers.Sha512WithRsaEncryption, "SHA512WITHRSA");
+			oids.Add(TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD160, "RIPEMD160WITHRSA");
+			oids.Add(TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD128, "RIPEMD128WITHRSA");
+			oids.Add(TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD256, "RIPEMD256WITHRSA");
+			oids.Add(X9ObjectIdentifiers.IdDsaWithSha1, "SHA1WITHDSA");
+			oids.Add(NistObjectIdentifiers.DsaWithSha224, "SHA224WITHDSA");
+			oids.Add(NistObjectIdentifiers.DsaWithSha256, "SHA256WITHDSA");
+			oids.Add(X9ObjectIdentifiers.ECDsaWithSha1, "SHA1WITHECDSA");
+			oids.Add(X9ObjectIdentifiers.ECDsaWithSha224, "SHA224WITHECDSA");
+			oids.Add(X9ObjectIdentifiers.ECDsaWithSha256, "SHA256WITHECDSA");
+			oids.Add(X9ObjectIdentifiers.ECDsaWithSha384, "SHA384WITHECDSA");
+			oids.Add(X9ObjectIdentifiers.ECDsaWithSha512, "SHA512WITHECDSA");
+			oids.Add(CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x94, "GOST3411WITHGOST3410");
+
+			//
+			// According to RFC 3279, the ASN.1 encoding SHALL (id-dsa-with-sha1) or MUST (ecdsa-with-SHA*) omit the parameters field.
+			// The parameters field SHALL be NULL for RSA based signature algorithms.
+			//
+			noParams.Add(X9ObjectIdentifiers.ECDsaWithSha1);
+			noParams.Add(X9ObjectIdentifiers.ECDsaWithSha224);
+			noParams.Add(X9ObjectIdentifiers.ECDsaWithSha256);
+			noParams.Add(X9ObjectIdentifiers.ECDsaWithSha384);
+			noParams.Add(X9ObjectIdentifiers.ECDsaWithSha512);
+			noParams.Add(X9ObjectIdentifiers.IdDsaWithSha1);
+			noParams.Add(NistObjectIdentifiers.DsaWithSha224);
+			noParams.Add(NistObjectIdentifiers.DsaWithSha256);
+		}
+
+		internal static DerObjectIdentifier GetAlgorithmOid(
+			string algorithmName)
+		{
+			algorithmName = Platform.ToUpperInvariant(algorithmName);
+
+            if (algorithms.Contains(algorithmName))
+			{
+				return (DerObjectIdentifier)algorithms[algorithmName];
+			}
+
+			return new DerObjectIdentifier(algorithmName);
+		}
+
+
+		internal static string GetAlgorithmName(
+			DerObjectIdentifier oid)
+		{
+			if (oids.Contains(oid))
+			{
+				return (string)oids[oid];
+			}
+
+			return oid.Id;
+		}
+
+		internal static AlgorithmIdentifier GetSigAlgID(
+			DerObjectIdentifier sigOid)
+		{
+			if (noParams.Contains(sigOid))
+			{
+				return new AlgorithmIdentifier(sigOid);
+			}
+
+			return new AlgorithmIdentifier(sigOid, DerNull.Instance);
+		}
+
+		internal static IEnumerable AlgNames
+		{
+			get { return new EnumerableProxy(algorithms.Keys); }
+		}
+	}
+}
diff --git a/crypto/src/ocsp/Req.cs b/crypto/src/ocsp/Req.cs
new file mode 100644
index 000000000..68fd9f12a
--- /dev/null
+++ b/crypto/src/ocsp/Req.cs
@@ -0,0 +1,38 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Ocsp;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.X509;
+
+namespace Org.BouncyCastle.Ocsp
+{
+	public class Req
+		: X509ExtensionBase
+	{
+		private Request req;
+
+		public Req(
+			Request req)
+		{
+			this.req = req;
+		}
+
+		public CertificateID GetCertID()
+		{
+			return new CertificateID(req.ReqCert);
+		}
+
+		public X509Extensions SingleRequestExtensions
+		{
+			get { return req.SingleRequestExtensions; }
+		}
+
+		protected override X509Extensions GetX509Extensions()
+		{
+			return SingleRequestExtensions;
+		}
+	}
+}
diff --git a/crypto/src/ocsp/RespData.cs b/crypto/src/ocsp/RespData.cs
new file mode 100644
index 000000000..105726ca7
--- /dev/null
+++ b/crypto/src/ocsp/RespData.cs
@@ -0,0 +1,60 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Ocsp;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.X509;
+
+namespace Org.BouncyCastle.Ocsp
+{
+	public class RespData
+		: X509ExtensionBase
+	{
+		internal readonly ResponseData data;
+
+		public RespData(
+			ResponseData data)
+		{
+			this.data = data;
+		}
+
+		public int Version
+		{
+			get { return data.Version.Value.IntValue + 1; }
+		}
+
+		public RespID GetResponderId()
+		{
+			return new RespID(data.ResponderID);
+		}
+
+		public DateTime ProducedAt
+		{
+			get { return data.ProducedAt.ToDateTime(); }
+		}
+
+		public SingleResp[] GetResponses()
+		{
+			Asn1Sequence s = data.Responses;
+			SingleResp[] rs = new SingleResp[s.Count];
+
+			for (int i = 0; i != rs.Length; i++)
+			{
+				rs[i] = new SingleResp(SingleResponse.GetInstance(s[i]));
+			}
+
+			return rs;
+		}
+
+		public X509Extensions ResponseExtensions
+		{
+			get { return data.ResponseExtensions; }
+		}
+
+		protected override X509Extensions GetX509Extensions()
+		{
+			return ResponseExtensions;
+		}
+	}
+}
diff --git a/crypto/src/ocsp/RespID.cs b/crypto/src/ocsp/RespID.cs
new file mode 100644
index 000000000..3238b26da
--- /dev/null
+++ b/crypto/src/ocsp/RespID.cs
@@ -0,0 +1,72 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Ocsp;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.X509;
+
+namespace Org.BouncyCastle.Ocsp
+{
+	/**
+	 * Carrier for a ResponderID.
+	 */
+	public class RespID
+	{
+		internal readonly ResponderID id;
+
+		public RespID(
+			ResponderID id)
+		{
+			this.id = id;
+		}
+
+		public RespID(
+			X509Name name)
+		{
+	        this.id = new ResponderID(name);
+		}
+
+		public RespID(
+			AsymmetricKeyParameter publicKey)
+		{
+			try
+			{
+				SubjectPublicKeyInfo info = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(publicKey);
+
+				byte[] keyHash = DigestUtilities.CalculateDigest("SHA1", info.PublicKeyData.GetBytes());
+
+				this.id = new ResponderID(new DerOctetString(keyHash));
+			}
+			catch (Exception e)
+			{
+				throw new OcspException("problem creating ID: " + e, e);
+			}
+		}
+
+		public ResponderID ToAsn1Object()
+		{
+			return id;
+		}
+
+		public override bool Equals(
+			object obj)
+		{
+			if (obj == this)
+				return true;
+
+			RespID other = obj as RespID;
+
+			if (other == null)
+				return false;
+
+			return id.Equals(other.id);
+		}
+
+		public override int GetHashCode()
+		{
+			return id.GetHashCode();
+		}
+	}
+}
diff --git a/crypto/src/ocsp/RevokedStatus.cs b/crypto/src/ocsp/RevokedStatus.cs
new file mode 100644
index 000000000..6e5ad1b26
--- /dev/null
+++ b/crypto/src/ocsp/RevokedStatus.cs
@@ -0,0 +1,58 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Ocsp;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Ocsp
+{
+	/**
+	 * wrapper for the RevokedInfo object
+	 */
+	public class RevokedStatus
+		: CertificateStatus
+	{
+		internal readonly RevokedInfo info;
+
+		public RevokedStatus(
+			RevokedInfo info)
+		{
+			this.info = info;
+		}
+
+		public RevokedStatus(
+			DateTime	revocationDate,
+			int			reason)
+		{
+			this.info = new RevokedInfo(new DerGeneralizedTime(revocationDate), new CrlReason(reason));
+		}
+
+		public DateTime RevocationTime
+		{
+			get { return info.RevocationTime.ToDateTime(); }
+		}
+
+		public bool HasRevocationReason
+		{
+			get { return (info.RevocationReason != null); }
+		}
+
+		/**
+		 * return the revocation reason. Note: this field is optional, test for it
+		 * with hasRevocationReason() first.
+		 * @exception InvalidOperationException if a reason is asked for and none is avaliable
+		 */
+		public int RevocationReason
+		{
+			get
+			{
+				if (info.RevocationReason == null)
+				{
+					throw new InvalidOperationException("attempt to get a reason where none is available");
+				}
+
+				return info.RevocationReason.Value.IntValue;
+			}
+		}
+	}
+}
diff --git a/crypto/src/ocsp/SingleResp.cs b/crypto/src/ocsp/SingleResp.cs
new file mode 100644
index 000000000..b8979c538
--- /dev/null
+++ b/crypto/src/ocsp/SingleResp.cs
@@ -0,0 +1,81 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Ocsp;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Utilities.Date;
+using Org.BouncyCastle.X509;
+
+namespace Org.BouncyCastle.Ocsp
+{
+	public class SingleResp
+		: X509ExtensionBase
+	{
+		internal readonly SingleResponse resp;
+
+		public SingleResp(
+			SingleResponse resp)
+		{
+			this.resp = resp;
+		}
+
+		public CertificateID GetCertID()
+		{
+			return new CertificateID(resp.CertId);
+		}
+
+		/**
+		 * Return the status object for the response - null indicates good.
+		 *
+		 * @return the status object for the response, null if it is good.
+		 */
+		public object GetCertStatus()
+		{
+			CertStatus s = resp.CertStatus;
+
+			if (s.TagNo == 0)
+			{
+				return null;            // good
+			}
+
+			if (s.TagNo == 1)
+			{
+				return new RevokedStatus(RevokedInfo.GetInstance(s.Status));
+			}
+
+			return new UnknownStatus();
+		}
+
+		public DateTime ThisUpdate
+		{
+			get { return resp.ThisUpdate.ToDateTime(); }
+		}
+
+		/**
+		* return the NextUpdate value - note: this is an optional field so may
+		* be returned as null.
+		*
+		* @return nextUpdate, or null if not present.
+		*/
+		public DateTimeObject NextUpdate
+		{
+			get
+			{
+				return resp.NextUpdate == null
+					?	null
+					:	new DateTimeObject(resp.NextUpdate.ToDateTime());
+			}
+		}
+
+		public X509Extensions SingleExtensions
+		{
+			get { return resp.SingleExtensions; }
+		}
+
+		protected override X509Extensions GetX509Extensions()
+		{
+			return SingleExtensions;
+		}
+	}
+}
diff --git a/crypto/src/ocsp/UnknownStatus.cs b/crypto/src/ocsp/UnknownStatus.cs
new file mode 100644
index 000000000..c0f7a3a64
--- /dev/null
+++ b/crypto/src/ocsp/UnknownStatus.cs
@@ -0,0 +1,15 @@
+using System;
+
+namespace Org.BouncyCastle.Ocsp
+{
+	/**
+	 * wrapper for the UnknownInfo object
+	 */
+	public class UnknownStatus
+		: CertificateStatus
+	{
+		public UnknownStatus()
+		{
+		}
+	}
+}