Click here to Skip to main content
15,867,308 members
Please Sign up or sign in to vote.
3.00/5 (2 votes)
See more:
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:

C#
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:

C#
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
Updated 19-Feb-12 7:38am
v2
Comments
[no name] 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 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.
[no name] 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 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
[no name] 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.

1 solution

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.
 
Share this answer
 
Comments
Andreas Gieriet 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)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900