如何使用Open XML密码保护Excel文档

Rud*_*cht 5 c# openxml

目前,我正在SpreadsheetDocument通过传递MemoryStream参数来创建一个包含Open XML 类的新Excel文档.我现在需要在这个SpreadsheetDocument对象上设置一个密码,但我尝试过的东西似乎不起作用.Excel文档无需输入密码即可打开.以下是我到目前为止所尝试的(mem作为MemoryStream参数):

using (SpreadsheetDocument spreadsheet = SpreadsheetDocument.Open(mem, true))
{
    foreach (var sheet in spreadsheet.WorkbookPart.WorksheetParts)
    {
        sheet.Worksheet.Append(new SheetProtection() { Password = "test" });
    }
}
Run Code Online (Sandbox Code Playgroud)

我也试过以下但没有成功:

using (SpreadsheetDocument spreadsheet = SpreadsheetDocument.Open(mem, true))
{
    spreadsheet.WorkbookPart.Workbook.WorkbookProtection = new WorkbookProtection
    {
        LockStructure = true,
        LockWindows = true,
        WorkbookPassword = "test"
    }
}
Run Code Online (Sandbox Code Playgroud)

我错过了什么?

小智 7

Openxml 表保护密码的输入数据类型为“HexBinaryValue”。所以输入密码要从字符串转换为十六进制二进制。

foreach (var worksheetPart in spreadsheet.WorkbookPart.WorksheetParts)
     {
         //Call the method to convert the Password string "MyPasswordfor sheet" to hexbinary type
         string hexConvertedPassword =  HexPasswordConversion("MyPasswordfor sheet");
//passing the Converted password to sheet protection
          SheetProtection sheetProt = new SheetProtection() { Sheet = true, Objects = true, Scenarios = true, Password = hexConvertedPassword };
          worksheetPart.Worksheet.InsertAfter(sheetProt,worksheetPart.Worksheet.Descendants<SheetData>().LastOrDefault());
worksheetPart.Worksheet.Save();
     }


/* This method will convert the string password to hexabinary value */
 protected string HexPasswordConversion(string password)
        {
            byte[] passwordCharacters = System.Text.Encoding.ASCII.GetBytes(password);
            int hash = 0;
            if (passwordCharacters.Length > 0)
            {
                int charIndex = passwordCharacters.Length;

                while (charIndex-- > 0)
                {
                    hash = ((hash >> 14) & 0x01) | ((hash << 1) & 0x7fff);
                    hash ^= passwordCharacters[charIndex];
                }
                // Main difference from spec, also hash with charcount
                hash = ((hash >> 14) & 0x01) | ((hash << 1) & 0x7fff);
                hash ^= passwordCharacters.Length;
                hash ^= (0x8000 | ('N' << 8) | 'K');
            }

            return Convert.ToString(hash, 16).ToUpperInvariant();
        }
Run Code Online (Sandbox Code Playgroud)

  • 你从哪里得到计算散列密码的算法? (2认同)

Rud*_*cht 0

好吧,这并不完全是我想要做的,但我最终放弃了 Open XML SDK 并使用 Office.Interop 程序集来保护文档。最初使用 Open XML 的原因是因为 Interop 工作簿似乎无法使用流打开,它需要一个实际的文件。