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.