From af5c4d00e81b62a3f6ff6cb34a89502400552a2d Mon Sep 17 00:00:00 2001 From: "Jonham.Chen" <me@jonham.cn> Date: Sat, 8 Jan 2022 10:32:13 +0800 Subject: feat: implement SHA-512 algorithm to ProtectSheet (#1115) --- sheet.go | 49 +++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 43 insertions(+), 6 deletions(-) (limited to 'sheet.go') diff --git a/sheet.go b/sheet.go index 17f6693..26baca8 100644 --- a/sheet.go +++ b/sheet.go @@ -1129,10 +1129,14 @@ func (f *File) SetHeaderFooter(sheet string, settings *FormatHeaderFooter) error } // ProtectSheet provides a function to prevent other users from accidentally -// or deliberately changing, moving, or deleting data in a worksheet. For -// example, protect Sheet1 with protection settings: +// or deliberately changing, moving, or deleting data in a worksheet. The +// optional field AlgorithmName specified hash algorithm, support XOR, MD4, +// MD5, SHA1, SHA256, SHA384, and SHA512 currently, if no hash algorithm +// specified, will be using the XOR algorithm as default. For example, +// protect Sheet1 with protection settings: // // err := f.ProtectSheet("Sheet1", &excelize.FormatSheetProtection{ +// AlgorithmName: "SHA-512", // Password: "password", // EditScenarios: false, // }) @@ -1168,22 +1172,55 @@ func (f *File) ProtectSheet(sheet string, settings *FormatSheetProtection) error Sort: settings.Sort, } if settings.Password != "" { - ws.SheetProtection.Password = genSheetPasswd(settings.Password) + if settings.AlgorithmName == "" { + ws.SheetProtection.Password = genSheetPasswd(settings.Password) + return err + } + hashValue, saltValue, err := genISOPasswdHash(settings.Password, settings.AlgorithmName, "", int(sheetProtectionSpinCount)) + if err != nil { + return err + } + ws.SheetProtection.Password = "" + ws.SheetProtection.AlgorithmName = settings.AlgorithmName + ws.SheetProtection.SaltValue = saltValue + ws.SheetProtection.HashValue = hashValue + ws.SheetProtection.SpinCount = int(sheetProtectionSpinCount) } return err } -// UnprotectSheet provides a function to unprotect an Excel worksheet. -func (f *File) UnprotectSheet(sheet string) error { +// UnprotectSheet provides a function to remove protection for a sheet, +// specified the second optional password parameter to remove sheet +// protection with password verification. +func (f *File) UnprotectSheet(sheet string, password ...string) error { ws, err := f.workSheetReader(sheet) if err != nil { return err } + // password verification + if len(password) > 0 { + if ws.SheetProtection == nil { + return ErrUnprotectSheet + } + if ws.SheetProtection.AlgorithmName == "" && ws.SheetProtection.Password != genSheetPasswd(password[0]) { + return ErrUnprotectSheetPassword + } + if ws.SheetProtection.AlgorithmName != "" { + // check with given salt value + hashValue, _, err := genISOPasswdHash(password[0], ws.SheetProtection.AlgorithmName, ws.SheetProtection.SaltValue, ws.SheetProtection.SpinCount) + if err != nil { + return err + } + if ws.SheetProtection.HashValue != hashValue { + return ErrUnprotectSheetPassword + } + } + } ws.SheetProtection = nil return err } -// trimSheetName provides a function to trim invaild characters by given worksheet +// trimSheetName provides a function to trim invalid characters by given worksheet // name. func trimSheetName(name string) string { if strings.ContainsAny(name, ":\\/?*[]") || utf8.RuneCountInString(name) > 31 { -- cgit v1.2.1