Visual Studio 2010 Beta 2: Why this Lack of Pureness Again? 

Developer pureness is what we should all strive for.

This is not it:

Conflicting with this:

[c:\NetFx4\versiontester\bin\debug]corflags VersionTester.exe
Microsoft (R) .NET Framework CorFlags Conversion Tool.  Version  3.5.21022.8
Copyright (c) Microsoft Corporation.  All rights reserved.

Version   : v4.0.21006
CLR Header: 2.5
PE        : PE32
CorFlags  : 1
ILONLY    : 1
32BIT     : 0
Signed    : 0

Visual Studio must display version number of 4.0 instead of 4 in RTM. It needs to display major and minor number of the new framework coherently with 2.0, 3.0, 3.5.

Otherwise my compulsive disorder kicks in.

Categories:  .NET 4.0 - General
Saturday, October 24, 2009 12:50:47 PM (Central Europe Standard Time, UTC+01:00)  #    Comments

 

 ServiceModel: Assembly Size in .NET 4.0 

I'm just poking around the new framework, dealing with corflags and CLR Header versions (more on that later), but what I found is the following.

Do a dir *.dll /o:-s in the framework directory. You get this on .NET FX 4.0 beta 2 box:

[c:\windows\microsoft.net\framework64\v4.0.21006]dir *.dll /o:-s

 Volume in drive C is 7  Serial number is 1ED5:8CA5
 Directory of  C:\Windows\Microsoft.NET\Framework64\v4.0.21006\*.dll

 7.10.2009 3:44   9.833.784  clr.dll
 7.10.2009 2:44   6.072.664  System.ServiceModel.dll
 7.10.2009 2:44   5.251.928  System.Windows.Forms.dll
 7.10.2009 6:04   5.088.584  System.Web.dll
 7.10.2009 5:31   5.086.024  System.Design.dll
 7.10.2009 3:44   4.927.808  mscorlib.dll
 7.10.2009 3:44   3.529.608  Microsoft.VB.Activities.Compiler.dll
 7.10.2009 2:44   3.501.376  System.dll
 7.10.2009 2:44   3.335.000  System.Data.Entity.dll
 7.10.2009 3:44   3.244.360  System.Data.dll
 7.10.2009 2:44   2.145.096  System.XML.dll
 7.10.2009 5:31   1.784.664  System.Web.Extensions.dll
 7.10.2009 2:44   1.711.488  System.Windows.Forms.DataVis.dll
 7.10.2009 5:31   1.697.128  System.Web.DataVis.dll
 7.10.2009 5:31   1.578.352  System.Workflow.ComponentModel.dll
 7.10.2009 3:44   1.540.928  clrjit.dll
 7.10.2009 3:44   1.511.752  mscordacwks.dll
 7.10.2009 3:44   1.454.400  mscordbi.dll
 7.10.2009 2:44   1.339.248  System.Activities.Presentation.dll
 7.10.2009 5:31   1.277.776  Microsoft.Build.dll
 7.10.2009 2:44   1.257.800  System.Core.dll
 7.10.2009 2:44   1.178.448  System.Activities.dll
 7.10.2009 5:31   1.071.464  System.Workflow.Activities.dll
 7.10.2009 5:31   1.041.256  Microsoft.Build.Tasks.v4.0.dll
 7.10.2009 2:44   1.026.920  System.Runtime.Serialization.dll

Funny how many engineer dollars are/were spent on middle tier technologies I love.

Proof: System.ServiceModel.dll is bigger then System.dll, System.Windows.Forms.dll, mscorlib.dll, and System.Data.dll.

We only bow to clr.dll, a new .NET 4.0 Common Language Runtime implementation.

Categories:  .NET 4.0 - General | .NET 4.0 - WCF
Saturday, October 24, 2009 12:39:05 PM (Central Europe Standard Time, UTC+01:00)  #    Comments

 

 Talk at Interoperability Day 2009 

Interoperability day is focused on, well, interoperability. Especially between major vendors in government space.

We talked about major issues in long term document preservation formats and the penetration of Office serialization in real world...

.. and the lack of support from legislature covering long term electronic document formats and their use.

Here's the PPT [Slovenian].

Categories:  Other | Work
Wednesday, June 03, 2009 2:23:45 PM (Central Europe Standard Time, UTC+01:00)  #    Comments

 

 Speaking at Document Interop Initiative 

On Monday, 05/18/2009 I'm speaking at Document Interop Initiative in London, England.

Title of the talk is: High Fidelity Programmatic Access to Document Content, which will cover the following topics:

  • Importance of OOXML as a standards based format, especially in technical issues of long term storage for document content preservation
  • Importance of legal long term storage for document formats
  • Signature and timestamp benefits of long term XML formats
  • Performance and actual cost analysis of using publicly-parsable formats
  • Benefits of having a high fidelity programmatic access to document content, backed with standardization

The event is held at Microsoft Limited, Cardinal Place, 100 Victoria Street SW1E 5JL, London.

Update: Here's the presentation.

Categories:  Microsoft | Work
Saturday, May 16, 2009 7:21:51 PM (Central Europe Standard Time, UTC+01:00)  #    Comments

 

 Designing Clean Object Models with SvcUtil.exe 

There are a couple situations where one might use svcutil.exe in command prompt vs. Add Service Reference in Visual Studio.

At least a couple.

I don't know who (or why) made a decision not to support namespace-less proxy generation in  Visual Studio. It's a fact that if you make a service reference, you have to specify a nested namespace.

On the other end, there is an option to make the proxy class either public or internal, which enables one to hide it from the outside world.

That's a design flaw. There are numerous cases, where you would not want to create another [1] namespace, because you are designing an object model that needs to be clean.

[1] This is only limited to local type system namespace declarations - it does not matter what you are sending over the wire.

Consider the following namespace and class hierarchy that uses a service proxy (MyNamespace.Service class uses it):

Suppose that the Service class uses a WCF service, which synchronizes articles and comments with another system. If you use Add Web Reference, there is no way to hide the generated service namespace. One would probably define MyNamespace.MyServiceProxy as a namespace and declared a using statement in MyNamespace.MyService scope with:

using MyNamespace.MyServiceProxy;

This results in a dirty object model - your clients will see your internals and that shouldn't be an option.

Your class hierarchy now has another namespace, called MyNamespace.ServiceProxy, which is actually only used inside the MyNamespace.Service class.

What one can do is insist that the generated classes are marked internal, hiding the classes from the outside world, but still leaving an empty namespace visible for instantiating assemblies.

Leaving only the namespace visible, with no public classes in it is pure cowardness.

Not good.

Since there is no internal namespace modifier in .NET, you have no other way of hiding your namespace, even if you demand internal classes to be generated by the Add Service Reference dialog.

So, svcutil.exe to the rescue:

svcutil.exe <metadata endpoint>
   /namespace:*, MyNamespace
   /internal
   /out:ServiceProxyClass.cs

The /namespace option allows you to map between XML and CLR namespace declarations. The preceding examples maps all (therefore *) existing XML namespaces in service metadata to MyNamespace CLR namespace.

The example will generate a service proxy class, mark it internal and put it into the desired namespace.

Your object model will look like this:

Currently, this is the only way to hide the internals of service communication with a proxy and still being able to keep your object model clean.

Note that this is useful when you want to wrap an existing service proxy or hide a certain already supported service implementation detail in your object model. Since your client code does not need to have access to complete service proxy (or you want to enhance it), it shouldn't be a problem to hide it completely.

Considering options during proxy generation, per method access modifiers would be beneficial too.

Categories:  .NET 3.5 - WCF | Web Services
Friday, April 10, 2009 10:06:43 PM (Central Europe Standard Time, UTC+01:00)  #    Comments

 

 Bug in XmlSerializer, XmlSerializerNamespaces 

XmlSerializer is a great peace of technology. Combined with xsd.exe and friends (XmlSerializerNamespaces, et al.) it's a powerful tool for one to get around XML instance serialization/deserialization.

But, there is a potentially serious bug present, even in 3.5 SP1 version of the .NET Framework.

Suppose we have the following XML structure:

<Envelope xmlns="NamespaceA"
          xmlns:B="NamespaceB">
  <B:Header></B:Header>
  <Body></Body>
</Envelope>

This tells you that Envelope, and Body elements are in the same namespace (namely 'NamespaceA'), while Header is qualified with 'NamespaceB'.

Now suppose we need to programmatically insert <B:Header> element into an empty, core, document.

Core document:

<Envelope xmlns="NamespaceA"
          xmlns:B="NamespaceB">
  <Body></Body>
</Envelope>

Now do an XmlNode.InsertNode() of the following:

<B:Header>...</B:Header>

We should get:

<Envelope xmlns="NamespaceA"
          xmlns:B="NamespaceB">
  <B:Header>...</B:Header>
  <Body></Body>
</Envelope>

To get the to be inserted part one would serialize (using XmlSerializer) the following Header document:

<B: Header xmlns:B="NamespaceB">
  ...
</B:Header>

To do this, a simple XmlSerializer magic will do the trick:

XmlSerializerNamespaces xsn = new XmlSerializerNamespaces();
xsn.Add("B", "NamespaceB");

XmlSerializer xSer = new XmlSerializer(typeof(Header));
XmlTextWriter tw = new XmlTextWriter(ms, null);
xSer.Serialize(tw, h, xsn);

ms.Seek(0, SeekOrigin.Begin);

XmlDocument doc = new XmlDocument()
doc.Load(ms);
ms.Close();

This would generate exactly what we wanted. A prefixed namespace based XML document, with the B prefix bound to 'NamespaceB'.

Now, if we would import this document fragment into our core document using XmlNode.ImportNode(), we would get:

<Envelope xmlns="NamespaceA"
          xmlns:B="NamespaceB">
  <B:Header xmlns:B="NamespaceB">...</B:Header>
  <Body></Body>
</Envelope>

Which is valid and actually, from an XML Infoset view, an isomorphic document to the original. So what if it's got the same namespace declared twice, right?

Right - until you involve digital signatures. I have described a specific problem with ambient namespaces in length in this blog entry: XmlSerializer, Ambient XML Namespaces and Digital Signatures.

When importing a node from another context, XmlNode and friends do a resolve against all namespace declarations in scope. So, when importing such a header, we shouldn't get a duplicate namespace declaration.

The problem is, we don't get a duplicate namespace declaration, since XmlSerializer actually inserts a normal XML attribute into the Header element. That's why we seem to get another namespace declaration. It's actually not a declaration but a plain old attribute. It's even visible (in this case in XmlElement.Attributes), and it definitely shouldn't be there.

So if you hit this special case, remove all attributes before importing the node into your core document. Like this:

XmlSerializerNamespaces xsn = new XmlSerializerNamespaces();
xsn.Add("B", "NamespaceB");

XmlSerializer xSer = new XmlSerializer(typeof(Header));
XmlTextWriter tw = new XmlTextWriter(ms, null);
xSer.Serialize(tw, h, xsn);

ms.Seek(0, SeekOrigin.Begin);

XmlDocument doc = new XmlDocument()
doc.Load(ms);
ms.Close();
doc.DocumentElement.Attributes.RemoveAll();

Note that the serialized document representation will not change, since an ambient namespace declaration (B linked to 'NamespaceB') still exists in the XML Infoset of doc XML document.

Categories:  .NET 3.5 - General | XML
Monday, April 06, 2009 1:22:33 PM (Central Europe Standard Time, UTC+01:00)  #    Comments

 

 DOW(n) 

DOW is down almost 700, again. And...

... I just have to post this. Especially when almost everything (besides devaluation of the safe currency) has already been done.

If you had bought $1,000.00 of Nortel stock one year ago, it would now be worth $49.00.

With
Enron, you would have $16.50 of the original $1,000.00.

With
MCI/Worldcom, you would have less than $5.00 left.

If you had bought $1,000.00 worth of
Miller Genuine Draft (the beer, not the stock) one year ago, drunk all the beer then turned in the cans for the 10-cent deposit, you would have $214.00.

Based on the above, 401KegPlan.com's current investment advice is to take that $5.00 you have left over and
drink lots and lots of beer and recycle.

Via: http://401kegplan.com/keg/

We are going over the edge. We as a world economy.

And yea, I opened a keg of Guinness.

Categories:  Personal
Thursday, October 09, 2008 9:29:37 PM (Central Europe Standard Time, UTC+01:00)  #    Comments

 

 Bleeding Edge 2008: Postback 

I'm sorry it took a week, but here we go.

This is my exit content from Bleeding Edge 2008. I'm also posting complete conference contents, just in case.

Thanks go out to Dušan, Dejan, Miha, Miha and Miha.

Downloads:

Remark: PPT in Slovene only. Code international.

Thank you for attending. Hope to see you next year!

Categories:  CLR | Conferences | Microsoft | Web Services | Work
Thursday, October 09, 2008 8:42:02 PM (Central Europe Standard Time, UTC+01:00)  #    Comments

 

 XmlSerializer: Serialized Syntax and How to Override It 

Recently I needed to specify exactly how I would like a specific class serialized. Suppose we have the following simple schema:

<xs:schema targetNamespace="http://my.favourite.ns/person.xsd"
   elementFormDefault="qualified"
   xmlns:xs="
http://www.w3.org/2001/XMLSchema"
  
xmlns="http://my.favourite.ns/person.xsd">
  <xs:complexType name="Person">
    <xs:sequence>
      <xs:element name="Name" type="xs:string" />
      <xs:element name="Surname" type="xs:string" />
      <xs:element name="Age" type="xs:int" minOccurs="0" />
    </xs:sequence>
  </xs:complexType>
</xs:schema>

Let's call this schema President.xsd.

A valid XML instance against this schema would be, for example:

<Person xmlns="http://my.favourite.ns/person.xsd">
   <Name>Barrack</Name>
   <Surname>Obama</Surname>
   <Age>47</Age>
</Person>

Since we are serializing against a specific XML schema (XSD), we have an option of schema compilation:

xsd /c President.xsd

This, obviously, yields a programmatic type system result in a form of a C# class. All well and done.

Now.

If we serialize the filled up class instance back to XML, we get a valid XML instance. It's valid against President.xsd.

There is a case where your schema changes ever so slightly - read, the namespaces change, and you don't want to recompile the entire solution to support this, but you still want to use XML serialization. Who doesn't - what do you do?

Suppose we want to get the following back, when serializing:

<PresidentPerson xmlns="http://schemas.gama-system.com/
      president.xsd"
>
   <Name>Barrack</Name>
   <Surname>Obama</Surname>
   <Age>47</Age>
</PresidentPerson>

There is an option to override the default serialization technique of XmlSerializer. Enter  the world of XmlAttributes and XmlAttributeOverrides:

private XmlSerializer GetOverridedSerializer()
{
   // set overrides for person element
   XmlAttributes attrsPerson = new XmlAttributes();
   XmlRootAttribute rootPerson =
      new XmlRootAttribute("PresidentPerson");
   rootPerson.Namespace = "
http://schemas.gama-system.com/
      president.xsd
";
   attrsPerson.XmlRoot = rootPerson;

   // create overrider
   XmlAttributeOverrides xOver = new XmlAttributeOverrides();
   xOver.Add(typeof(Person), attrsPerson);

   XmlSerializer xSer = new XmlSerializer(typeof(Person), xOver);
   return xSer;
}

Now serialize normally:

Stream ms = new MemoryStream();
XmlTextWriter tw = new XmlTextWriter(ms, null);
xSer.Serialize(tw, person);

This will work even if you only have a compiled version of your object graph, and you don't have any sources. System.Xml.Serialization.XmlAttributeOverrides class allows you to adorn any XML serializable class with your own XML syntax - element names, attribute names, namespaces and types.

Remember - you can override them all and still serialize your angle brackets.


Categories:  XML
Friday, August 29, 2008 7:38:07 PM (Central Europe Standard Time, UTC+01:00)  #    Comments

 

 Bleeding Edge 2008 

I'm happy to announce our organization work is coming to fruition.

Bleeding Edge 2008 is taking the stage for the autumn season.


Portorož, Slovenia, October 1st, 9:00

Official site, Registration, Sponsors

Go for the early bird registration (till September 12th). The time is now.

Potential sponsor? Here's the offering.

Categories:  Architecture | Conferences | MVP | Work
Thursday, July 17, 2008 2:50:06 PM (Central Europe Standard Time, UTC+01:00)  #    Comments

 

 Accreditus: Gama System eArchive 

One of our core products, Gama System eArchive was accredited last week.

This is the first accreditation of a domestic product and the first one covering long term electronic document storage in a SOA based system.

Every document stored inside the Gama System eArchive product is now legally legal. No questions asked.

Accreditation is done by a national body and represents the last step in a formal acknowledgement to holiness.

That means a lot to me, even more to our company.

The following blog entries were (in)directly inspired by the development of this product:

We've made a lot of effort to get this thing developed and accredited. The certificate is here.

This, this, this, this, this, this, this, this, this and those are direct approvals of our correct decisions.

Categories:  .NET 3.0 - General | .NET 3.0 - WCF | .NET 3.5 - WCF | Other | Personal | Work
Saturday, July 05, 2008 1:18:06 PM (Central Europe Standard Time, UTC+01:00)  #    Comments

 

 Sysinternals Live 

This is brilliant.

Sysinternals tools are now (actually were already when I left for vacation) available live via a web (http and WebDAV) based resource on http://live.sysinternals.com and \\live.sysinternals.com.

This means I can do the following:

[c:\]dir \\live.sysinternals.com\tools

 Directory of  \\live.sysinternals.com\tools\*

 2.06.2008   1:16         <DIR>    .
 2.06.2008   1:16         <DIR>    ..
 2.06.2008   1:16         <DIR>    WindowsInternals
30.05.2008  17:55             668  About_This_Site.txt
13.05.2008  19:00         225.320  accesschk.exe
 1.11.2006  15:06         174.968  AccessEnum.exe
 1.11.2006  23:05         121.712  accvio.EXE
12.07.2007   7:26          50.379  AdExplorer.chm
26.11.2007  14:21         422.952  ADExplorer.exe
 7.11.2007  11:13         401.616  ADInsight.chm
20.11.2007  14:25       1.049.640  ADInsight.exe
 1.11.2006  15:05         150.328  adrestore.exe
 1.11.2006  15:06         154.424  Autologon.exe
 8.05.2008  10:20          48.476  autoruns.chm
12.05.2008  17:31         622.632  autoruns.exe 1.11.2006  
...
 1.11.2006  15:06         207.672  Winobj.exe
30.12.1999  12:26           7.653  WINOBJ.HLP
27.05.2008  16:21         142.376  ZoomIt.exe
     24.185.901 bytes in 103 files and 3 dirs
109.442.727.936 bytes free

Or, I can fire up a Windows Explorer window (or press the start key, then type) and just type: \\live.sysinternals.com\tools.

Or:

[c:\]copy \\live.sysinternals.com\tools\Procmon.exe
        C:\Windows\System32
\\live.sysinternals.com\tools\Procmon.exe =>
        C:\Windows\System32\Procmon.exe
     1 file copied

Brilliant and useful.

Categories:  Other
Thursday, June 19, 2008 6:52:52 PM (Central Europe Standard Time, UTC+01:00)  #    Comments

 

 Demos from the NT Conference 2008 

As promised, here are the sources from my NTK 2008 sessions [1].

Talk: Document Style Service Interfaces

Read the following blog entry, I tried to describe the concept in detail. Also, this blog post discusses issues when using large document parameters with reliable transport  (WS-RM) channels.

Demo: Document Style Service Interfaces [Download]

This demo defines a service interface with the document parameter model, ie. Guid CreatePerson(XmlDocument person). It shows three different approaches to creation of the passed document:

  1. Raw XML creation
  2. XML Serialization of the (attribute annotated) object graph
  3. XML Serialization using the client object model

Also, versioned schemas for the Person document are shown, including the support for document validation and version independence.

Talk: Windows Server 2008 and Transactional NTFS

This blog entry describes the concept.

Demo 1: Logging using CLFS (Common Log File System) [Download]
Demo 2: NTFS Transactions using the File System, SQL, WCF [Download]
Demo 3: NTFS Transactions using the WCF, MTOM Transport [Download] [2]

[1] All sources are in VS 2008 solution file format.
[2] This transaction spans from the client, through the service boundary, to the server.

Categories:  .NET 3.5 - WCF | Transactions | XML
Thursday, May 15, 2008 4:24:19 PM (Central Europe Standard Time, UTC+01:00)  #    Comments

 

 Laws and Digital Signatures 

Suppose we have a document like this:

<?xml version="1.0"?>
<root xmlns="urn-foo-bar">
  <subroot>
    <value1>value1</value1>
    <value2>value2</value2>
  </subroot>
  <Signature xmlns="h
ttp://www.w3.org/2000/09/xmldsig#">
    <SignedInfo>
      <CanonicalizationMethod
        Algorithm="
http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
      <SignatureMethod
        Algorithm="
http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
      <Reference URI="">
        <Transforms>
          <Transform 
            Algorithm="
http://www.w3.org/2000/09/
              xmldsig#enveloped-signature
"/>
        </Transforms>
        <DigestMethod
          Algorithm="
http://www.w3.org/2000/09/xmldsig#sha1" />
        <DigestValue>1Xp...EOko=</DigestValue>
      </Reference>
    </SignedInfo>
    <SignatureValue>nls...cH0k=</SignatureValue>
    <KeyInfo>
      <KeyValue>
        <RSAKeyValue>
          <Modulus>9f3W...fxG0E=</Modulus>
          <Exponent>AQAB</Exponent>
        </RSAKeyValue>
      </KeyValue>
      <X509Data>
        <X509Certificate>MIIEi...ktYgN</X509Certificate>
      </X509Data>
    </KeyInfo>
  </Signature>
</root>

This document represents data and an enveloped digital signature over the complete XML document. The digital signature completeness is defined in the Reference element, which has URI attribute set to empty string (Reference Uri="").

Checking the Signature

The following should always be applied during signature validation:

  1. Validating the digital signature
  2. Validating the certificate(s) used to create the signature
  3. Validating the certificate(s) chain(s)

Note: In most situations this is the optimal validation sequence. Why? Signatures are broken far more frequently then certificates are revoked/expired. And certificates are revoked/expired far more frequently then their chains.

1. Validating the digital signature

First, get it out of there:

XmlNamespaceManager xmlns = new XmlNamespaceManager(xdkDocument.NameTable); [1]
xmlns.AddNamespace("ds", "
http://www.w3.org/2000/09/xmldsig#");
XmlNodeList nodeList = xdkDocument.SelectNodes("//ds:Signature", xmlns);
 
[1] xdkDocument should be an XmlDocument instance representing your document.

Second, construct a SignedXml instance:

foreach (XmlNode xmlNode in nodeList)
{
  // create signed xml object
  SignedXml signedXml = new SignedXml(xdkDocument); [2]

  // verify signature
  signedXml.LoadXml((XmlElement)xmlNode);
}

[2] Note that we are constructing the SignedXml instance from a complete document, not only the signature. Read this.

Third, validate:

bool booSigValid = signedXml.CheckSignature();

If booSigValid is true, proceed.

2. Validating the certificate(s) used to create the signature

First, get it out of there:

XmlNode xndCert = xmlNode.SelectSingleNode(".//ds:X509Certificate", xmlns); [3]

[3] There can be multiple X509Certificate elements qualified with http://www.w3.org/2000/09/xmldsig# namespace in there. Xml Digital Signature specification is allowing the serialization of a complete certificate chain of the certificate used to sign the document. Normally, the signing certificate should be the first to be serialized.

Second, get the X509Certificate2 instance:

byte[] bytCert = Convert.FromBase64String(xndCert.InnerText);
X509Certificate2 x509cert = new X509Certificate2(bytCert);

Third, validate:

bool booCertValid = x509cert.Verify();

If booCertValid is true, proceed.

3. Validating the certificate(s) chain(s)

Building and validating the chain:

X509Chain certChain = new X509Chain();
bool booChainValid = certChain.Build(x509cert);
int intChainLength = certChain.ChainElements.Count; [4]

If booChainValid is true, your signature is valid.

Some Rules and Some Laws

We have three booleans:

  • booSigValid - signature validity
  • booCertValid - certificate validity
  • booChainValid - certificate's chain validity

If booSigValid evaluates to false, there is no discussion. Someone changed the document.

What happens if one of the following two expressions evaluates to true:

1. ((booSigValid) && (!booCertValid) && (!booChainValid))
2. ((booSigValid) && (booCertValid) && (!booChainValid))

This normally means that either the certificate is not valid (CRLed or expired) [4], or one of the chain's certificate is not valid/expired.

[4] The premise is that one checked the signature according to 1, 2, 3 schema described above.

The Question

Is digital signature valid even if CA revoked the certificate after the signature has already been done? Is it valid even after the certificate expires? If signature is valid and certificate has been revoked, what is the legal validity of the signature?

In legal terms, the signature would be invalid on both upper assertions, 1 and 2.

This means, that once the generator of the signature is dead, or one of his predecessors is dead, all his children die too.

Timestamps to the Rescue

According to most country's digital signature laws the signature is valid only during the validity of the signing certificate and validity of the signing certificate's chain, both being checked for revocation and expiry date ... if you don't timestamp it.

If the source document has another signature from a trusted authority, and that authority is a timestamp authority, it would look like this:

<?xml version="1.0"?>
<root xmlns="urn-foo-bar">
  <subroot>
    <value1>value1</value1>
    <value2>value2</value2>
  </subroot>
  <Signature xmlns="
http://www.w3.org/2000/09/xmldsig#">
    ...
  </Signature>
  <dsig:Signature Id="TimeStampToken"
   
xmlns:dsig="http://www.w3.org/2000/09/xmldsig#">
    <dsig:SignedInfo>
      <dsig:CanonicalizationMethod
        Algorithm="
http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
      <dsig:SignatureMethod
        Algorithm="
http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
      <dsig:Reference
        URI="#TimeStampInfo-113D2EEB158BBB2D7CC000000000004DF65">
        <dsig:DigestMethod
          Algorithm="
http://www.w3.org/2000/09/xmldsig#sha1" />
          <dsig:DigestValue>y+xw...scKg=</dsig:DigestValue>
      </dsig:Reference>
      <dsig:Reference URI="#TimeStampAuthority">
        <dsig:DigestMethod
          Algorithm="
http://www.w3.org/2000/09/xmldsig#sha1" />
        <dsig:DigestValue>KhFIr...Sv4=</dsig:DigestValue>
      <dsig:/Reference>
    </dsig:SignedInfo>
    <dsig:SignatureValue>R4m...k3aQ==</dsig:SignatureValue>
    <dsig:KeyInfo Id="TimeStampAuthority">
      <dsig:X509Data>
        <dsig:X509Certificate>MII...Osmg==</dsig:X509Certificate>
      </dsig:X509Data>
    </dsig:KeyInfo>
    <dsig:Object
      Id="TimeStampInfo-113D2EEB158BBB2D7CC000000000004DF65">
      <ts:TimeStampInfo
         xmlns:ts="
http://www.provider.com/schemas
           
/timestamp-protocol-20020207
"
         xmlns:ds="
http://www.w3.org/2000/09/xmldsig#">
        <ts:Policy id="
http://provider.tsa.com/documents" />
          <ts:Digest>
            <ds:DigestMethod Algorithm="
http://www.w3.org/2000/
              09/xmldsig#sha1"
/>
            <ds:DigestValue>V7+bH...Kmsec=</ds:DigestValue>
          </ts:Digest>
          <ts:SerialNumber>938...045</ts:SerialNumber>
          <ts:CreationTime>2008-04-13T11:31:42.004Z</ts:CreationTime>
          <ts:Nonce>121...780</ts:Nonce>
      </ts:TimeStampInfo>
    </dsig:Object>
  </dsig:Signature>
</root>

The second signature would be performed by an out-of-band authority, normally a TSA authority. It would only sign a hash value (in this case SHA1 hash) which was constructed by hashing the original document and the included digital signature.

This (second) signature should be checked using the same 1, 2, 3 steps. For the purpose of this mind experiment, let's say it would generate a booTimestampValid boolean.

Now, let's reexamine the booleans:

  1. ((booSigValid) && (!booCertValid) && (!booChainValid) && (booTimestampValid))
  2. ((booSigValid) && (booCertValid) && (!booChainValid) && (booTimestampValid))

In this case, even though the signature's certificate (or its chain) is invalid, the signature would pass legal validity if the timesamp's signature is valid, together with its certificate and certificate chain. Note that the TSA signature is generated with a different set of keys than the original digital signature.

Actually booTimestampValid is defined as ((booSigValid) && (booCertValid) && (booChainValid)) for the timestamp signature/certificate/certificate chain [5].

[5] Legal validity is guaranteed only in cases where 1 or 2 are true.

Categories:  Other | XML
Wednesday, April 16, 2008 6:32:29 PM (Central Europe Standard Time, UTC+01:00)  #    Comments

 

 WCF: Reliable Messaging and Retry Timeouts 

There is a serious limitation present in the RTM version of WCF 3.0/3.5 regarding control of WS-RM retry messages during a reliable session saga.

Let me try to explain the concept.

We have a sender (communication initiator) and a receiver (service). When a reliable session is constructed between the two, every message needs to come to the other side. In a request-reply world, the sender would be a client during the request phase. Then roles would switch during the response phase.

The problem arises when one of the sides does not get the message acknowledgement in time. WCF reliable messaging implementation retries the sending process and hopes for the acknowledgement. All is well.

The problem is that there is no way for the sending application to specify how long the retry timeout should be. There is a way to specify channel opening and closing timeouts, acknowledgement interval and more, but nothing will define how long should the initiator wait for message acks.

Let's talk about how WCF acknowledges messages.

During a request-reply exchange every request message is acknowledged in a response message. WS-RM SOAP headers regarding sequence definition (request) and acknowledgements (response) look like this:

a1 <r:Sequence s:mustUnderstand="1" u:Id="_2">
a2    <r:Identifier>urn:uuid:6c9d...ca90</r:Identifier>
a3    <r:MessageNumber>1</r:MessageNumber>
a4 </r:Sequence>

b1 <r:SequenceAcknowledgement u:Id="_3">
b2    <r:Identifier>urn:uuid:6c99...ca290</r:Identifier>
b3    <r:AcknowledgementRange Lower="1" Upper="1"/>
b4    <netrm:BufferRemaining
b5       xmlns:netrm="
http://schemas.microsoft.com/ws/2006/05/rm">
b6    </netrm:BufferRemaining>
b7 </r:SequenceAcknowledgement>

Request phase defines a sequence and sends the first message (a3). In response, there is the appropriate acknowledgement present, which acks the first message (b3) with Lower and Upper attributes. Lines b4-b6 define a benign and super useful WCF implementation of flow control, which allows the sender to limit the rate of sent messages if service side becomes congested.

When the session is setup, WCF will have a really small time waiting window for acks. Therefore, if ack is not received during this period, the infrastructure will retry the message.

Duplex contracts work slightly differently. There, the acknowledgement interval can be set. This configuration option (config attribute is called acknowledgementInterval) is named inappropriately, since it controls the service and not the client side.

It does not define the time limit on received acknowledgements, but the necessary time to send the acknowledgments back. It allows grouping of sent acks, so that multiple incoming messages can be acked together. Also, the infrastructure will not necessarily honor the specified value.

Now consider the following scenario:

  1. The client is on a reliable network
  2. Network bandwidth is so thin that the sending message takes 20s to come through [1]
  3. Service instancing is set to Multiple
  4. The solution uses a request-reply semantics

[1] It does not matter whether the initiator is on a dial up, or the message is huge.

What happens?

Service initiator sets up a reliable session, then:

  1. First message is being sent
  2. Since the retry interval is really small [2], the message will not get to the other end and the acknowledgement will not bounce back in time
  3. First message is retried, now two messages are being transported
  4. No acks received yet
  5. First message is retried again
  6. Network bandwidth is even thinner
  7. First message is acknowledged
  8. First message retry is discarded on the service side
  9. Second message retry is discarded on the service side

[2] Under 3s.

The number of retry messages depends on the bandwidth and message size. It can happen that tens of messages will be sent before first acknowledgement will be received.

Adaptability algorithms

A good thing is that there are undocumented algorithms implemented for retry timeout. The implementation increases the reply timeout exponentially when the infrastructure detects that the network conditions demand more time (slow throughput) and allows reliable delivery (no losses). If loses are present the reply timeout decreases.

Retry timeout is actually calculated when establishing an RM session. It is based on the roundtrip time and is bigger if the roundtrip time is long.

So, when first messages in a session are exchanged, don't be too surprised to see a couple of message retries.

Categories:  .NET 3.0 - WCF | .NET 3.5 - WCF
Tuesday, April 08, 2008 11:33:13 PM (Central Europe Standard Time, UTC+01:00)  #    Comments

 

 Calculating Outsourcing Project Cost 

Wow, Stephen.

This is one of the best ideas I've heard of hedging against the dollar in terms if IT outsourcing cost. And I mean it.

I'm not in a position of valueing the description made, but I am willing to take the pill, no matter what.

What everybody needs is only to get to one million sterling project, taking half a year.

That's it, hedging done or not.

Categories:  Personal
Monday, February 18, 2008 11:01:39 PM (Central Europe Standard Time, UTC+01:00)  #    Comments

 

Copyright © 2003-2010 , Matevž Gačnik
Recent Posts
RD / MVP
Feeds
RSS: Atom:
Archives
Categories
Blogroll
Legal

The opinions expressed herein are my own personal opinions and do not represent my company's view in any way.

My views often change.

This blog is just a collection of bytes.

Copyright © 2003-2010
Matevž Gačnik

Send mail to the author(s) E-mail