Pergunta

I am having an issue using the OOXML library when attempting to read encrypted 2007 Excel documents. The password that I send to the DecryptToStream method is sending back a "Password not valid" message, but if I go directly into excel the password works fine. Below is the code I am using.

OleStorage ols = new OleStorage(d.fileLocation);
OfficeCrypto oc = new OfficeCrypto();
Stream test = oc.DecryptToStream(ols, "test123");

I have also tried using the POI Decryptor to attempt to read the encrypted 2007 excel, but I have had no luck with this as well. Below is code.

FileStream file = new FileStream(d.fileLocation, FileMode.Open, System.IO.FileAccess.Read);
NPOI.POIFS.FileSystem.POIFSFileSystem nfs;
nfs = new NPOI.POIFS.FileSystem.POIFSFileSystem(file);
Stream excelData;
try
{
    string password = "test123";
    EncryptionInfo info = new EncryptionInfo(nfs);
    Decryptor dc = Decryptor.GetInstance(info);

    if (!dc.VerifyPassword(password))
    {
        throw new NotImplementedException();
    }

    excelData = dc.GetDataStream(nfs);

}
catch (Exception ex)
{
    excelData = (Stream)file;
}

The VerifyPassword method always returns true no matter what I pass to it and it will still not read the document. I created the above code using http://poi.apache.org/encryption.html as a reference.

Any help would be greatly appreciated!

Foi útil?

Solução

As far as I know the current NPOI version 1.2.5 does not support Excel2007 files. Fortunately the NPOI 2.0 alpha version does support Excel2007 files but does not support encrypted Excel files.

However, there is a project called OfficeOpenXmlCrypto which supports reading encrypted Excel files. The project is based on the NPOI version 1.2.1 and the ExcelPackage project to read Excel 2007 files.

You can download the source of the OfficeOpenXmlCrypto project, replace the old NPOI library with the new NPOI 2.0 library and compile the project.

Then, you can use a comibnation of the XSSFWorkbook and OfficeCryptoStream classes to read the content of an encrypted Excel file:

using (OfficeCryptoStream ocs = OfficeCryptoStream.Open("c:\\temp\\secured.xlsx", "PA$$W0rd"))
{
  NPOI.XSSF.UserModel.XSSFWorkbook w = new NPOI.XSSF.UserModel.XSSFWorkbook(ocs);

  NPOI.xssf.extractor.XSSFExcelExtractor ee = new NPOI.xssf.extractor.XSSFExcelExtractor(w);

  Console.Out.WriteLine(ee.Text);                    
}

As an alternative the EPPlus class library provides a class called ExcelPackage which provides support for encrypted Excel documents. This class also has a few properties (Workbook) to access the content of the Excel document.

Here is a simple example reading the first cell of an encrypted Excel file:

using (FileStream file = new FileStream("c:\\temp\\secure.xlsx", 
       FileMode.OpenOrCreate, System.IO.FileAccess.ReadWrite))
{
  using (ExcelPackage ep = new ExcelPackage(file, "P@$$W0rd"))
  {
    Console.Out.WriteLine(ep.Workbook.Worksheets[1].Cells["A1"].Value);     
  }
} 

You can also use the OpenXml 2.0 SDK SpreadsheetDocument class in combination with the ExcelPackage class.

Use the following code to read the content of the first cell (encrypted Excel document):

using (FileStream file = new FileStream("c:\\temp\\secure.xlsx", 
       FileMode.OpenOrCreate, System.IO.FileAccess.ReadWrite))
{
  using (ExcelPackage ep = new ExcelPackage(file, "P@$$W0rd"))
  {     
    using (SpreadsheetDocument sd = SpreadsheetDocument.Open(ep.Package))
    {
      WorkbookPart workbookPart = sd.WorkbookPart;
      WorksheetPart worksheetPart = workbookPart.WorksheetParts.Last();
      SheetData sheetData = worksheetPart.Worksheet.Elements<SheetData>().First();

      var row = sheetData.Elements<Row>().FirstOrDefault();
      var cell = row.Elements<Cell>().FirstOrDefault();

      Console.Out.WriteLine(cell.CellValue.InnerText);
    }
  }
}

The constructor of the ExcelPackage class throws an UnauthorizedAccessException if the password is invalid.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top