(c) 2005 Marc Clifton All Rights Reserved.

Introduction
This article, above all else, demonstrates how you can piece together a
useful application from the amazing amount of code that is available at The Code
Project and on the Internet in general. Using completely public domain code, I
put together a little XML Control Panel. The control panel manages XML file
sets, allowing you to perform digital signing, compression, and encryption on
the file set.
The project consists of two significant components--the UI front end
(implemented in MyXaml) and the API that you can include separately in your
application for digital signing/verification, compression/decompression, and
encryption/decryption services.
Note that you may also use this application for encryption and compression of
non-XML files. Only the digital signing is XML specific.
Features
This control panel is a GUI wrapper around the following functionality:
- digital signing
- encryption
- compression
allowing you to selectively choose one or more of these options for your XML
files. Non-XML files may take advantage of the encryption and compression
functions.
- The control panel has command line capability so it can be used as part of
a post-build process.
- A separate API is used for the encoding and decoding algorithms, allowing
you to include the API in your own application separate from the UI.
Digital Signing
The digital signing and signature verification code is built entirely on the
work presented by Heath Stewart. The
application will sign each XML file with a randomly generated key. The key is
written out to "keyfile.snk". This key is registered into a key container
on your machine. The public key is extracted and placed in the file
"publicKey.xml". Please read Heath's article regarding options on how to
embed the public key into your application.
If all you're doing is signing the XML files, each of the input files will be
written out with the extension changed to ".sgn", indicating that it has
been signed.
This signing portion utilizes the "sn.exe" utility and uses the ShellAPI code
from "arikp".
Encryption
Encryption/Decryption is accomplished using the .NET cryptography providers
as described in the MSDN Library article. Please note that the TripleDES algorithm
accepts 16 or 24 byte keys only but requires an 8 byte initial vector (IV),
while the Rijndael algorithm accepts a 16 or 24 byte key but requires a 16 byte
IV.
If compression isn't used, each encrypted XML file (whether signed or not) is
written out with the same base filename, having the extension changed to
".enc".
Encrypted files are always written out as binary rather than using base64
encoding, since this would defeat (or at least reduce) the advantage of
compression.
Compression
Compression/decompression is provided by the SharpZipLib library. Only ZIP and TAR compression is
supported, as these are the only two that allow multiple files to be combined
into a single file.
If encryption is not used, the signed files are all placed into a single
compressed file having the base filename of the configuration name and with the
extension ".zip" or ".tar", depending on the selected
compression.
If encryption is used, then the extension is ".enc".
Compression is always done before encryption because it is assumed that the
compression algorithm will be much more efficient working with the original XML
files. This seems reasonable, given how tokenized an XML file is.
The User Interface
The user interface is implemented with MyXaml and is a good illustration of using
styles, flow panels, runtime property containers and data binding. The original
article on flow panels was written by Matt Dockins and I've made some
significant changes to it (see my comments in his article), including
implementing a grid panel.
Usage
To create a new configuration that will manage your XML files:
- load XML files into the configuration tree view
- select the desired operations to perform on the collection of XML files
- save this configuration
- encode it!
To use an existing configuration, simply open the configuration.
Internally, the application preserves the original path of the XML files in
the configuration, however, the encoded file(s) are written out to the current
working directory.
Command Line Mode
You can pass the configuration file (for example, "test.xmlcp") to the
application, and it generates the encoded file(s) in the working directory. If
"Always Create A New Key" is unchecked, make sure that the public key
file is also in the working directory.
Key Sizes
(I think I have this right):
| Algorithm |
Key Size |
IV Size |
| DES |
8 |
8 |
| RC2 |
>4 |
8 |
| Rijndael |
16 or 24 |
16 |
| TripleDES |
16 or 24 |
8 |
The Test Application
A simple test application is provided that verifies the basic functionality
of the application and illustrates using the XCPAPI for extracting two XML files
from an encrypted and ZIP compressed file, then verifying its signature.
Extracting the same files from a non-encrypted TAR compressed file is also
demonstrated.
using System;
using System.IO;
using System.Text;
using XCPAPI;
namespace Test
{
class TestApp
{
[STAThread]
static void Main(string[] args)
{
// ***** ENCRYPTED, ZIP COMPRESSED, SIGNED *****
// Get the encoded file.
FileStream fs=new FileStream("test.enc", FileMode.Open, FileAccess.Read);
BinaryReader r=new BinaryReader(fs);
byte[] data=r.ReadBytes((int)fs.Length);
r.Close();
fs.Close();
// Decrypt it.
Decryptor dec=new Decryptor(EncryptionAlgorithm.Des);
dec.IV=Encoding.ASCII.GetBytes("init vec");
data=dec.Decrypt(data, Encoding.ASCII.GetBytes("password"));
// Decompress it.
Decompression decomp=new Decompression(CompressionAlgorithm.Zip, data);
string fn1;
byte[] data1=decomp.GetFile(out fn1, data);
string text1=Encoding.ASCII.GetString(data1);
string fn2;
// Decompress second file.
byte[] data2=decomp.GetFile(out fn2, data);
string text2=Encoding.ASCII.GetString(data2);
// Verify signature of both files.
string xmlKey="[...omitted...]";
Signer signer=new Signer();
signer.XmlKey=xmlKey;
bool ret=signer.VerifySignature(text1);
Console.WriteLine("Signature verification for "+fn1+": "+ret.ToString());
ret=signer.VerifySignature(text2);
Console.WriteLine("Signature verification for "+fn2+": "+ret.ToString());
// Write the first file.
StreamWriter sw=new StreamWriter(fn1);
sw.Write(text1);
sw.Flush();
sw.Close();
// write the second file.
sw=new StreamWriter(fn2);
sw.Write(text2);
sw.Flush();
sw.Close();
// ***** TAR COMPRESSED, SIGNED *****
// Get the encoded file.
fs=new FileStream("test.tar", FileMode.Open, FileAccess.Read);
r=new BinaryReader(fs);
data=r.ReadBytes((int)fs.Length);
r.Close();
fs.Close();
// Decompress it.
decomp=new Decompression(CompressionAlgorithm.TAR, data);
data1=decomp.GetFile(out fn1, data);
text1=Encoding.ASCII.GetString(data1);
// Decompress second file.
data2=decomp.GetFile(out fn2, data);
text2=Encoding.ASCII.GetString(data2);
// Verify signature of both files.
ret=signer.VerifySignature(text1);
Console.WriteLine("Signature verification for "+fn1+": "+ret.ToString());
ret=signer.VerifySignature(text2);
Console.WriteLine("Signature verification for "+fn2+": "+ret.ToString());
}
}
}
Things Of Note
The user interface is implemented with MyXaml as well as a runtime container
that manages the property settings. If you inspect the xcp.myxaml file,
you'll see some interesting things:
DockPadding defined for the application form.
- A simple style applied to buttons, groupboxes, radiobuttons, and
checkboxes.
- A declarative approach to initializing
OpenFileDialog and
SaveFileDialog.
- Resource binding of icons to menu item bitmaps.
- Flow panels used in various configurations which avoids specifying
absolute coordinates for controls.
- Data binding--note how databinding is used not just for the container
properties but also the
Enabled property of some controls are
bound to the CheckBox Checked property. This
mechanism provides a code free way of manipulating the visual state of the
controls that correspond to the check state.
Limits
- The compression algorithm expects that filenames will be unique and does
not preserve any directory hierarchy.
- Only alphanumeric keys are supported and must be specified in the edit
box.
- Both key and initial vector (IV) must be provided. Random generation is
not supported.
Licensing
This UI application and the XCPAPI are licensed under the BSD License. MyXaml
is licensed under the GNU GPL.
References