Technical Details

Where is my data and how does the encryption work?

This section goes into technical details on how Shot Works Pro stores your data.  The software is mostly written in VB.Net 2010, compiled against the Microsoft .Net 2.0 libraries.  Some parts of the software are written in C#.  I think it is important that folks understand how their data is stored and encrypted so you will feel safer utilizing this software.

The first time you start the program, a random asymmetric RSA encryption key pair is generated.  This key pair then is encrypted with symmetric AES 256 bit encryption that is generated based on your password.  That encrypted RSA key block is saved with your data.

When you log in, your password is used to generate an AES 256 bit key which then tries to decrypt the RSA key pair.  If the wrong password is used, this fails and you're prompted to try again.  If it works, then the decrypted RSA key is loaded into memory for use in decoding and encoding your data.

Data is stored with encrypted XML files.  All data is stored as basic text in a set of data tables.  The raw data tables are "serialized" into an XML file, which is then encrypted.  What happens is a temporary AES 256 key is created, which then encrypts the XML node.  The AES 256 key is then encrypted with the RSA key and saved with the data.  Without the original unlocked RSA key, the AES key cannot be decrypted, and therefore the XML cannot be decrypted.  For transparency reasons, here is the base code used to encrypt the XML which is based on code from MSDN.

    Friend Sub EncryptXmlDocument(ByVal XmlDoc As XmlDocument, Optional ByVal nodeXPath As String = "/*")
        Dim keyname As String = "sKey"
        ' Get the node to be encrypted
        Dim elementEncrypt As XmlElement = DirectCast(XmlDoc.SelectSingleNode(nodeXPath), XmlElement)
        ' Create a temporary symmetric key to be used for just this object
        Using sessionKey As New RijndaelManaged()
            sessionKey.KeySize = 256
            ' Encrypt the node with the temporary key
            Dim eXml As New EncryptedXml()
            Dim encryptedElement As Byte() = eXml.EncryptData(elementEncrypt, sessionKey, False)
            ' Encrypt the key with the RSA key
            Dim edElement As New EncryptedData()
            edElement.Type = EncryptedXml.XmlEncElementUrl
            edElement.EncryptionMethod = New EncryptionMethod(EncryptedXml.XmlEncAES256Url)
            ' Add the encrypted AES key
            Dim ek As New EncryptedKey()
            Dim encryptedKey As Byte() = EncryptedXml.EncryptKey(sessionKey.Key, _rsakey, False)
            ek.CipherData = New CipherData(encryptedKey)
            ek.EncryptionMethod = New EncryptionMethod(EncryptedXml.XmlEncRSA15Url)
            edElement.KeyInfo = New KeyInfo()
            ' Replace the existing xml node with the encrypted version.
            Dim kin As New KeyInfoName()
            kin.Value = keyname
            ek.KeyInfo.AddClause(kin)
            edElement.KeyInfo.AddClause(New KeyInfoEncryptedKey(ek))
            edElement.CipherData.CipherValue = encryptedElement
            EncryptedXml.ReplaceElement(elementEncrypt, edElement, False)
        End Using
    End Sub

Photos are also stored encrypted in Isolated Storage.  The RSA key is combined with an encryption salt to create an AES 256 bit key, which then encrypts the photo.  To ensure that items load quickly, a small thumbnail of each image is stored, also encrypted, but much smaller than the original for quicker decryption.  After loading of the item is completed, the full images are loaded in the background. 

The encryption code is here.  The RSA key and the salt are combined to create a symmetric AES 256 key.  Since photos can be very large, symmetric keys such as AES 256 are used because they are much faster than the asymmetric RSA keys directly.

    Friend Function EncryptStream(ByVal input As Stream) As Stream
        Dim e As New MemoryStream ' Output stream
        Using rm As New RijndaelManaged ' New AES 256 encryption key
            ' Add the key and initialization vector based on the salt and the RSA key
            Dim r2898 As New Rfc2898DeriveBytes(_rsakey.ToXmlString(True), Encoding.Unicode.GetBytes(_salt))
            rm.Key = r2898.GetBytes(CInt(rm.KeySize / 8))
            rm.IV = r2898.GetBytes(CInt(rm.BlockSize / 8))
            ' Create the encryption stream
            Dim cryptor As New CryptoStream(e, rm.CreateEncryptor(), CryptoStreamMode.Write)
            ' Write the stream to the encrypted memory stream.
            Dim b() As Byte = ReadAllBytes(input)
            cryptor.Write(b, 0, b.Length)
            cryptor.FlushFinalBlock()
        End Using
        ' Return the resulting encrypted stream
        Return e
    End Function

Credits

Shot Works Pro makes use of a few third party software libraries. Tar-CS is used to create the backup data files.  PSTaskDialog is used to show standard prompts throughout the program.  Software licensing and program obfuscation is provided by Intellilock.