diff --git a/components/fpspreadsheet/source/common/fpscrypto.pas b/components/fpspreadsheet/source/common/fpscrypto.pas index 9fd4bbcd6..a0fe9b05b 100644 --- a/components/fpspreadsheet/source/common/fpscrypto.pas +++ b/components/fpspreadsheet/source/common/fpscrypto.pas @@ -5,28 +5,42 @@ interface uses SysUtils, fpsTypes; -function AlgorithmToStr(Algorithm: TsCryptoAlgorithm): String; +type + TsAlgorithmUsage = (auExcel, auOpenDocument); + +function AlgorithmToStr(Algorithm: TsCryptoAlgorithm; AUsage: TsAlgorithmUsage): String; function StrToAlgorithm(const AName: String): TsCryptoAlgorithm; function ExcelPasswordHash(const APassword: String): String; implementation -function AlgorithmToStr(Algorithm: TsCryptoAlgorithm): String; +uses + LazUTF8; + +function AlgorithmToStr(Algorithm: TsCryptoAlgorithm; AUsage: TsAlgorithmUsage): 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 := ''; + Result := ''; + case AUsage of + auExcel: + 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'; + end; + auOpenDocument: + case Algorithm of + caSHA1 : Result := 'http://www.w3.org/2000/09/xmldsig#sha1'; + caSHA256 : Result := 'http://www.w3.org/2000/09/xmldsig#sha256'; + end; end; end; @@ -56,22 +70,35 @@ begin end; end; -{@@ This is the code for generating Excel 2010 and earlier password's hash } -function ExcelPasswordHash(const APassword: string): string; -const - Key = $CE4B; +{@@ This is the code for generating Excel 2010 and earlier password's hash + See: http://forum.lazarus.freepascal.org/index.php/topic,36075.msg240132.html#msg240132 } +function ExcelPasswordHash( const APassword: string ): string; var i: Integer; - HashValue: Word = 0; + PassLen: Integer; + Password: string; + PassHash: Word = 0; begin - for i:= Length(APassword) downto 1 do + // we are needed to work with single byte character. + Password:= UTF8ToWinCP(APassword); + PassLen := Length(Password); + + if PassLen = 0 then begin - HashValue := ord(APassword[i]) xor HashValue; - HashValue := HashValue shl 1; + Result := ''; + exit; end; - HashValue := HashValue xor Length(APassword) xor Key; - - Result := IntToHex(HashValue, 4); + + for i:= PassLen downto 1 do + begin + PassHash:= ((PassHash shr 14) and $0001) or ((PassHash shl 1) and $7fff); + PassHash:= PassHash xor ord(Password[i]); + end; + + PassHash:= ((PassHash shr 14) and $0001) or ((PassHash shl 1) and $7fff); + PassHash:= PassHash xor PassLen xor $CE4B; + + Result := IntToHex(PassHash, 4); end; end. diff --git a/components/fpspreadsheet/source/common/xlsxooxml.pas b/components/fpspreadsheet/source/common/xlsxooxml.pas index 91bbca3f3..7c0c837ba 100644 --- a/components/fpspreadsheet/source/common/xlsxooxml.pas +++ b/components/fpspreadsheet/source/common/xlsxooxml.pas @@ -3435,7 +3435,7 @@ begin s := s + ' hashValue="' + AWorksheet.CryptoInfo.PasswordHash + '"'; if AWorksheet.CryptoInfo.Algorithm <> caUnknown then - s := s + ' algorithmName="' + AlgorithmToStr(AWorksheet.CryptoInfo.Algorithm) + '"'; + s := s + ' algorithmName="' + AlgorithmToStr(AWorksheet.CryptoInfo.Algorithm, auExcel) + '"'; if AWorksheet.CryptoInfo.SaltValue <> '' then s := s + ' saltValue="' + AWorksheet.CryptoInfo.SaltValue + '"'; @@ -4676,7 +4676,7 @@ begin begin s:= s + ' workbookHashVal="' + Workbook.CryptoInfo.PasswordHash + '"'; if Workbook.CryptoInfo.Algorithm <> caUnknown then - s:= s + ' workbookAlgorithmName="' + AlgorithmToStr(Workbook.CryptoInfo.Algorithm) + '"'; + s:= s + ' workbookAlgorithmName="' + AlgorithmToStr(Workbook.CryptoInfo.Algorithm, auExcel) + '"'; if Workbook.CryptoInfo.SaltValue <> '' then s:= s + ' workbookSaltValue="' + Workbook.CryptoInfo.SaltValue + '"'; diff --git a/components/fpspreadsheet/source/visual/fpspreadsheetctrls.pas b/components/fpspreadsheet/source/visual/fpspreadsheetctrls.pas index c93d77ef0..31a028c6c 100644 --- a/components/fpspreadsheet/source/visual/fpspreadsheetctrls.pas +++ b/components/fpspreadsheet/source/visual/fpspreadsheetctrls.pas @@ -3654,7 +3654,7 @@ begin if (ienCryptoInfo in FExpanded) then begin AStrings.Add('(-) CryptoInfo='); AStrings.Add(Format(' PasswordHash=%s', [Workbook.CryptoInfo.PasswordHash])); - AStrings.Add(Format(' Algorithm=%s', [AlgorithmToStr(Workbook.CryptoInfo.Algorithm)])); + AStrings.Add(Format(' Algorithm=%s', [AlgorithmToStr(Workbook.CryptoInfo.Algorithm, auExcel)])); AStrings.Add(Format(' SaltValue=%s', [Workbook.CryptoInfo.SaltValue])); AStrings.Add(Format(' SpinCount=%d', [Workbook.CryptoInfo.SpinCount])); end else @@ -3837,7 +3837,7 @@ begin if (ienCryptoInfo in FExpanded) then begin AStrings.Add('(-) CryptoInfo='); AStrings.Add(Format(' PasswordHash=%s', [Worksheet.CryptoInfo.PasswordHash])); - AStrings.Add(Format(' Algorithm=%s', [AlgorithmToStr(Worksheet.CryptoInfo.Algorithm)])); + AStrings.Add(Format(' Algorithm=%s', [AlgorithmToStr(Worksheet.CryptoInfo.Algorithm, auExcel)])); AStrings.Add(Format(' SaltValue=%s', [Worksheet.CryptoInfo.SaltValue])); AStrings.Add(Format(' SpinCount=%d', [Worksheet.CryptoInfo.SpinCount])); end else