From 6126788bec1068a05ec60bd59337442391286598 Mon Sep 17 00:00:00 2001 From: wp_xxyyzz Date: Sun, 5 Mar 2017 12:25:29 +0000 Subject: [PATCH] fpspreadsheet: Refactor TsCryptoInfo record. git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@5788 8e941d3f-bd1b-0410-a28a-d453659cc2b4 --- .../fpspreadsheet/source/common/fpscrypto.pas | 40 +++++++++- .../fpspreadsheet/source/common/fpstypes.pas | 14 +++- .../fpspreadsheet/source/common/fpsutils.pas | 4 +- .../fpspreadsheet/source/common/xlsxooxml.pas | 76 +++++++++++-------- .../source/visual/fpspreadsheetctrls.pas | 10 +-- 5 files changed, 101 insertions(+), 43 deletions(-) diff --git a/components/fpspreadsheet/source/common/fpscrypto.pas b/components/fpspreadsheet/source/common/fpscrypto.pas index b2679fb1c..b652b0147 100644 --- a/components/fpspreadsheet/source/common/fpscrypto.pas +++ b/components/fpspreadsheet/source/common/fpscrypto.pas @@ -3,12 +3,50 @@ unit fpsCrypto; interface uses - SysUtils; + SysUtils, fpsTypes; + +function AlgorithmToStr(Algorithm: TsCryptoAlgorithm): String; +function StrToAlgorithm(const AName: String): TsCryptoAlgorithm; function ExcelPasswordHash(const APassword: String): String; implementation +function AlgorithmToStr(Algorithm: TsCryptoAlgorithm): String; +begin + case Algorithm of + caExcel : Result := 'EXCEL'; + caMD2 : Result := 'MD2'; + caMD4 : Result := 'MD4'; + caMD5 : Result := 'MD5'; + caRIPEMD128 : Result := 'RIPEMD-128'; + caRIPEMD160 : Result := 'RIPEMD-160'; + caSHA1 : Result := 'SHA-1'; + caSHA256 : Result := 'SHA-256'; + caSHA384 : Result := 'SHA-384'; + caSHA512 : Result := 'SHA-512'; + caWHIRLPOOL : Result := 'WHIRLPOOL'; + else Result := ''; + end; +end; + +function StrToAlgorithm(const AName: String): TsCryptoAlgorithm; +begin + case AName of + 'MD2' : Result := caMD2; + 'MD4' : Result := caMD4; + 'MD5' : Result := caMD5; + 'RIPEMD-128' : Result := caRIPEMD128; + 'RIPEMD-160' : Result := caRIPEMD160; + 'SHA-1' : Result := caSHA1; + 'SHA-256' : Result := caSHA256; + 'SHA-384' : Result := caSHA384; + 'SHA-512' : Result := caSHA512; + 'WHIRLPOOL' : Result := caWHIRLPOOL; + else Result := caUnknown; + end; +end; + {@@ This is the code for generating Excel 2010 and earlier password's hash } function ExcelPasswordHash(const APassword: string): string; const diff --git a/components/fpspreadsheet/source/common/fpstypes.pas b/components/fpspreadsheet/source/common/fpstypes.pas index 46f8288c3..9d0ad2bf2 100644 --- a/components/fpspreadsheet/source/common/fpstypes.pas +++ b/components/fpspreadsheet/source/common/fpstypes.pas @@ -638,10 +638,18 @@ type {@@ Switch a cell from left-to-right to right-to-left orientation } TsBiDiMode = (bdDefault, bdLTR, bdRTL); - {@@ } + {@@ Algorithm used for encryption/decryption } + TsCryptoAlgorithm = (caUnknown, + caExcel, // Excel <= 2010 + caMD2, caMD4, caMD5, caRIPEMD128, caRIPEMD160, + caSHA1, caSHA256, caSHA384, caSHA512, + caWHIRLPOOL + ); + + {@@ Record collection information for encryption/decryption } TsCryptoInfo = record - AlgorithmName: string; - Password: string; // For old version of Excel (2010 and earlier) + PasswordHash: String; + Algorithm: TsCryptoAlgorithm; HashValue: string; SaltValue: string; SpinCount: Integer; diff --git a/components/fpspreadsheet/source/common/fpsutils.pas b/components/fpspreadsheet/source/common/fpsutils.pas index e542f8206..a1b8234f4 100644 --- a/components/fpspreadsheet/source/common/fpsutils.pas +++ b/components/fpspreadsheet/source/common/fpsutils.pas @@ -2085,8 +2085,8 @@ end; -------------------------------------------------------------------------------} procedure InitCryptoInfo(out AValue: TsCryptoInfo); begin - AValue.Password := ''; - AValue.AlgorithmName := ''; + AValue.PasswordHash := ''; + AValue.Algorithm := caUnknown; AValue.HashValue := ''; AValue.SaltValue := ''; AValue.SpinCount := 0; diff --git a/components/fpspreadsheet/source/common/xlsxooxml.pas b/components/fpspreadsheet/source/common/xlsxooxml.pas index a1b432b1e..96f4df9ba 100644 --- a/components/fpspreadsheet/source/common/xlsxooxml.pas +++ b/components/fpspreadsheet/source/common/xlsxooxml.pas @@ -235,7 +235,7 @@ implementation uses variants, strutils, math, lazutf8, LazFileUtils, uriparser, - {%H-}fpsPatches, + {%H-}fpsPatches, fpsCrypto, fpsStrings, fpsStreams, fpsClasses, fpsImages; const @@ -2013,16 +2013,19 @@ begin InitCryptoInfo(shc); s := GetAttrValue(ANode, 'password'); - if s <> '' then - shc.Password := s - else + if s <> '' then begin + shc.PasswordHash := s; + shc.Algorithm := caExcel; + end else begin s := GetAttrValue(ANode, 'hashValue'); if s <> '' then begin - shc.HashValue := s; + shc.PasswordHash := s; s := GetAttrValue(ANode, 'algorithmName'); - shc.AlgorithmName := s; + shc.Algorithm := StrToAlgorithm(s); + if shc.Algorithm = caUnknown then + Workbook.AddErrorMsg('Found unknown encryption algorithm "%s" for worksheet protection', [s]); s := GetAttrValue(ANode, 'saltValue'); shc.SaltValue := s; @@ -2290,14 +2293,20 @@ begin InitCryptoInfo(wbc); s := GetAttrValue(ANode, 'workbookPassword'); if s <> '' then - wbc.Password := s + wbc.PasswordHash := s else begin s := GetAttrValue(ANode, 'workbookHashVal'); if s <> '' then begin - wbc.HashValue := s; - wbc.AlgorithmName := GetAttrValue(ANode, 'workbookAlgorithmName'); + wbc.PasswordHash := s; + + s := GetAttrValue(ANode, 'workbookAlgorithmName'); + wbc.Algorithm := StrToAlgorithm(s); + if wbc.Algorithm = caUnknown then + Workbook.AddErrorMsg('Found unknown encryption algorithm "%s" for workbook protection', [s]); + wbc.SaltValue := GetAttrValue(ANode, 'workbookSaltValue'); + wbc.SpinCount := StrToIntDef(GetAttrValue(ANode, 'workbookSpinCount'), 0); end; end; @@ -3435,21 +3444,22 @@ begin else Exit; //exit if sheet not protected - if AWorksheet.CryptoInfo.Password <> '' then - s := s + ' password="' + AWorksheet.CryptoInfo.Password + '"' - else - if AWorksheet.CryptoInfo.HashValue <> '' then - begin - s := s + ' hashValue="' + AWorksheet.CryptoInfo.HashValue + '"'; + if AWorksheet.CryptoInfo.PasswordHash <> '' then begin + if AWorksheet.CryptoInfo.Algorithm = caExcel then + s := s + ' password="' + AWorksheet.CryptoInfo.PasswordHash + '"' + else + begin + s := s + ' hashValue="' + AWorksheet.CryptoInfo.HashValue + '"'; - if AWorksheet.CryptoInfo.AlgorithmName <> '' then - s := s + ' algorithmName="' + AWorksheet.CryptoInfo.AlgorithmName + '"'; + if AWorksheet.CryptoInfo.Algorithm <> caUnknown then + s := s + ' algorithmName="' + AlgorithmToStr(AWorksheet.CryptoInfo.Algorithm) + '"'; - if AWorksheet.CryptoInfo.SaltValue <> '' then - s := s + ' saltValue="' + AWorksheet.CryptoInfo.SaltValue + '"'; + if AWorksheet.CryptoInfo.SaltValue <> '' then + s := s + ' saltValue="' + AWorksheet.CryptoInfo.SaltValue + '"'; - if AWorksheet.CryptoInfo.SpinCount <> 0 then - s := s + ' spinCount="' + IntToStr(AWorksheet.CryptoInfo.SpinCount) + '"'; + if AWorksheet.CryptoInfo.SpinCount <> 0 then + s := s + ' spinCount="' + IntToStr(AWorksheet.CryptoInfo.SpinCount) + '"'; + end; end; { @@ -4675,20 +4685,22 @@ var begin s := ''; - if Workbook.CryptoInfo.Password <> '' then - s := s + ' workbookPassword="' + Workbook.CryptoInfo.Password + '"' - else - if Workbook.CryptoInfo.HashValue <> '' then + if Workbook.CryptoInfo.PasswordHash <> '' then begin - s:= s + ' workbookHashVal="' + Workbook.CryptoInfo.HashValue + '"'; - if Workbook.CryptoInfo.AlgorithmName <> '' then - s:= s + ' workbookAlgorithmName="' + Workbook.CryptoInfo.AlgorithmName + '"'; + if Workbook.CryptoInfo.Algorithm = caExcel then + s := s + ' workbookPassword="' + Workbook.CryptoInfo.PasswordHash + '"' + else + begin + s:= s + ' workbookHashVal="' + Workbook.CryptoInfo.PasswordHash + '"'; + if Workbook.CryptoInfo.Algorithm <> caUnknown then + s:= s + ' workbookAlgorithmName="' + AlgorithmToStr(Workbook.CryptoInfo.Algorithm) + '"'; - if Workbook.CryptoInfo.SaltValue <> '' then - s:= s + ' workbookSaltValue="' + Workbook.CryptoInfo.SaltValue + '"'; + if Workbook.CryptoInfo.SaltValue <> '' then + s:= s + ' workbookSaltValue="' + Workbook.CryptoInfo.SaltValue + '"'; - if Workbook.CryptoInfo.SpinCount <> 0 then - s:= s + ' workbookSpinCount="' + IntToStr(Workbook.CryptoInfo.SpinCount) + '"'; + if Workbook.CryptoInfo.SpinCount <> 0 then + s:= s + ' workbookSpinCount="' + IntToStr(Workbook.CryptoInfo.SpinCount) + '"'; + end; end; { diff --git a/components/fpspreadsheet/source/visual/fpspreadsheetctrls.pas b/components/fpspreadsheet/source/visual/fpspreadsheetctrls.pas index 52cb7c0e8..1c9b405c0 100644 --- a/components/fpspreadsheet/source/visual/fpspreadsheetctrls.pas +++ b/components/fpspreadsheet/source/visual/fpspreadsheetctrls.pas @@ -584,7 +584,7 @@ implementation uses Types, Math, StrUtils, TypInfo, LCLType, LCLIntf, LCLProc, Dialogs, Forms, Clipbrd, - fpsStrings, fpsReaderWriter, fpsUtils, fpsNumFormat, fpsImages, + fpsStrings, fpsCrypto, fpsReaderWriter, fpsUtils, fpsNumFormat, fpsImages, fpsHTMLUtils, fpsCSV; var @@ -3653,8 +3653,8 @@ begin if (ienCryptoInfo in FExpanded) then begin AStrings.Add('(-) CryptoInfo='); - AStrings.Add(Format(' Password=%s', [Workbook.CryptoInfo.Password])); - AStrings.Add(Format(' AlgorithmName=%s', [Workbook.CryptoInfo.AlgorithmName])); + AStrings.Add(Format(' PasswordHash=%s', [Workbook.CryptoInfo.PasswordHash])); + AStrings.Add(Format(' Algorithm=%s', [AlgorithmToStr(Workbook.CryptoInfo.Algorithm)])); AStrings.Add(Format(' HashValue=%s', [Workbook.CryptoInfo.HashValue])); AStrings.Add(Format(' SaltValue=%s', [Workbook.CryptoInfo.SaltValue])); AStrings.Add(Format(' SplinCount=%d', [Workbook.CryptoInfo.SpinCount])); @@ -3837,8 +3837,8 @@ begin if (ienCryptoInfo in FExpanded) then begin AStrings.Add('(-) CryptoInfo='); - AStrings.Add(Format(' Password=%s', [Worksheet.CryptoInfo.Password])); - AStrings.Add(Format(' AlgorithmName=%s', [Worksheet.CryptoInfo.AlgorithmName])); + AStrings.Add(Format(' PasswordHash=%s', [Worksheet.CryptoInfo.PasswordHash])); + AStrings.Add(Format(' Algorithm=%s', [AlgorithmToStr(Worksheet.CryptoInfo.Algorithm)])); AStrings.Add(Format(' HashValue=%s', [Worksheet.CryptoInfo.HashValue])); AStrings.Add(Format(' SaltValue=%s', [Worksheet.CryptoInfo.SaltValue])); AStrings.Add(Format(' SplinCount=%d', [Worksheet.CryptoInfo.SpinCount]));