fpspreadsheet: Fix Excel password hash calculation (patch by shobits1).
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@5792 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
parent
16118290c5
commit
06688f42e1
@ -5,28 +5,42 @@ interface
|
|||||||
uses
|
uses
|
||||||
SysUtils, fpsTypes;
|
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 StrToAlgorithm(const AName: String): TsCryptoAlgorithm;
|
||||||
|
|
||||||
function ExcelPasswordHash(const APassword: String): String;
|
function ExcelPasswordHash(const APassword: String): String;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
function AlgorithmToStr(Algorithm: TsCryptoAlgorithm): String;
|
uses
|
||||||
|
LazUTF8;
|
||||||
|
|
||||||
|
function AlgorithmToStr(Algorithm: TsCryptoAlgorithm; AUsage: TsAlgorithmUsage): String;
|
||||||
begin
|
begin
|
||||||
case Algorithm of
|
Result := '';
|
||||||
caExcel : Result := 'EXCEL';
|
case AUsage of
|
||||||
caMD2 : Result := 'MD2';
|
auExcel:
|
||||||
caMD4 : Result := 'MD4';
|
case Algorithm of
|
||||||
caMD5 : Result := 'MD5';
|
caExcel : Result := 'EXCEL';
|
||||||
caRIPEMD128 : Result := 'RIPEMD-128';
|
caMD2 : Result := 'MD2';
|
||||||
caRIPEMD160 : Result := 'RIPEMD-160';
|
caMD4 : Result := 'MD4';
|
||||||
caSHA1 : Result := 'SHA-1';
|
caMD5 : Result := 'MD5';
|
||||||
caSHA256 : Result := 'SHA-256';
|
caRIPEMD128 : Result := 'RIPEMD-128';
|
||||||
caSHA384 : Result := 'SHA-384';
|
caRIPEMD160 : Result := 'RIPEMD-160';
|
||||||
caSHA512 : Result := 'SHA-512';
|
caSHA1 : Result := 'SHA-1';
|
||||||
caWHIRLPOOL : Result := 'WHIRLPOOL';
|
caSHA256 : Result := 'SHA-256';
|
||||||
else Result := '';
|
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;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -56,22 +70,35 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{@@ This is the code for generating Excel 2010 and earlier password's hash }
|
{@@ This is the code for generating Excel 2010 and earlier password's hash
|
||||||
function ExcelPasswordHash(const APassword: string): string;
|
See: http://forum.lazarus.freepascal.org/index.php/topic,36075.msg240132.html#msg240132 }
|
||||||
const
|
function ExcelPasswordHash( const APassword: string ): string;
|
||||||
Key = $CE4B;
|
|
||||||
var
|
var
|
||||||
i: Integer;
|
i: Integer;
|
||||||
HashValue: Word = 0;
|
PassLen: Integer;
|
||||||
|
Password: string;
|
||||||
|
PassHash: Word = 0;
|
||||||
begin
|
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
|
begin
|
||||||
HashValue := ord(APassword[i]) xor HashValue;
|
Result := '';
|
||||||
HashValue := HashValue shl 1;
|
exit;
|
||||||
end;
|
end;
|
||||||
HashValue := HashValue xor Length(APassword) xor Key;
|
|
||||||
|
for i:= PassLen downto 1 do
|
||||||
Result := IntToHex(HashValue, 4);
|
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;
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
@ -3435,7 +3435,7 @@ begin
|
|||||||
s := s + ' hashValue="' + AWorksheet.CryptoInfo.PasswordHash + '"';
|
s := s + ' hashValue="' + AWorksheet.CryptoInfo.PasswordHash + '"';
|
||||||
|
|
||||||
if AWorksheet.CryptoInfo.Algorithm <> caUnknown then
|
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
|
if AWorksheet.CryptoInfo.SaltValue <> '' then
|
||||||
s := s + ' saltValue="' + AWorksheet.CryptoInfo.SaltValue + '"';
|
s := s + ' saltValue="' + AWorksheet.CryptoInfo.SaltValue + '"';
|
||||||
@ -4676,7 +4676,7 @@ begin
|
|||||||
begin
|
begin
|
||||||
s:= s + ' workbookHashVal="' + Workbook.CryptoInfo.PasswordHash + '"';
|
s:= s + ' workbookHashVal="' + Workbook.CryptoInfo.PasswordHash + '"';
|
||||||
if Workbook.CryptoInfo.Algorithm <> caUnknown then
|
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
|
if Workbook.CryptoInfo.SaltValue <> '' then
|
||||||
s:= s + ' workbookSaltValue="' + Workbook.CryptoInfo.SaltValue + '"';
|
s:= s + ' workbookSaltValue="' + Workbook.CryptoInfo.SaltValue + '"';
|
||||||
|
@ -3654,7 +3654,7 @@ begin
|
|||||||
if (ienCryptoInfo in FExpanded) then begin
|
if (ienCryptoInfo in FExpanded) then begin
|
||||||
AStrings.Add('(-) CryptoInfo=');
|
AStrings.Add('(-) CryptoInfo=');
|
||||||
AStrings.Add(Format(' PasswordHash=%s', [Workbook.CryptoInfo.PasswordHash]));
|
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(' SaltValue=%s', [Workbook.CryptoInfo.SaltValue]));
|
||||||
AStrings.Add(Format(' SpinCount=%d', [Workbook.CryptoInfo.SpinCount]));
|
AStrings.Add(Format(' SpinCount=%d', [Workbook.CryptoInfo.SpinCount]));
|
||||||
end else
|
end else
|
||||||
@ -3837,7 +3837,7 @@ begin
|
|||||||
if (ienCryptoInfo in FExpanded) then begin
|
if (ienCryptoInfo in FExpanded) then begin
|
||||||
AStrings.Add('(-) CryptoInfo=');
|
AStrings.Add('(-) CryptoInfo=');
|
||||||
AStrings.Add(Format(' PasswordHash=%s', [Worksheet.CryptoInfo.PasswordHash]));
|
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(' SaltValue=%s', [Worksheet.CryptoInfo.SaltValue]));
|
||||||
AStrings.Add(Format(' SpinCount=%d', [Worksheet.CryptoInfo.SpinCount]));
|
AStrings.Add(Format(' SpinCount=%d', [Worksheet.CryptoInfo.SpinCount]));
|
||||||
end else
|
end else
|
||||||
|
Loading…
Reference in New Issue
Block a user