I wanted to sign a plain text file.
The attempts to use the
sn
tool or the
SignTool
failed: they do support to sign assemblies or any exe/dll/... files, but no text files. If I try to nonetheless use those tools, they do complain that the file format is unknown.
I even tried to simply rename the
test.txt
file to
test.dll
but no success neither ;-).
I assumed this was a no-brainer, but I could not find any ready-to-use solution.
Maybe one of you could shade some light on this.
What I came up with is to go over XML signing which is directly supported by .NET Framework.
The followin pseudo code gives an idea on my approach:
public static string SignText(string unsignedText)
{
var xmlDoc = WrapUnsignedTextIntoXml(unsignedText);
var signedXmlDoc = SignXmlDoc(xmlDoc);
var signatureXml = GetXmlTextFromXml(signedXmlDoc);
var base64 = TextToBase64(signatureXml);
var textSignature = WrapBase64IntoSignatureBlock(base64);
var signedText = unsignedText + textSignature;
return signedText;
}
public static bool VerifySignedText(string signedText)
{
var {unsignedText, base64} = SplitTextAndSignature(signedText);
var signatureXml = Base64ToText(base64);
var signatureXmlNode = CreateXmlNodeFromSignature(signatureXml);
var xmlDoc = WrapUnsignedTextIntoXml(unsignedText);
var signedXmlDoc = CreateSignedXmlDoc(xmlDoc, signatureXmlNode);
return VerifyXml(signedXmlDoc);
}
This approach bases on
How to: Sign XML Documents with Digital Signatures[
^] and
How to: Verify the Digital Signatures of XML Documents[
^].
The resulting signed text file would be something like:
This is a sample text with a signature that
verifies tha the integrity of the plain text is
not corrupted.
All whitespaces are relevant - no single character of the text must have changed.
2012-02-19/A.Gieriet
# BEGIN-SIGNATURE
# //48AFMAaQBnAG4AYQB0AHUAcgBlACAAeABtAGwAbgBzAD0AIgBoAHQAdABwADoALwAvAHcAdwB3
# AC4AdwAzAC4AbwByAGcALwAyADAAMAAwAC8AMAA5AC8AeABtAGwAZABzAGkAZwAjACIAPgA8AFMA
# aQBnAG4AZQBkAEkAbgBmAG8APgA8AEMAYQBuAG8AbgBpAGMAYQBsAGkAegBhAHQAaQBvAG4ATQBl
# AHQAaABvAGQAIABBAGwAZwBvAHIAaQB0AGgAbQA9ACIAaAB0AHQAcAA6AC8ALwB3AHcAdwAuAHcA
# MwAuAG8AcgBnAC8AVABSAC8AMgAwADAAMQAvAFIARQBDAC0AeABtAGwALQBjADEANABuAC0AMgAw
# ADAAMQAwADMAMQA1ACIAIAAvAD4APABTAGkAZwBuAGEAdAB1AHIAZQBNAGUAdABoAG8AZAAgAEEA
# bABnAG8AcgBpAHQAaABtAD0AIgBoAHQAdABwADoALwAvAHcAdwB3AC4AdwAzAC4AbwByAGcALwAy
# ADAAMAAwAC8AMAA5AC8AeABtAGwAZABzAGkAZwAjAHIAcwBhAC0AcwBoAGEAMQAiACAALwA+ADwA
# UgBlAGYAZQByAGUAbgBjAGUAIABVAFIASQA9ACIAIgA+ADwAVAByAGEAbgBzAGYAbwByAG0AcwA+
# ADwAVAByAGEAbgBzAGYAbwByAG0AIABBAGwAZwBvAHIAaQB0AGgAbQA9ACIAaAB0AHQAcAA6AC8A
# LwB3AHcAdwAuAHcAMwAuAG8AcgBnAC8AMgAwADAAMAAvADAAOQAvAHgAbQBsAGQAcwBpAGcAIwBl
# AG4AdgBlAGwAbwBwAGUAZAAtAHMAaQBnAG4AYQB0AHUAcgBlACIAIAAvAD4APAAvAFQAcgBhAG4A
# cwBmAG8AcgBtAHMAPgA8AEQAaQBnAGUAcwB0AE0AZQB0AGgAbwBkACAAQQBsAGcAbwByAGkAdABo
# AG0APQAiAGgAdAB0AHAAOgAvAC8AdwB3AHcALgB3ADMALgBvAHIAZwAvADIAMAAwADAALwAwADkA
# LwB4AG0AbABkAHMAaQBnACMAcwBoAGEAMQAiACAALwA+ADwARABpAGcAZQBzAHQAVgBhAGwAdQBl
# AD4ATABaAGoAbABSAHIAVQBVAHEAVQBrAGEARgBzAHIAdwBUAGYAeABNAGYAZABoAGYAMQBHAEEA
# PQA8AC8ARABpAGcAZQBzAHQAVgBhAGwAdQBlAD4APAAvAFIAZQBmAGUAcgBlAG4AYwBlAD4APAAv
# AFMAaQBnAG4AZQBkAEkAbgBmAG8APgA8AFMAaQBnAG4AYQB0AHUAcgBlAFYAYQBsAHUAZQA+AEkA
# KwB5AHAAaQBHADAAdgBhAGoAbABMADMATABjAHUAZgBFAHMANQBqAFkAUABRAHAARgA2AHMANQAv
# AEwALwBGAHkARABhAFMAaAA0ADkATAAxAEQATgBLAFQAWAB6AEQASABpAG4AdgBLAFcAKwBnAG0A
# MwA1AGkAcgBUAHYASAAvAEsASgBHAGYASwBZADUAOQBhAGoAZQBrAGEAUwBDAEwANQBUAGoATAAw
# ADIASwBCAGcASABGAEwAQgBmADEAaQBzAG0AaQA3AFEAdwBYAEYARgByAHMAQgB4ADIATABhADQA
# eQBGAEEAZwBPAHEAUwBuAGkAVQAwAEsAQgBaAE8AKwBWAGwAUgB3AEkAQgBJADcAWgBOADEAVwBR
# AEQASgBKADkASABTAEUAdwA3AEEATgB6AHEAagBsAE8AagBqAEMAcgBSAEQAdABVAGoAawA4AD0A
# PAAvAFMAaQBnAG4AYQB0AHUAcgBlAFYAYQBsAHUAZQA+ADwALwBTAGkAZwBuAGEAdAB1AHIAZQA+
# AA==
# END-SIGNATURE
Or similary for a C# file:
using System;
using System.IO;
using System.Security.Cryptography;
using System.Security.Cryptography.Xml;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;
namespace SigningText
{
public class SignText
{
private static readonly AsymmetricAlgorithm RSAKEY =
new RSACryptoServiceProvider(new CspParameters() { KeyContainerName = "XML_DSIG_RSA_KEY" });
private static readonly string NL = Environment.NewLine;
private static readonly string BS = "BEGIN-SIGNATURE";
private static readonly string ES = "END-SIGNATURE";
...
}
I still assume that there is some simpler and more straight forward way to solve this under the requirement that I want to append the signature to the plain text file as shown in the examples above.
Any hint is very much appreciated.
Thanks
Andi