54968

Downloading encrypted file from Window Azure storage

I have created a MVC WebRole Window Azure application where i upload encrypted files to Azure blob storage using SymmetricAlgorithm (Rijndael) like this

Controler>Action is

[HttpPost] public ActionResult UploadImage_post(HttpPostedFileBase fileBase) { if (fileBase.ContentLength > 0) { // Retrieve a reference to a container Microsoft.WindowsAzure.StorageClient.CloudBlobContainer blobContainer = _myBlobStorageService.GetCloudBlobContainer(); Microsoft.WindowsAzure.StorageClient.CloudBlob blob = blobContainer.GetBlobReference(fileBase.FileName); using (BlobStream blobStream = blob.OpenWrite()) { string encryptionKey = //somekey; byte[] file = new byte[fileBase.ContentLength]; EncDecAlgo.EncryptBlobFile(file, blobStream, encryptionKey); } } } public void EncryptBlobFile(byte[] file, BlobStream bs, string key) { PasswordDeriveBytes pdb = new PasswordDeriveBytes(key, new byte[] {0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76}); Rijndael alg = Rijndael.Create(); alg.Key = pdb.GetBytes(32); alg.IV = pdb.GetBytes(16); CryptoStream cs = new CryptoStream(bs, alg.CreateEncryptor(), CryptoStreamMode.Write); foreach (var data in file) { cs.WriteByte((byte)data); } cs.Close(); bs.Close(); }

The above File encryption is working fine.

For Downloading code is

public ActionResult DownloadFile(string filename) { // Retrieve reference to a previously created container. Microsoft.WindowsAzure.StorageClient.CloudBlobContainer blobContainer = _myBlobStorageService.GetCloudBlobContainer(); Microsoft.WindowsAzure.StorageClient.CloudBlob blob = blobContainer.GetBlobReference(filename); blob.FetchAttributes(); string encryptionKey = //same key used in encryption; using (BlobStream blobStream = blob.OpenRead()) { EncDecAlgo.DecryptBlobFile(blobStream, encryptionKey, filename); } } public static void DecryptBlobFile(BlobStream bs, string key, string filePath) { try { PasswordDeriveBytes pdb = new PasswordDeriveBytes(key, new byte[] {0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76}); Rijndael alg = Rijndael.Create(); alg.Key = pdb.GetBytes(32); alg.IV = pdb.GetBytes(16); CryptoStream cs = new CryptoStream(bs, alg.CreateDecryptor(), CryptoStreamMode.Read); // Decrypt & Download Here System.Web.HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment; filename=" + Path.GetFileName(filePath)); System.Web.HttpContext.Current.Response.ContentType = "application/" + Path.GetExtension(filePath).Replace(".", ""); int data; while ((data = cs.ReadByte()) != -1) { if (data != 0) { } System.Web.HttpContext.Current.Response.OutputStream.WriteByte((byte)data); System.Web.HttpContext.Current.Response.Flush(); } cs.Close(); bs.Close(); } catch { } }

On downloading get following error

Server cannot set content type after HTTP headers have been sent.

Please suggest some solution.

Answer1:

This should be fairly simple, hope this is enough to get you started:

public class CloudFileResult : ActionResult { private string m_FileName; private CloudBlobContainer m_Container; public CloudFileResult(string imageName, CloudBlobContainer container) { if (string.IsNullOrEmpty(imageName)) { throw new ArgumentNullException("imageName"); } if (container == null) { throw new ArgumentNullException("container"); } m_FileName = imageName; m_Container = container; } public override void ExecuteResult(ControllerContext context) { context.HttpContext.Response.Clear(); var blockBlob = m_Container.GetBlockBlobReference(m_FileName); blockBlob.FetchAttributes(); context.HttpContext.Response.ContentType = blockBlob.Metadata["ContentType"]; const string key = "my secret"; using (var pdb = new Rfc2898DeriveBytes(key, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 })) { using (var alg = RijndaelManaged.Create()) { alg.Key = pdb.GetBytes(32); alg.IV = pdb.GetBytes(16); using (var stream = new CryptoStream(context.HttpContext.Response.OutputStream, alg.CreateDecryptor(), CryptoStreamMode.Write)) { blockBlob.DownloadToStream(stream); } } } } } static void UploadFileToCloud(CloudBlobContainer container, HttpPostedFileBase file) { const string key = "my secret"; using (var pdb = new Rfc2898DeriveBytes(key, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 })) { using (var alg = RijndaelManaged.Create()) { alg.Key = pdb.GetBytes(32); alg.IV = pdb.GetBytes(16); var blockBlob = container.GetBlockBlobReference(file.FileName); using (var stream = new CryptoStream(file.InputStream, alg.CreateEncryptor(), CryptoStreamMode.Read)) { blockBlob.UploadFromStream(stream); } blockBlob.Metadata.Add("ContentType", file.ContentType); blockBlob.SetMetadata(); } } } static CloudBlobContainer GetContainer() { string connection = "DefaultEndpointsProtocol=http;AccountName=AzureAccount;AccountKey=AzureAccountKey;"; var account = CloudStorageAccount.Parse(connection); var client = account.CreateCloudBlobClient(); var container = client.GetContainerReference("container"); return container; }

As for download you can simple use:

[HttpGet] public ActionResult Index(string fileName) { if (!string.IsNullOrEmpty(fileName)) { return new CloudFileResult(fileName, GetContainer()); } return View(); }

Pointers:

    <li>I prefer using managed crypto algorithms</li> <li>I store contenttype of original file in blob metadata (so you know how to serve it)</li> <li>catch {} gives me creeps, at least log the exception somewhere</li> <li>Rather than playing with HttpContext.Response, create custom ActionResult</li> <li>Always dispose IDisposable stuff</li> </ul>

Recommend

  • Rijndael initialization vector with 16 bytes
  • Translating AesManaged to new universal app CryptographicEngine
  • compressing pdf file makes it bigger
  • Is there a FxCop rule for local used IDisposable's?
  • Why won't 3DES encrypt one block?
  • AES-Encrypt-then-MAC a large file with .NET
  • Vector of comma separated token to const char**
  • Creating certificate using makecert without pvk file
  • Posting to Facebook page from Facebook application without login to facebook
  • Securely storing (encrypting) data in an ASP.Net application
  • Hatch area using pcolormesh in Basemap
  • java.net.SocketTimeoutException on embedded tomcat with jersey
  • Why isn't \\\\ interpreted as a blackslash in this regex?
  • Send the string to its hex equivalent
  • Xamarin PCLCrypto SHA256 give different hash
  • NRefactory: How do I access unresolved Named Arguments on a Property Attribute?
  • Animate LayoutChanges does not work properly
  • How can I include If-None-Match header in HttpRequestMessage
  • Why value captured by reference in lambda is broken? [duplicate]
  • Encrypt data by using a public key in c# and decrypt data by using a private key in php
  • Is there a amazon webstore API for customers?
  • Can Jackson SerializationFeature be overridden per field or class?
  • How to extract text from Word files using C#?
  • vba code to select only visible cells in specific column except heading
  • Warning: Can't call setState (or forceUpdate) on an unmounted component
  • How to delete a row from a dynamic generate table using jquery?
  • Windows forms listbox.selecteditem displaying “System.Data.DataRowView” instead of actual value
  • InvalidAuthenticityToken between subdomains when logging in with Rails app
  • KeystoneJS: Relationships in Admin UI not updating
  • trying to dynamically update Highchart column chart but series undefined
  • using HTMLImports.whenReady not working in chrome
  • Why joiner is not used after Sequence generator or Update statergy
  • embed rChart in Markdown
  • Authorize attributes not working in MVC 4
  • EntityFramework adding new object to nested object collection
  • Recursive/Hierarchical Query Using Postgres
  • How to get NHibernate ISession to cache entity not retrieved by primary key
  • How can I use `wmic` in a Windows PE script?
  • UserPrincipal.Current returns apppool on IIS
  • Unable to use reactive element in my shiny app