English 中文(简体)
使用密码保护OpenXML电子表格工作簿
原标题:OpenXML Protect Spreadsheet Workbook with Password

我正在尝试使用OpenXML SDK创建受保护的电子表格文档。但是,生成的WorkbookHashValue不正确,因此无法取消对工作簿的保护。

var password = Encoding.UTF8.GetBytes("123");
var salt = new byte[16];
new RNGCryptoServiceProvider().GetNonZeroBytes(salt);
var spinCount = 100000U;

using (var document = SpreadsheetDocument.Create("text.xlsx", SpreadsheetDocumentType.Workbook))
{
    var workbookPart = document.AddWorkbookPart();
    var workbook = new Workbook();
    WorkbookProtection workbookProtection = new WorkbookProtection()
    {
        LockStructure = true,
        WorkbookAlgorithmName = "SHA-512",
        WorkbookHashValue = Convert.ToBase64String(GetPasswordHash(password, salt, spinCount)),
        WorkbookSaltValue = Convert.ToBase64String(salt),
        WorkbookSpinCount = spinCount
    };
    var sheets = new Sheets();
    var sheet = new Sheet
    {
        Name = "Sheet 1",
        SheetId = 1U,
        Id = "rId1"
    };
    sheets.Append(sheet);
    workbook.Append(workbookProtection);
    workbook.Append(sheets);
    workbookPart.Workbook = workbook;

    var worksheetPart = workbookPart.AddNewPart<WorksheetPart>("rId1");
    var worksheet = new Worksheet();
    var sheetData = new SheetData();
    worksheet.Append(sheetData);
    worksheetPart.Worksheet = worksheet;
}
private byte[] GetPasswordHash(byte[] password, byte[] salt, uint spinCount)
{
    using (var sha512 = SHA512.Create())
    {
        var buffer = new byte[salt.Length + password.Length];
        Array.Copy(salt, buffer, salt.Length);
        Array.Copy(password, 0, buffer, salt.Length, password.Length);
        byte[] hash = sha512.ComputeHash(buffer);
        buffer = new byte[hash.Length + 4];
        for (var i = 0U; i < spinCount; i++)
        {
            Array.Copy(hash, buffer, hash.Length);
            Array.Copy(BitConverter.GetBytes(i), 0, buffer, hash.Length, 4);
            hash = sha512.ComputeHash(buffer);
        }
        return hash;
    }
}

SALT VAQd0dyl7U67APquHio1lQ = =的密码123的正确哈希值应为2ZwXmW83qax0iUfzSkbhwAOVSDHAm6S/v9irWWTzdoFDgzO2Kc82P3Z9BAwbWqFLzN4rKaL0APOMzQ5tA7TBDw = = = ,但上述代码生成的z5ebojaXN/sD4ps9yurRCpSTDp + kSuTz + HN2PyKmGuicNgszAPKxfsE + kTgOEbGhT/VqSbwTd + + + oyAJxJh0L3A = =

最佳回答

用于获取密码字节的编码应为UTF16LE

Encoding.Unicode.GetBytes("123");
问题回答

暂无回答




相关问题
Anyone feel like passing it forward?

I m the only developer in my company, and am getting along well as an autodidact, but I know I m missing out on the education one gets from working with and having code reviewed by more senior devs. ...

NSArray s, Primitive types and Boxing Oh My!

I m pretty new to the Objective-C world and I have a long history with .net/C# so naturally I m inclined to use my C# wits. Now here s the question: I feel really inclined to create some type of ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

How to Use Ghostscript DLL to convert PDF to PDF/A

How to user GhostScript DLL to convert PDF to PDF/A. I know I kind of have to call the exported function of gsdll32.dll whose name is gsapi_init_with_args, but how do i pass the right arguments? BTW, ...

Linqy no matchy

Maybe it s something I m doing wrong. I m just learning Linq because I m bored. And so far so good. I made a little program and it basically just outputs all matches (foreach) into a label control. ...

热门标签