Integrity and Authenticity - c#

Sorry to keep asking so many questions, but you guys always seem to be so nice and helpful...
I need to do some application that imports data from a file. For instance, user selects one file and the application imports some data to database.
But I've been thinking, and this kind of app leads to a problem of integrity and authenticity of files. If a user changes the file the application is not allowed to use that information. And if one file is not from a source well known, the application can't use that file.
How do I do this kind of thing?
P.S.: I'm using C#.NET

Authentication and integrity are provided by digital signatures.
Follow driis' advice if you control the file format.
Alternately, if the file is XML, use an XML Signature.
Using C#/.NET:
Sign XML Documents
Verify the Digital Signatures of XML Documents

If you can control the source file format, you can embed a digital signature. If you base the signature on a hash of the file contents, then you can be sure that the file comes from a trusted source, and that is has not been tampered with.

It depends on how strong you want this protection.
For example, you can have an xml file (for human readability) which has a hash node somewhere which contains the hash of the original file (+salt). This can be updated by the program, but the user can have a harder time figuring out what that key means. When the program opens the file, it calculates the hash and checks if it's the same as the one written in the file.
You can even take one step further and use digital signatures, but that's way more complicated.

Related

Signing binary files (not code signing)

Is there a way to sign binary files? I'd like to sign my zip files to protect them from modification (to prevent installation of malicious software).
Signing XML is rather easy, but I'm not so sure about binary files. Is this even possible? All I can find about that matter is code signing (which is not what I want). There is no use in buying expensive certificates, it's just to ensure that update files aren't modified when they get installed.
I figure I have to work like that: Hashing the file, generating a key pair (probably using the hash for it) and then append the signature bytes to the file.
Vice versa, reading the signature bytes and verifying the hash against the public key of the signature.
But I don't think it's that simple. Do I have to consider certain things (like with XML that you need to canonicalize)?
I do not necessarily need code, but some detailed explanation about the process (any resources that explain that thoroughly would be okay as well).
When working with arbitrary binary files you can't modify their content so if you want to sign them you need to use a separate external file that contains the hash of the file you want to sign and also signs itself to prevent itself from being modified.
You then read this separate file, verify its personal signature, then verify the hash of each file it lists in its contents. You can use Catalog Files built in to windows (using MakeCat and SignTool to create them) or create your own following the same process.
Because you are only distributing updates, and if you are allowed to assume that the program loading the updates has not been modified, you don't need to "buy" a certificate. You could create your own "private CA", distribute that CA's certificate inside the updater, then use that Private CA's certificate to validate the catalog file.
I'm not sure what you mean as "binary file", but if you talk about PE format (Windows binary executable) you can generate own signature (encrypted hash) and put it inside of PE file in the same place as Windows authenticode certificate goes. Here is an open source tool to make such modifications:
http://blog.didierstevens.com/programs/disitool/

Can i use File.Encrypt for this purpose?

I have an application, its Name and Logo can changed directly from a TXT and a PNG file in the same directory.
I want to give the user the ability to change the Logo and Text File from another application that does the following :
Takes the Logo.png , Name.txt file paths and the directory of my Software then encrypt these two files and put them in the Directory of the Software
In the other hand. The software will Decrypt these two files and write them to Hard Disk to temp directory then use them to display the name and the logo.
I searched for the simplest and easiest way to encrypt a file and i found :
From the MSDN :
File.Encrypt():
Encrypts a file so that only the account used to encrypt the file can decrypt it.
Could someone please tell me what does it mean "only the account used to encrypt a file can decrypt it"
What about encrypting the application from Computer1 by Application1 then the file will be decrypted by Computer2 in Application2
Will the encryption work correctly ?
Edit:The purpose why I need to encrypt these two files is to avoid users from directly change the Logo and the Name of Application from the directory
This will encrypt the file, but not as you expect - and almost certainly not such that it can be decrypted by another application/user on a different computer.
The Encrypt method basically just toggles a feature of the underlying NTFS driver to encrypt the specified file on the file system itself. The nice feature is that it (typically) provides seamless file encryption for the user, but it isn't really portable encryption. It is the same as opening the file properties, clicking the advanced button and selecting the "Encrypt" checkbox.
More information on the encrypting feature of NTFS can be be found here: http://technet.microsoft.com/en-us/library/bb457116.aspx
No. You should use a proper encryption method such as those in System.Security.Cryptography namespace. There is a stream implementation for this, too, called CryptoStream, which you may wrap a FileStream with for encrypting files with.
This is related to Windows' EFS.
You can try it from Windows Explorer by right-clicking on the file, Properties, Advanced, Encrypt contents. The file data is automatically decrypted/encrypted on the fly as your app accesses it. But if another user logs in the machine and copies the file it will appear encrypted since the encryption is based on a user token.
This is may or may not be what you want and that depends on your intended use of that feature. If you don't want the user to be able to modify the data outside your app it won't be enough.

Signing contents of a file archive

Let's say I have a custom file archive format similar to Zip or Rar, for example. A small game I'm working on would then during runtime read the archived files, which may be textures, sounds, XML files or whatever else.
Now I'd like a way to verify the authenticity of the archive (or even of individual files inside the archive), so that the game can distinguish between "official" files released by me and modified files or archives released by some modder. The game should still be able to read the modded files just fine, but it will display some kind of warning or notice about the presence of modified data.
How could I go about this? What encryption or signing facilities in C# could be useful? Is that even feasible or should I just don't care?
Look into RSACryptoServiceProvider:
http://msdn.microsoft.com/en-us/library/system.security.cryptography.rsacryptoserviceprovider.aspx
You can use it to generate an RSA keypair and sign a hash of the file with your private key. Then you can use your public key (stored in your executable) to verify the signature.
Fortunately, the System.IO.Packaging namespace includes support for digital signatures, which are part of the Open Packaging Conventions (OPC). See:
http://msdn.microsoft.com/en-us/library/system.io.packaging.package.aspx?
http://msdn.microsoft.com/en-us/library/aa905326.aspx
An OPC file is a ZIP file whose format conforms to the OPC specification. An OPC file can contain a digital signature.

Securely deleting a file in C#.NET

In a project I am doing I want to give users the option of 'securely' deleting a file - as in, overwriting it with random bits or 0's. Is there an easy-ish way of doing this in C#.NET? And how effective would it be?
You could invoke sysinternals SDelete to do this for you. This uses the defragmentation API to handle all those tricky edge cases.
Using the defragmentation API, SDelete
can determine precisely which clusters
on a disk are occupied by data
belonging to compressed, sparse and
encrypted files.
If you want to repackage that logic in a more convenient form, the API is described here.
You can't securely delete a file on a journaling filesystem. The only non-journaling system still in heavy use is fat32. On any other system, the only way to securely delete is to shred the entire hard drive.
EDIT
The reason secure delete doesn't work, is that that data used to overwrite a file might not be stored in the same location as the data it is overwriting.
It seems Microsoft does provide a secure delete tool, but it does not appear to be something that you can use as a drop in replacement.
The only good way to prevent deleted file recover, short of shredding the disk, would be to encrypt the file before it is written to disk.
It wouldn't be secure at all. Instead you may wish to look at alternative solutions like encryption.
One solution would be to encrypt the contents of the data file. A new key would be used each time the file is updated. When you want to "securely delete" the data simply "lose" the encryption key and delete the file. The file will still be on the disk physically but without the encryption key recovery would be impossible.
Here is more detailed explanation as to why "secure" overwrites of files is poor security:
Without a low level tool (outside of .net runtime) you have no access to the physical disk location. Take a filestream on NTFS, when you "open a file for write access" you have no guarantee that the "updated" copy (in this case random 101010 version) will be stored in the same place (thus overwriting the original file). In fact most of the time this is what happens:
1) File x.dat is stored starting at cluster 8493489
2) You open file x.dat for write access. What is returned to you by the OS is merely a pointer to the file stream abstracted by not just the OS but the underlying file system and device drivers (hardware RAID for example) and sometimes the physical disk itself (SSD). You update the contents of the file with random 1 & 0s and close the filestream.
3) The OS likely may (and likely will) write the new file to another cluster (say cluster 4384939). It will then merely update the MFT indicating file x is now stored at 4384939.
To the end user it looks like only one copy of the file exists and it now has random data in it however the original data still exists on the disk.
Instead you should consider encrypting the contents of the file with a different key each time file is saved. When the user wants the file "deleted" delete the key and file. The physical file may remain but without encryption key recovery would be impossible.
Gutmann erasing implementation
I'd first try simply to open the file and overwrite its contents as I would normally do it. Pretty trivial in C#, I won't even bother to write it. However I don't know how secure that would be. For one thing, I'm quite certain it would not work on flash drives and SSD's that use sophisticated algorithms to provide wear leveling. I don't know what would work there, perhaps it would need to be done on driver level, perhaps it would be impossible at all. On normal drives I just don't know what Windows would do. Perhaps it would retain old data as well.

Is there an easy way to determine the type of a file without knowing the file's extension?

I have a table with a binary column which stores files of a number of different possible filetypes (PDF, BMP, JPEG, WAV, MP3, DOC, MPEG, AVI etc.), but no columns that store either the name or the type of the original file. Is there any easy way for me to process these rows and determine the type of each file stored in the binary column? Preferably it would be a utility that only reads the file headers, so that I don't have to fully extract each file to determine its type.
Clarification: I know that the approach here involves reading just the beginning of each file. I'm looking for a good resource (aka links) that can do this for me without too much fuss. Thanks.
Also, just C#/.NET on Windows, please. I'm not using Linux and can't use Cygwin (doesn't work on Windows CE, among other reasons).
you can use these tools to find the file format.
File Analyser
http://www.softpedia.com/get/Programming/Other-Programming-Files/File-Analyzer.shtml
What Format
http://www.jozy.nl/whatfmt.html
PE file format analyser
http://peid.has.it/
This website may be helpful for you.
http://mark0.net/onlinetrid.aspx
Note:
i have included the download links to make sure that you are getting the right tool name and information.
please verify the source before you download them.
i have used a tool in the past i think it is File Analyser, which will tell you the closest match.
happy tooling.
This is not a complete answer, but a place to start would be a "magic numbers" library. This examines the first few bytes of a file to determine a "magic number", which is compared against a known list of them. This is (at least part) of how the file command on Linux systems works.
Someone else asked a similar question and posted the code used to do exactly this. You should be able to take what is posted here, and slightly modify it so that it pulls from your database.
https://stackoverflow.com/questions/58510
In addition to that, it looks like someone has written a library based off of magic numbers to do this, however, it looks like the site requires registration, and some form of alternate access in order to download this lirbary. The documentation is avaliable for free without registration, that may be helpful.
http://software.topcoder.com/catalog/c_component.jsp?comp=13249160&ver=2
The easiest way I know is to use file command that it is also available in Windows with Cygwin .
A lot of filetypes have well defined headers that begin the file. You could check the first few bytes to check to see how the file begins.
Easiest way to do this would be through access to a *nix (or cygwin) system that has the 'file' command:
$ file visitors.*
visitors.html: HTML document text
visitors.png: PNG image data, 5360 x 2819, 8-bit colormap, non-interlaced
You could write a C# application that piped the first X bytes of each binary column to the file command (using - as the file name)
You need to use some p/invoke interop code to call the SHGetFileInfo method from the Win32 API. This article may also help.

Categories