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.X509;
namespace Org.BouncyCastle.Ocsp{
public class OcspReqGenerator
{
private IList list = new ArrayList();
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; }
}
}
}
|