Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
See more: C#4.0 Signing
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 Wink | ;-) .
 
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
{
    /// <summary>
    /// <seealso href="http://msdn.microsoft.com/en-us/library/ms229745.aspx"/>
    /// <seealso href="http://msdn.microsoft.com/en-us/library/ms229950.aspx"/>
    /// </summary>
    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";
...
}
 
// BEGIN-SIGNATURE
// //48AFMAaQBnAG4AYQB0AHUAcgBlACAAeABtAGwAbgBzAD0AIgBoAHQAdABwADoALwAvAHcAdwB3
// AC4AdwAzAC4AbwByAGcALwAyADAAMAAwAC8AMAA5AC8AeABtAGwAZABzAGkAZwAjACIAPgA8AFMA
// aQBnAG4AZQBkAEkAbgBmAG8APgA8AEMAYQBuAG8AbgBpAGMAYQBsAGkAegBhAHQAaQBvAG4ATQBl
// AHQAaABvAGQAIABBAGwAZwBvAHIAaQB0AGgAbQA9ACIAaAB0AHQAcAA6AC8ALwB3AHcAdwAuAHcA
// MwAuAG8AcgBnAC8AVABSAC8AMgAwADAAMQAvAFIARQBDAC0AeABtAGwALQBjADEANABuAC0AMgAw
// ADAAMQAwADMAMQA1ACIAIAAvAD4APABTAGkAZwBuAGEAdAB1AHIAZQBNAGUAdABoAG8AZAAgAEEA
// bABnAG8AcgBpAHQAaABtAD0AIgBoAHQAdABwADoALwAvAHcAdwB3AC4AdwAzAC4AbwByAGcALwAy
// ADAAMAAwAC8AMAA5AC8AeABtAGwAZABzAGkAZwAjAHIAcwBhAC0AcwBoAGEAMQAiACAALwA+ADwA
// UgBlAGYAZQByAGUAbgBjAGUAIABVAFIASQA9ACIAIgA+ADwAVAByAGEAbgBzAGYAbwByAG0AcwA+
// ADwAVAByAGEAbgBzAGYAbwByAG0AIABBAGwAZwBvAHIAaQB0AGgAbQA9ACIAaAB0AHQAcAA6AC8A
// LwB3AHcAdwAuAHcAMwAuAG8AcgBnAC8AMgAwADAAMAAvADAAOQAvAHgAbQBsAGQAcwBpAGcAIwBl
// AG4AdgBlAGwAbwBwAGUAZAAtAHMAaQBnAG4AYQB0AHUAcgBlACIAIAAvAD4APAAvAFQAcgBhAG4A
// cwBmAG8AcgBtAHMAPgA8AEQAaQBnAGUAcwB0AE0AZQB0AGgAbwBkACAAQQBsAGcAbwByAGkAdABo
// AG0APQAiAGgAdAB0AHAAOgAvAC8AdwB3AHcALgB3ADMALgBvAHIAZwAvADIAMAAwADAALwAwADkA
// LwB4AG0AbABkAHMAaQBnACMAcwBoAGEAMQAiACAALwA+ADwARABpAGcAZQBzAHQAVgBhAGwAdQBl
// AD4AbwBiAGwAVwBDAGUAbABrAEwAdABPAFEARgBVAGkATwBzAEkATQBwAEEARABhACsAUwA1AGcA
// PQA8AC8ARABpAGcAZQBzAHQAVgBhAGwAdQBlAD4APAAvAFIAZQBmAGUAcgBlAG4AYwBlAD4APAAv
// AFMAaQBnAG4AZQBkAEkAbgBmAG8APgA8AFMAaQBnAG4AYQB0AHUAcgBlAFYAYQBsAHUAZQA+AFoA
// SgBhADIAVwBWADYAYgB5AE0AbQAxAGwAYgBwAE0AbgBwAHYAYwBGAG0ATgB1AFcAVgBCAHUANABp
// AHQAeQBHAGgAcgBJAFAAdgBqADMAaQBWAG0AWgArADUAbwA4AGwAYwBIAEIAVQA0AE0AbgB4AGcA
// ZwBXAGUAagBUAEsATwBRAG0AdQBoAGgAUwBwAHgATABJADAANABuAE0AKwBoAEcAeABmAFoARABN
// AGMANAAzAGoARQBDAEkAOQBOAGEAQQAxAFAAegBqACsAMABUADMAaQBtAGYAZgBUAEMATwBVAEYA
// VwArAFEAWQB0AHkAegBuAFQASQBBAE4ANgBoAEsAQwBmADEAYwBQAHQAbQBiAGEAbQBiAEEAbwBt
// AGoAQwBaAGoAMgAvAE8ASgBCAC8AYQA1AGkARwAyAE0ATwBsADUAZAAzAFUASwBwAHIAZQBFAD0A
// PAAvAFMAaQBnAG4AYQB0AHUAcgBlAFYAYQBsAHUAZQA+ADwALwBTAGkAZwBuAGEAdAB1AHIAZQA+
// AA==
// 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
Posted 19-Feb-12 6:08am
Edited 19-Feb-12 8:38am
v2
Comments
Mark Nischalke at 19-Feb-12 11:14am
   
Why do you need to sign a text file? What is your overall goal for this? There may be other ways to accomplish your goal if we knew what it was.
Andreas Gieriet at 19-Feb-12 12:15pm
   
Let's assume the following requirements:
1. There is a set of plain text files.
2. Each file shall be signed to *enable* checking the integrity of the content.
3. Everybody shall be enabled to read the text file *as-is* in any text editor of his choice.
4. Those who want to verify the integrity of the text files can do so by running a provided verification tool.
5. The only data and environment provieded is the signed text files plus the verification tool.
Mark Nischalke at 19-Feb-12 13:59pm
   
As you found out what you want is a Digital Signature which is different from signing a file with a string name, which is what the sn utility does.
 
Not all text readers will support digital signatures nor will they open a file in read-only mode, unless the file itself is read-only.
 
If you want to provide a read-only secured version of the file I would suggest creating a PDF.
Andreas Gieriet at 19-Feb-12 14:33pm
   
Hello Mark,
 
All you mention is not a requirement in this case.
Access rights can be managed on a file system base (E.g. all files are readonly for the common user).
 
Any text editor can load the text files as shown in the examples. They are plain text. I'm not asking for any support of the text reader other than display the text as-is.
 
What I'm asking is, if there is a simpler way in *.NET* to add a text signature to a text file similar to the one shown above.
 
Thank you for your hint about the PDF.
 
Cheers
 
Andi
Mark Nischalke at 19-Feb-12 15:26pm
   
"Any text editor can load the text files as shown in the examples". Yes they can, but do you really want all users to see the encrypted signature? You are not protecting anything in that case.
 
Digital Signatures are not meant to be visible to the end users in the reader application.
 
Your comments make no sense.
Andreas Gieriet at 19-Feb-12 15:48pm
   
That's your perception of the case - if this makes sense is relative ;-)
And it is not a requirement in this case to hide anything - you may assume educated operators in that use case...
 
So, again, is there a way to do it in a .NET way rather than the hand-crafted one I did - no matter if my use case makes sense to you?
 
Thanks
 
Andi
Mark Nischalke at 19-Feb-12 20:38pm
   
Make no sense, as in your statements are confusing and unclear.
 
Andreas Gieriet at 20-Feb-12 3:09am
   
So, which of the above mentioned requirements in my first reply is confusing or unclear. If I knew, I could fix.
BTW: I find it a bit annoying to have to explain "why" if I ask for a technical solution. If I would ask you how to get by car from A to B, it would neither matter "why" I want to get from A to B. So, why does it matter here?
 
Take it as a technical challenge: assuming you had to sign an unicode text string, and the signature should be a unicode text again, how would you do it in C# 4.0? The signature does not need to be human readable though (i.e. it may be encoded). E.g.:
 
public static string CalculateSignature(string plainText)
{
 
var signature = GetSignature(plainText);
 
return signature.ToString();
 
}
 

 
How to implement GetSignature(...) in decent way?
 
Is this more clear?
 
Thanks
krumia at 20-Feb-12 5:44am
   
If you wan't to just know if the file has been (maliciously or otherwise) changed or not, just produce the hash of the file, and store it somewhere public. MD5 or SHA1 hashing should be adequate. And they are easy to get too.
Andreas Gieriet at 20-Feb-12 6:45am
   
Hello krumia,
 
thanks for the hint. I'll go that path and integrate the hash into the document as described in Solution #1.
Andreas Gieriet at 20-Feb-12 3:18am
   
For the individual voting this question down: please tell why so I can improve the question and learn for the future.

1 solution

Rate this: bad
good
Please Sign up or sign in to vote.

Solution 1

So you want to make sure that nobody changed the contents of the text file, that's the point isn't it?
A rough outline of a possible solution:
Read the text of the file, apply a hash function, encrypt the hash using your private key of a non-symmetric encryption function. Add a new line containing the encrypted hash value (encoded in BASE64 or something textual).
When you want to check the contents, read the file excluding that last line, use the same hash function and compare the result with the de-cryption of the stored hash value.
  Permalink  
Comments
Andreas Gieriet at 20-Feb-12 6:48am
   
Hello Bernhard,
 
thanks for sharing your idea. I'll investigate in going that path.
 
Cheers
 
Andi

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS
0 OriginalGriff 7,853
1 Sergey Alexandrovich Kryukov 7,107
2 DamithSL 5,604
3 Manas Bhardwaj 4,986
4 Maciej Los 4,790


Advertise | Privacy | Mobile
Web03 | 2.8.1411023.1 | Last Updated 20 Feb 2012
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100