CryptoQrUtilities

This NuGet provides the following facilities:
  1. QrUtilitiesWrapper - A wrapper for QR encoding and decoding tools.
  2. CryptedEnvelope - A container and tools for encrypting and decrypting data.
  3. QrMessage - A message container for data and metadata, (de)serializable to a QR.
  4. Touchless.Vision - A library for controlling a web camera. See also here.

Encoding and decoding QRs

QrUtilitiesWrapper is a simple wrapper around the Zxing library, for the major use of converting text to QR and back again.

First we create a QR utility box:
var qrUtils = new QrUtilitiesWrapper();

For converting a QR bitmap to a text we use (we of-course check that the given bitmap indeed contains a QR):
string qrText;
var qrDecode = qrUtils.GetQrDecoding(snapshot);

if (qrDecode != null && qrDecode.Text != null)
{
    qrText = qrDecode.Text;
}

and to convert text to a QR bitmap:
string myText = "Hello World";
var qrBitmap = qrUtils.GetQrEncoding(myText);

Encryption and decryption of data

CryptedEnvelope is an immutable type to use as a container for encrypted text. It contains the tools for encrypting a given text, and decrypting it as well as tools for managing the encryption algorithms used.
Although not used in the demo, this type is serializable (DataContract) and it serializes the byte buffer containing the encrypted text.

Encrypting

It is important to understand that the preparing of the encrypted text envelope is carried in three phases:
  1. Encrypting the plain text with AES256 symmetric algorithm.
  2. Encrypting the AES key used with RSA asymmetric algorithm, as the private key is maintained in a specialized .NET container in the encrypting device on machine-level (opposing to user-level).
  3. The AES encrypted text and the RSA encrypted key are bundled together to form the byte buffer contained in the created CryptedEnvelope object.
Please also see a useful description of the paradigm used above here.

First we'd like to create an encrypted envelope with our text to encrypt.
var envelope = new CryptedEnvelope(message, rsaKeyContainerName);

rsaKeyContainerName is the name of the .NET container for the RSA private key. This container is persistent, meaning it stays there like a file until you delete it, and so the private key is persistent as well and can decrypt the message at any given moment.
There is, of course, a much secure way to store and maintain asymmetric encryption private keys - which is using security cards or Microsoft's TPM. This is not yet implemented.

To delete the .NET private key container, we use
CryptedEnvelope.DeleteKeyFromContainer(rsaKeyContainerName);

After encrypting the message, we have it encrypted in the property:
[DataMember]
public byte[] EncryptedContents { get; private set; }

We can also initialize a CryptedEnvelope object directly with an encrypted data, provided that it was encrypted with the above mentioned procedure, or simply with another instance of CryptedEnvelope:
var envelope = new CryptedEnvelope(encryptedMessage);

Decrypting

The decryption process is done in the exact reverse way of the described in the Encrypting section above.

A CryptedEnvelope object containing an encrypted message in its EncryptedContents property can decrypt the message using:
var decodedMessage = envelope.RetrieveEnvelopeContents(c_rsaKeyContainerName, true);

Bundling all into a QR message

The QrMessage class is a container which properties can be (de)serialized (from)to a QR bar-code bitmap.
It contains the following serializable properties:
/// <summary>
/// Gets the version of the framework supporting this message structure. May be used for backward/forward compatibility or compatibility check.
/// </summary>
[DataMember]
public string Version { get; private set;}

/// <summary>
/// Gets the message contents. This is a textual message even when encrypted.ADISHILO
/// </summary>
[DataMember]
public byte[] MessageContents { get; private set; }

/// <summary>
/// Gets a value indicating whether this instance is encryped.
/// </summary>
[DataMember]
public bool IsEncrypted { get; private set; }

Version Is used for backward compatibility, and MessageContents is the actual buffer which is turned into and from a QR bar-code (and in the middle is converted to a base64 format).

Creating an encrypted QrMessage and QR-serializing it

Creating a QrMessage with a contained message is done via either of its constructors, and in order to create an encrypted QrMessage we use the constructor that has a parameter specifying the name for the .NET container for the RSA private key:
/// <summary>
/// Initializes a new instance of the <see cref="CryptoQrUtilities.QrMessage"/> class for text that needs encryption.
/// </summary>
/// <param name="message">The message to encrypt.</param>
/// <param name="rsaKeyContainerName">The RSA key container name to use with encryption.</param>
public QrMessage(string message, string rsaKeyContainerName)

Using this initialization method also encrypts the given message with the paradigm described above, when storing it in the MessageContents property:
var message = new QrMessage(passText, c_rsaKeyContainerName);

After creating the QrMessage object, we'd like to serialize it into a QR bitmap:
var newQr = message.SerializeIntoQr();

Deserializing a QR into QrMessage and extracting the message

When given a bitmap QR, we first decode the bitmap into a text:
string qrText;
var qrDecode = qrUtils.GetQrDecoding(snapshot);

if (qrDecode != null && qrDecode.Text != null)
{
    qrText = qrDecode.Text;
}

then decode the QrMessage:
var deserialized = QrMessage.DeserializeEncodedMessage(qrText);

and finally decrypt the actual message:
var envelope = new CryptedEnvelope(deserialized.MessageContents);
string decodedMessage = envelope.RetrieveEnvelopeContents(c_rsaKeyContainerName, true);

Last edited Dec 18, 2014 at 7:55 PM by adi3shilo, version 23