0

We have an encrypted binary field in a SQL server DB with a key and we are trying to decrypt the file. It creates the PDF files that we need with the correct file names in the specified directory but when we try to open them we get an error that they were not decrypted correctly.

The file type is .PDF and we can tell by the size that there is content in the files.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.SqlClient;
using System.IO;
using System.Security.Cryptography;
using System.Configuration;

namespace PHDocExtract
{
    class Program
    {
        private static List<PHDocFile> GetPHDocFiles()
        {
            List<PHDocFile> docList = new List<PHDocFile>();
            PHDocFile docFile;
            Database db = new Database();
            SqlConnection connection = db.GetConnection();

            string sqlQuery = "select Filename, ENCRYPTION_KEY, Filedata from dbo.PHATTACH where RECORD_TYPE = 'client' and PHATTACH_KEY > 116 and PHATTACH_KEY < 170";

            SqlCommand command = new SqlCommand(sqlQuery, connection);
            SqlDataReader dataReader = command.ExecuteReader();

            while (dataReader.Read())
            {
                docFile = new PHDocFile();
                docFile.FileName = dataReader.GetString(0);                
                docFile.EncryptionKey = dataReader.GetString(1);
                docFile.FileData = dataReader.GetSqlBytes(2);
                docList.Add(docFile);
                docFile = null;
            }

            db.CloseConnection();

            return docList;
        }

        private static void DecryptFiles(List<PHDocFile> docFiles)
        {
            UnicodeEncoding unicodeEncoding = new UnicodeEncoding();
            MemoryStream returnStream = new MemoryStream();
            RijndaelManaged crypto = new RijndaelManaged();

            crypto.KeySize = 256;
            crypto.BlockSize = 128;
            crypto.Mode = CipherMode.CBC;

            foreach (PHDocFile doc in docFiles)
            {

                var key = new Rfc2898DeriveBytes(doc.EncryptionKey, unicodeEncoding.GetBytes(doc.EncryptionKey.Substring(0, 8)), 1000);
                crypto.Key = key.GetBytes(crypto.KeySize / 8);
                crypto.IV = key.GetBytes(crypto.BlockSize / 8);

                //fileStream.Seek(0, SeekOrigin.Begin);
                //Stream inputFileStream = fileStream;
                Stream inputFileStream = doc.FileData.Stream;
                CryptoStream cryptoStream = new CryptoStream(inputFileStream, crypto.CreateDecryptor(), CryptoStreamMode.Read);

                int data;
                try
                {
                    while ((data = cryptoStream.ReadByte()) != -1)
                    {
                        returnStream.WriteByte((byte)data);
                    }
                }
                catch (CryptographicException ex)
                {
                    // ¯\_(ツ)_/¯
                    Console.WriteLine(ex.ToString());
                }

                doc.DecryptedFileData = returnStream.ToArray();

                //if (cryptoStream != null)
                //    cryptoStream.Dispose();
                //if (inputFileStream != null)
                //    inputFileStream.Dispose();
            }
        }

        private static void WriteFiles(List<PHDocFile> docFiles)
        {
            string exportFilePath = ConfigurationManager.AppSettings["outputFolder"];
            FileStream fileStream;
            BinaryWriter binaryWriter;

            foreach (PHDocFile docFile in docFiles)
            {
                fileStream = new FileStream(exportFilePath + docFile.FileName, FileMode.Create, FileAccess.Write);
                binaryWriter = new BinaryWriter(fileStream);

                foreach (byte idx in docFile.DecryptedFileData)
                {
                    binaryWriter.Write(idx);
                    binaryWriter.Flush();
                }
                binaryWriter.Close();
                fileStream.Close();
            }
        }

        static void Main(string[] args)
        {
            List<PHDocFile> phDocFiles = new List<PHDocFile>();
            phDocFiles = GetPHDocFiles();
            DecryptFiles(phDocFiles);
            WriteFiles(phDocFiles);
        }
    }
}

Adobe Acrobat Reader could not open (file name) because it is wither not a supported file type or because the file has been damaged (for example, it was sent as an email attachment and wasn't correctly decoded).

dangell82
  • 1
  • 1
  • `decrypted binary field in a SQL server DB with a key and we are trying to decrypt the file` am I missing something here? You have a decrypted field, but you are trying to decrypt the file? – Trevor Aug 13 '19 at 13:40
  • 1
    What type of column is `Filedata` ? IMO save the encryption key with the data encrypted doesnt have sense, if you save the file encrypted in another location is right... – kip Aug 13 '19 at 13:40
  • I think he meant to say `file`. Anyway, we'd need to see the encrypting side as well. – 500 - Internal Server Error Aug 13 '19 at 13:41
  • 1
    The usage of `Rfc2898DeriveBytes` here is pretty debatable but more important: it has to match what the encryptor did. – H H Aug 13 '19 at 13:43
  • Create a [mcve] where you first encrypt a file and then decrypt it, most likely you won't be able to do that and then you have something to debug. Encryption and decryption go hand-in-hand, a bug in either can make it impossible to decrypt the final result. – Lasse V. Karlsen Aug 13 '19 at 13:45
  • Yeah it's a file stored in the database with 'Filedata' being a varbinary(MAX) type. We get the files already encrypted from the vendor and they provided us with the decryption code and the encryption keys. We don't have access to see the encryption code. – dangell82 Aug 13 '19 at 13:47
  • Could you test the code with a file taked from path instead of db ? Do you have the specification from the vendor about the encryption method used ? – kip Aug 13 '19 at 13:54
  • The vendor provided us with the decryption code so it should match but to be sure I have requested an example of the encryption code from them. – dangell82 Aug 13 '19 at 13:56
  • The vendor won't give us the encryption code. – dangell82 Aug 13 '19 at 14:32

0 Answers0