
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@5831 8e941d3f-bd1b-0410-a28a-d453659cc2b4
183 lines
5.2 KiB
ObjectPascal
183 lines
5.2 KiB
ObjectPascal
unit fpsCrypto;
|
|
|
|
interface
|
|
|
|
uses
|
|
SysUtils, fpsTypes;
|
|
|
|
type
|
|
TsAlgorithmUsage = (auExcel, auOpenDocument);
|
|
|
|
function AlgorithmToStr(Algorithm: TsCryptoAlgorithm; AUsage: TsAlgorithmUsage): String;
|
|
function StrToAlgorithm(const AName: String): TsCryptoAlgorithm;
|
|
|
|
function CrackExcelPassword(const AHash: Word): String;
|
|
function ExcelPasswordHash(const APassword: string): Word;
|
|
(*
|
|
function PasswordHash(const APassword: String; Algorithm: TsAlgorithm): String;
|
|
*)
|
|
implementation
|
|
|
|
uses
|
|
//sha1,
|
|
LazUTF8;
|
|
|
|
function AlgorithmToStr(Algorithm: TsCryptoAlgorithm; AUsage: TsAlgorithmUsage): String;
|
|
begin
|
|
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;
|
|
|
|
function StrToAlgorithm(const AName: String): TsCryptoAlgorithm;
|
|
begin
|
|
case AName of
|
|
// Excel
|
|
'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
|
|
// Libre/OpenOffice
|
|
if pos('sha1', AName) > 0 then // http://www.w3.org/2000/09/xmldsig#sha1
|
|
Result := caSHA1
|
|
else
|
|
if pos('sha256', AName) > 0 then // http://www.w3.org/2000/09/xmldsig#sha256
|
|
Result := caSHA256
|
|
else
|
|
Result := caUnknown;
|
|
end;
|
|
end;
|
|
|
|
{@@ Cracks an Excel password hash by brute force and retrieves one of many
|
|
possible passwords.
|
|
Runtime: around 1 ms.
|
|
Ref.: http://www.theofficeexperts.com/VBASamples/Excel02.htm }
|
|
function CrackExcelPassword(const AHash: Word): String;
|
|
var
|
|
i, j, k, l, m, n: char;
|
|
i1, i2, i3, i4, i5, i6: char;
|
|
begin
|
|
for i := #65 to #66 do
|
|
for j := #65 to #66 do
|
|
for k := #65 to #66 do
|
|
for l := #65 to #66 do
|
|
for m := #65 to #66 do
|
|
for i1 := #65 to #66 do
|
|
for i2 := #65 to #66 do
|
|
for i3 := #65 to #66 do
|
|
for i4 := #65 to #66 do
|
|
for i5 := #65 to #66 do
|
|
for i6 := #65 to #66 do
|
|
for n := #32 to #126 do
|
|
begin
|
|
Result := i + j + k + l + m + i1 + i2 + i3 + i4 + i5 + i6 + n;
|
|
if ExcelPasswordHash(Result) = AHash then
|
|
exit;
|
|
end;
|
|
Result := '';
|
|
end;
|
|
|
|
{@@ 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): word;
|
|
var
|
|
i: Integer;
|
|
PassLen: Integer;
|
|
Password: string;
|
|
PassHash: Word = 0;
|
|
begin
|
|
// we are needed to work with single byte character.
|
|
Password:= UTF8ToWinCP(APassword);
|
|
PassLen := Length(Password);
|
|
|
|
if PassLen = 0 then
|
|
raise Exception.Create('Password length is zero');
|
|
|
|
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 := PassHash;
|
|
end;
|
|
|
|
(*
|
|
function ExcelPasswordHash(const APassword: string): string;
|
|
var
|
|
i: Integer;
|
|
PassLen: Integer;
|
|
Password: string;
|
|
PassHash: Word = 0;
|
|
begin
|
|
// we are needed to work with single byte character.
|
|
Password:= UTF8ToWinCP(APassword);
|
|
PassLen := Length(Password);
|
|
|
|
if PassLen = 0 then
|
|
begin
|
|
Result := '';
|
|
exit;
|
|
end;
|
|
|
|
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;
|
|
*)
|
|
(*
|
|
function SHA1Hash(const AText: String): String;
|
|
var
|
|
sha1: TSHA1Digest;
|
|
begin
|
|
sha1 := SHA1String(AText);
|
|
Result := PChar(sha1);
|
|
end;
|
|
|
|
function CalcPasswordHash(const APassword: String; Algorithm: TsAlgorithm): String;
|
|
begin
|
|
case Algorithm of
|
|
caExcel: Result := ExcelPasswordHash(APassword);
|
|
caSHA1 : Result := SHA1Hash(APassword);
|
|
else raise Exception.Create('Hashing algorithm not implemented.');
|
|
end;
|
|
end; *)
|
|
|
|
end.
|