EldoS | Feel safer!

Software components for data protection, secure storage and transfer

Signing XML document at client side in browser

Also by EldoS: MsgConnect
Cross-platform protocol-independent communication framework for building peer-to-peer and client-server applications and middleware components.
#21101
Posted: 08/21/2012 11:19:49
by Ken Ivanov (EldoS Corp.)

I have re-read your question and now I am not sure that I understood you correctly. What exactly goal do you want to achieve?
#21111
Posted: 08/22/2012 01:19:26
by janjoris van der Lei (Priority Standard support level)
Joined: 08/16/2012
Posts: 14

Quote
Innokentiy Ivanov wrote:
I have re-read your question and now I am not sure that I understood you correctly. What exactly goal do you want to achieve?


Currently I have this piece of code.

Code
SBDC.TElDCAsyncState State = null;
    using (TElXMLDOMDocument Doc = new TElXMLDOMDocument())
    {
        using (FileStream F = new FileStream(SourceFileName, FileMode.Open, FileAccess.Read))
        {
            Doc.LoadFromStream(F);
        }

      
        TElXMLSigner Signer = new TElXMLSigner();
      
        try
        {
            Signer.SignatureType = SBXMLSec.Unit.xstEnveloped;
            Signer.SignatureMethodType = SBXMLSec.Unit.xmtSig;
            
            Signer.SignatureMethod = SBXMLSec.Unit.xsmRSA_SHA256;
            
            Signer.IncludeKey = false;
          
            

            TElXMLReference Ref = new TElXMLReference();
            Ref.DigestMethod = SBXMLSec.Unit.xdmSHA256;
            Ref.URINode = Doc.DocumentElement;
            Ref.URI = "";
            Ref.TransformChain.Add(new SBXMLTransform.TElXMLEnvelopedSignatureTransform());
                      
            
            Signer.References.Add(Ref);

            Signer.UpdateReferencesDigest();
            Signer.GenerateSignatureAsync();

            TElXMLDOMNode SigNode = Doc.DocumentElement;
            
            State = Signer.InitiateAsyncSign(ref SigNode);
            

        }
        finally
        {
            Signer.Dispose();
          
        }

        using (FileStream F = new FileStream(TempFileName, FileMode.Create, FileAccess.ReadWrite))
        {
            Doc.SaveToStream(F, SBXMLDefs.Unit.xcmNone, "");
        }
    }

    // saving the obtained state to file for debug purposes
    using (FileStream F = new FileStream(StateFileName, FileMode.Create, FileAccess.ReadWrite))
    {
        State.SaveToStream(F, null);
    }

    State.Dispose();


Then in the browser the applet comes and asks the user to choose a certificate. In our case we choose to use the windows certificate store. After the user completes the wizard of the applet we return to the serverside code.

There I try to create a TElDCX509SignOperationHandler and add it to a TElDCStandardServer which will then process the it and get a new userstate from it. With that I would complete the signing with a signer. The problem is that the TElDCX509SignOperationHandler requires a certificatestore and I don't know where to get those certificates from. The client entered the certificates but I don't know how I can link that certificate to the Handler.
#21113
Posted: 08/22/2012 03:31:06
by Ken Ivanov (EldoS Corp.)

I see, thank you for the explanation.

You do not need to create a TElDCX509SignOperationHandler object on the web server side when finalizing the operation. Once the applet completes the signing, it creates a 'state' object that is later encoded and passed back to the server. The server just has to load the obtained blob into a TElDCAsyncState object and pass the latter to the CompleteAsync*() method of the used SBB class:

Code
        // the signature parameter contains a state blob received from the
        // applet
        protected void FinishSigning(ref String fileName, byte[] signature)
        {
            TElDCAsyncState state = new TElDCAsyncState();
            MemoryStream input = new MemoryStream(signature);
            state.LoadFromStream(input, SBDCXMLEnc.__Global.DCXMLEncoding());

            TElPDFDocument doc = new TElPDFDocument();
            TElPDFPublicKeySecurityHandler handler = new TElPDFPublicKeySecurityHandler();
            handler.SignatureType = TSBPDFPublicKeySignatureType.pstPKCS7SHA1;

            FileStream file = new FileStream(fileName, FileMode.Open, FileAccess.ReadWrite);
            try
            {
                doc.CompleteAsyncOperation(file, state, handler);
            }
            finally
            {
                file.Close();
            }


This way, normally you do not need to load any certificates on the finalization stage. The only steps you have to take is load the state into the TElDCAsyncState object, re-create the signing environment (load the pre-signed document into the SBB component and adjust its properties) and pass the state to the CompleteAsync*() method.

BTW, you are saving the state in incorrect way in your code. You should pass an encoding object to the second parameter of the SaveToStream() method:

state.SaveToStream(output, SBDCXMLEnc.__Global.DCXMLEncoding());
#21115
Posted: 08/22/2012 04:08:31
by janjoris van der Lei (Priority Standard support level)
Joined: 08/16/2012
Posts: 14

Ok, I tried this, but with XML. I know get an xml file that seems to be signed. But how can we add the certificate data to the xml file like you it was posted a few posts ago:

Code
  Signer.Signature.KeyInfo.SetKeyData(X509KeyData);
  TElXMLDOMElement El = Signer.Signature.KeyInfo.SaveToXML(Doc);
  Signer.Signature.XMLElement.AppendChild(El);


So my question is: how do we get the contents of the X509KeyData?
#21116
Posted: 08/22/2012 05:17:41
by Dmytro Bogatskyy (EldoS Corp.)

Quote
So my question is: how do we get the contents of the X509KeyData?

You would need to create an instance of TElXMLKeyInfoX509Data, and then set a Certificate property with a signing certificate. To obtain a signing certificate from a state object, please do following:
Code
  TElDCBaseMessage Msg = State.FindMessageByType(TElDCOperationResponseMessage);
  if (Msg != null)
  {
    byte[] buf = TElDCOperationResponseMessage(Msg).KeysRDN.GetFirstValueByOID(      SBDCPKIConstants.Unit.SB_OID_DC_SIGNING_CERTIFICATE)
   // then load certificate from a buffer
  }
#21121
Posted: 08/22/2012 07:55:09
by janjoris van der Lei (Priority Standard support level)
Joined: 08/16/2012
Posts: 14

The buffer I receive seems to be empty.

the code I use is the following:
Code
            TElDCBaseMessage Msg = State.FindMessageByType(TElDCOperationResponseMessage.MetaClass.Instance);
          
            SBX509.TElX509Certificate cert = new SBX509.TElX509Certificate();
          
            if (Msg != null)
            {

                byte[] buf = ((TElDCOperationResponseMessage)Msg).KeysRDN.GetFirstValueByOID(SBDCPKIConstants.__Global.SB_OID_DC_SIGNING_CERTIFICATE);
                cert.LoadFromBuffer(buf);
            }
#21147
Posted: 08/22/2012 20:16:44
by Dmytro Bogatskyy (EldoS Corp.)

Quote
The buffer I receive seems to be empty.

Please add a following code after InitiateAsyncSign method:
Code
TElDCBaseMessage Msg = State.FindMessageByType(TElDCOperationRequestMessage.MetaClass.Instance);
if (Msg != null)
  ((TElDCOperationRequestMessage)Msg).IncludeKeysInResponse = true;


P.S. For the next version I will ensure that TElXMLSigner.IncludeKey property will be used to control DC request message IncludeKeysInResponse property.
#21148
Posted: 08/23/2012 04:22:35
by janjoris van der Lei (Priority Standard support level)
Joined: 08/16/2012
Posts: 14

Thank you, now I can indeed get the certificate from the state.
Now the next thing to do is see if I can use the xades structure and include the CA certificate in the keychain.
#21150
Posted: 08/23/2012 07:08:42
by Dmytro Bogatskyy (EldoS Corp.)

Quote
Now the next thing to do is see if I can use the xades structure and include the CA certificate in the keychain.

You can pass other certificates in the applet and then read them in the similar way as a signing certificate, use:
Code
((TElDCOperationResponseMessage)Msg).KeysRDN.GetValuesByOID(BDCPKIConstants.__Global.SB_OID_DC_CERTIFICATE, ref OutValues)

Then when you have additional cerificates and completed async sign, you can load a signature using TElXMLVerifier and TElXAdESVerifier classes and finally upgrade XAdES to XAdES-X-L form using, for example, TElXAdESVerifier.AddValidationDataValues method.
#21194
Posted: 08/27/2012 04:23:32
by janjoris van der Lei (Priority Standard support level)
Joined: 08/16/2012
Posts: 14

I tried the solution offered in the following post: http://www.eldos.com/forum/read.php?FID=7&TID=3145&MID=17334&sphrase_id=402095#message17334.
But I keep getting an error: "QualifyingProperties object not found (or signature is not calculated).".
Any ideas what I am doing wrong?
Also by EldoS: Rethync
The cross-platform framework that simplifies synchronizing data between mobile and desktop applications and servers and cloud storages

Reply

Statistics

Topic viewed 6682 times

Number of guests: 1, registered members: 0, in total hidden: 0




|

Back to top

As of July 15, 2016 EldoS Corporation will operate as a division of /n software inc. For more information, please read the announcement.

Got it!