Thoughts and Experiments on Cloud Encryption

[ Dies ist ein Auszug aus meinem Artikel “Wolkentresor” im dotnetpro Magazin 9.2015 mit einigen ergänzenden Abbildungen ]

Private files should only be stored in the cloud being encrypted via a key controlled and known by the user solely (= end-to-end encryption). Transport encryption and encryption in the cloud provided by storage providers are not sufficient here.

Attack Surface

Attack Surface

The safety of encryption depends on good passwords. Passwords are good if they are not only strong but also easy to use. For an interesting discussion about better passwords see Toward Better Master Passwords.

Some cloud storage providers like Tresorit support automatic end-to-end encryption out of the box. Many widely used services like DropBox and the deeply in Windows integrated OneDrive are sadly lacking this support. For these one can use additional encryption tools like:

boxcryptor: Good commercial tool.
CryptSync: Free open source tool based on 7-zip encryption.
Allows decrypting files even without CrypSync using 7-zip apps.

Without any form of automated end-to-end cloud encryption one should encrypt private data manually before storing it in the cloud, which is inconvenient. Some tools for this are: 7-zip passwords, TrueCrypt 7.1a or VeraCrypt.

Data I classify as “paranoid” should not be stored in the cloud at all. Some of it should never be stored electronically at all, like critical login credentials or banking TANs.

OneNote uses a custom synchronization mechanism over OneDrive. Thus non of the automatic encryption approaches work with it. One either looses synchronization or must use inconvenient  notebook or section passwords

In addition to end-to-end cloud encryption one should encrypt local drives because your files (or at least remnants of them) are stored there in decrypted form. Win10 does automatically enable BitLocker for all internal drives (not for removable drives like SD cards!) but for convenience stores the key under your Microsoft account in OneDrive, see onedrive.live.com/recoverykey. To regain control of your keys one can disable and reenable BitLocker and not select “Save to your Microsoft account”. By this you loose the convenience of MS taking care of your keys and are responsible yourself: if you loose your key you loose your data!  On Win10 mobile one must manually enable encryption via Settings, System, Device Encryption. Win10 mobile does not allow to encrypt removable drives and there seems to be no way to gain control of your keys, see here.

CloudCryptor experimental app

When using cloud storage one has to trust storage providers and/or creators of encryption tools. Thus it would be nice to roll your own end-to-end encryption. To get a feeling for this I wrote the experimental app CloudCryptor (download code). Beware! I have limited expertise in security and my experimental code is buggy and unsafe (e.g. does not use the IV properly). While the abstraction level of the .NET crypto API is nicely high, the strength of a crypto solution depends on selecting the right crypto methods and using them correctly for which one needs solid crypto expertise. My resumé: Don’t write your own encryption apps if you are not a security expert!

CloudCryptor uses the following .NET crypto and compression classes:

  • Rfc2898DeriveBytes
  • ProtectedData
  • AesManaged
  • CrytoStream
  • DeflateStream
CloudCryptoArchitecture

Attack Surface

CloudCryptor functionality

  • Works on folder pairs: encrypted folder / clear folder.
  • Encrypted folder synced to cloud (OneDrive, DropBox, …).
  • User works on clear folder.
  • Windows service does encrypt / decrypt files via an AES CryptoStraeam.
  • Derives the encryption key from a user supplied password via Rfc2898DeriveBytes.
  • Password stored locally encrypted via ProtectedData (DPAPI).
  • For simplicity polls for changes instead of using FileSystemWatchers.
    See Windows Service Worker Options.
  • WinForms UI to configure Windows service via WCF.

Stream pipeline for compressing and encrypting

Because encrypted data does not compress CloudCryptor compresses before encrypting. To improve performance a stream pipeline is used.

Sub CompressAndEncryptFile(fromFileInfo As FileInfo)
  Try
  …
    Using fromFileStream As FileStream = fromFileInfo.OpenRead(),
          aes As New AesManaged

        aes.GenerateIV()
        Dim password = ProtectedString.UnProtect(My.Settings.ProtectedPassword,
                                                DataProtectionScope.CurrentUser)
        Dim keyGenerator As New Rfc2898DeriveBytes(password, Encoding.Unicode.GetBytes(Salt),
                                                   10000)
        aes.Key = keyGenerator.GetBytes(aes.KeySize >> 3) 'KeySize is in bits

        Using toFileStream As FileStream = File.Create(toFilePathTemp),
             encryptorStream As New CryptoStream(toFileStream, aes.CreateEncryptor
                                                CryptoStreamMode.Write),
             compressorStream As DeflateStream = New DeflateStream(encryptorStream,
                                                 CompressionLevel.Optimal, False)

            'Prepend IV
            'BUG: !!!To strengthen Cipher Block Chaining the IV should be prepended
            'to the clear text and encypted instead
            Dim ivStream As New MemoryStream(aes.IV)
            ivStream.CopyTo(toFileStream)

            fromFileStream.CopyTo(compressorStream)
    End Using
  Catch ex As IOException When IsFileInUse(ex)
    _trace.InfoFormat("Skipping file in use {0}", ex.Message)
  Catch ex As Exception
    _trace.ErrorFormat("Unexpected error {0}", ex.ToString)
  End Try

Encrypting the password

To avoid having to enter the password frequently it can be stored locally. CloudCryptor stores the password encrypted via  ProtectedData (= NET API of the Windows Data Protection API (DPAPI)). DPAPI derives its encryption key form the login  credentials of the current Windows user.

Public Class ProtectedString
    'To add some protection against other apps run by same user decrypting the string
    Private Shared _aditionalEntropy = New Byte(15) {0, 7 … , 22, 11, 9, 2, 5, 8}

    Public Shared Function Protect(clearText As String
                                   scope As DataProtectionScope) As String
        Return Convert.ToBase64String(ProtectedData.Protect(Encoding.UTF8.GetBytes(clearText),
                                                            _aditionalEntropy, scope))
    End Function

    Public Shared Function UnProtect(encryptedText As String,
                                     scope As DataProtectionScope) As String
        Return Encoding.UTF8.GetString(
                              ProtectedData.Unprotect(Convert.FromBase64String(encryptedText),
                              _aditionalEntropy, scope))
    End Function
End Class

Configuration UI

Notice the DPAPI encrypted password in the config file!

CloudCryptorUI

Configuration UI

Cross-device usage

End-to-end encrypted files can be used across heterogeneous devices like desktops, tablets and phones. BoxCryptor offers a Win10 mobile app and there are 7-zip apps with password support for Win10 mobile. In my CloudCryptor experiments I used “file type associations” to trigger decryption on the Windows Phone.

CrossDeviceIntegration

Cross-Device Usage

About Peter Meinl

IT Consultant
This entry was posted in Computers and Internet and tagged , , , , , . Bookmark the permalink.

2 Responses to Thoughts and Experiments on Cloud Encryption

  1. Wieslaw says:

    Hello Peter,
    Nice informative article, thanks to you, today I learned about diceware-generated passphrases.

    It is important to put clear files onto a path that is not potentially synced to the cloud. In your app sample, it should be fine since the encrypted folder is not where the user directly writes their files into.

    Otherwise, depending on several factors like your internet connection speed, file size/count and PC computing power, sync period, etc., it may be very well be possible the clear file is sent to the cloud before the fogging service has finished its job.
    It has been experienced firsthand by a boxcryptor-like commercial product user in that topic:
    https://forums.viivo.com/showthread.php?3252-Very-disappointing-flaw-files-uploaded-before-encryption-this-is-NOT-secure!
    when folder sync (clear-encrypted folder pair) is not enabled.

    Even with folder sync enabled, I’m not positive it is secure enough. If by mistake clear files are saved in the cloud folder, according to logs, it is copied to the clear folder then used as source for encrypting. However, if we suppose a huge file copy takes some time for some reason, all clear files sit there while in the mean time and may potentially be uploaded.

    • Peter Meinl says:

      Hi Wieslaw,

      Correct: “It is important to put clear files onto a path that is not potentially synced to the cloud.
      In my code experiment files are copied to the synced folder via a stream pipeline containing an encrypting stream.
      Thus no clear file or part of a clear file ever gets copied to the cloud, regardless of the file size.
      I expect commercial products implementing something similar.

      The problem with Viivo you are referring to looks like users not being aware of sideeffects of a specific feature usage of this product.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s