Create CMS signature in distributed way with DC
This article concerns the implementation of the client side of the CMS+DC scheme, which is typically represented by a web server in the 'web server - browser' DC relationship.
This article assumes that you are generally familiar with the DC (Distributed Cryptography) concepts, including awareness of the DC parties and their roles. It does not concern the task of implementing the server (in-browser) side of the DC application, and only provides guidance on implementing its client (web server) side.
First, you need to create a so-called pre-signed CMS message and prepare the hash to be sent to the DC server. Create a TElSignedCMSMessage object; add and set up a TElCMSSignature object as you would do in a generic (non-DC) signing scenario:
TElSignedCMSMessage cms = new TElSignedCMSMessage(); cms.CreateNew(…); cms.AddSignature(); TElCMSSignature sig = cms.get_Signatures(0); sig.DigestAlgorithm = SBConstants.Unit.SB_ALGORITHM_DGST_SHA256; sig.SigningTime = DateTime.UtcNow;
Once the signature object is ready, call its InitiateAsyncSign() method:
Save the returned state object in XML form:
TElDCAsyncState state = null; sig.InitiateAsyncSign(ref state);
Save the pre-signed message to some temporary place:
MemoryStream stateOut = new MemoryStream(); state.SaveToStream(stateOut, new TElDCXMLEncoding());
cms.Save(preSignedCmsStream);Now pass the saved state to the DC server for signing. With the 'web server – browser' scheme you normally do this by flushing a web page containing the applet and the state XML embedded to the user's browser.
Having received the signed hash (in the form of XML state) from the DC server, you are ready to proceed to the signing finalization. Re-create a TElSignedCMSMessage object and load your pre-signed message:
Obtain the incomplete signature object:
TElSignedCMSMessage cms = new TElSignedCMSMessage(); cms.Open(preSignedCmsStream, null);
TElCMSSignature sig = cms.get_Signatures(0);Load the received state into a TElDCAsyncState object:
Call the signature object’s CompleteAsyncSign() method:
TElDCAsyncState state = new TElDCAsyncState(); state.LoadFromStream(stateIn, new TElDCXMLEncoding());
Sig.CompleteAsyncSign(state);Save the completed CMS to the needed location:
Note that there are several overloads of the InitiateAsyncSign() method. You are free to choose the one that best suits your scenario. The one that accepts Cert and Chain parameters allows you to pass the signing certificate and its chain to the CMS components (so that they can insert the Signing Certificate attribute). You only need the public part of the signing certificate in this case.