ntlm 的 delphi for smtp

 

Code
unit NtlmMsgs;

interface

uses
  SysUtils, Encryption;

type
  TNTLM_Message1 
= record
    Protocol: 
array [0..7of Byte;
    MsgType: Char;
    Zero1: 
array [0..2of Byte;
    Flags: Word;
    Zero2: 
array [0..1of Byte;
    LenDomain1: Word;
    LenDomain2: Word;
    OffSetDomain: Word;
    Zero3: 
array [0..1of Byte;
    LenHost1: Word;
    LenHost2: Word;
    OffSetHost: Word;
    Zero4: 
array [0..1of Byte;
  
end;

  TNTLM_Message2 
= record
    Protocol: 
array [0..7of Byte;
    MsgType: Char;
    Zero1: 
array [0..6of Byte;
    LenMessage: Word;
    Zero2: 
array [0..1of Byte;
    Flags: Word;
    Zero3: 
array [0..1of Byte;
    Nonce: 
array [0..7of Byte;
    Zero4: 
array [0..7of Byte;
  
end;

  TNTLM_Message3 
= record
    Protocol: 
array [0..7of Byte;
    MsgType: Char;
    Zero1: 
array [0..2of Byte;
    Len_LM_Resp1: Word;
    Len_LM_Resp2: Word;
    OffSet_LM_Resp: Word;
    Zero2: 
array [0..1of Byte;
    Len_NT_Resp1: Word;
    Len_NT_Resp2: Word;
    OffSet_NT_Resp: Word;
    Zero3: 
array [0..1of Byte;
    LenDomain1: Word;
    LenDomain2: Word;
    OffSetDomain: Word;
    Zero4: 
array [0..1of Byte;
    LenUser1: Word;
    LenUser2: Word;
    OffSetUser: Word;
    Zero5: 
array [0..1of Byte;
    LenHost1: Word;
    LenHost2: Word;
    OffSetHost: Word;
    Zero6: 
array [0..5of Byte;
    LenMessage: Word;
    Zero7: 
array [0..1of Byte;
    Flags: Word;
    Zero8: 
array [0..1of Byte;
  
end;

type
  INTLM 
= interface
    [
'{E184F5EF-CB02-11D6-A883-0002B30B8C0F}']
    
function GetMensaje1( AHost, ADomain: String ): String;
    
function GetMensaje2( AServerReply: String ): TNTLM_Message2;
    
function GetMensaje3( ADomain, AHost, AUser, APassword: String; ANonce: Array of Byte ): String;
  
end;

  TNTLM 
= class( TInterfacedObject, INTLM )
    
private
      
{ Public declarations }
      
function GetLMHash( APassword: String; ANonce: Array of Byte ): String;
      
function GetNTHash( APassword: String; ANonce: Array of Byte ): String;
      
function Unicode( AData: String ): String;
    
public
      
{ Public declarations }
      
function GetMensaje1( AHost, ADomain: String ): String;
      
function GetMensaje2( AServerReply: String ): TNTLM_Message2;

      
function ReverseMessage1(AString: string): TNTLM_Message1;
      
function GetMensaje3( ADomain, AHost, AUser, APassword: String; ANonce: Array of Byte ): String;
  
end;

implementation

{ TNTLM }
function TNTLM.GetMensaje1(AHost, ADomain: String): String;
var
  Msg: TNTLM_Message1;
  MessageAux: String;
  Encryption: IEncryption;
begin

  Encryption :
= TEncryption.Create;
  AHost :
= UpperCase( AHost );
  ADomain :
= UpperCase( ADomain );
  
with Msg do
  
begin
    FillChar( Msg, sizeof( Msg ), #
0 );
    Move( 
'NTLMSSP' + #0, Protocol, 8 );
    MsgType :
= #1;
    
//Flags := 45571;
    
//Flags := 33287;
    Flags :
= 519;
    
//Zero2 := 
    LenHost1 :
= Length( AHost );
    LenHost2 :
= LenHost1;
    
//OffSetHost := $20;
    OffSetHost :
= 0;
    LenDomain1 :
= Length( ADomain );
    LenDomain2 :
= LenDomain1;
    OffSetDomain :
= OffSetHost + LenHost1;

    
{new method}


    
  
end;
  SetLength( MessageAux, sizeof( Msg ) );
  Move( Msg, MessageAux[
1], sizeof( Msg ) );
  MessageAux :
= MessageAux + AHost + ADomain;

  Result :
= Encryption.StrToBase64( MessageAux );
end;

function TNTLM.GetMensaje2(AServerReply: String): TNTLM_Message2;
var
  Msg: TNTLM_Message2;
  NTLMReply: String;
  Encryption: IEncryption;
begin
  Encryption :
= TEncryption.Create;
  NTLMReply :
= Encryption.Base64toStr( AServerReply );
  Move( NTLMReply[
1], Msg, sizeof( Msg ) );
  Result :
= Msg;
end;

function TNTLM.GetMensaje3(ADomain, AHost, AUser,
  APassword: String; ANonce: Array 
of Byte): String;
var
  Msg: TNTLM_Message3;
  MessageAux: String;
  LM_Resp: String[
30];
  NT_Resp: String[
30];
  Encryption: IEncryption;
begin
  Encryption :
= TEncryption.Create;
  ADomain :
= Unicode( UpperCase( ADomain ) );
  AHost :
= Unicode( UpperCase( AHost ) );
  AUser :
= Unicode( AUser );

  FillChar( Msg, Sizeof( Msg ), #
0 );
  
with Msg do
  
begin
    Move( 
'NTLMSSP' + #0, Protocol, 8 );
    MsgType :
= #3;
    LenDomain1 :
= Length( ADomain );
    LenDomain2 :
= LenDomain1;
    OffSetDomain :
= $40;
    LenUser1 :
= Length( AUser );
    LenUser2 :
= LenUser1;
    OffSetUser :
= OffSetDomain + LenDomain1;
    LenHost1 :
= Length( AHost );
    LenHost2 :
= LenHost1;
    OffSetHost :
= OffsetUser + LenUser1;
    Len_LM_Resp1 :
= $18;
    Len_LM_Resp2 :
= Len_LM_Resp1;
    OffSet_LM_Resp :
= OffsetHost + LenHost1;
    Len_NT_Resp1 :
= $18;
    Len_NT_Resp2 :
= Len_NT_Resp1;
    OffSet_NT_Resp :
= OffSet_LM_Resp + Len_LM_Resp1;
    LenMessage :
= Offset_NT_Resp + Len_NT_Resp1;
    Flags :
= 33281;
  
end;
  LM_Resp :
= GetLMHash( APassword, ANonce );
  NT_Resp :
= GetNTHash( APassword, ANonce );
  SetLength( MessageAux, sizeof( Msg ) );
  Move( Msg, MessageAux[
1], sizeof( Msg ) );
  MessageAux :
= MessageAux + ADomain + AUser + AHost + LM_Resp + NT_Resp;
  Result :
= Encryption.StrToBase64( MessageAux );
end;

function TNTLM.GetLMHash(APassword: String; ANonce: Array of Byte): String;
const
  magic: 
array [0..7of Byte = ($4B, $47, $53, $21, $40, $23, $24, $25 );
var
  i: Integer;
  Encryption: IEncryption;
  PassHash: String;
begin
  Encryption :
= TEncryption.Create;
  APassword :
= UpperCase( APassword );
  
if Length( APassword ) >= 14 then
    SetLength( APassword, 
14 )
  
else
    
for i := Length( APassword ) to 14 do
      APassword :
= APassword + #0;

  PassHash :
= '';
  PassHash :
= Encryption.DesEcbEncrypt( Copy( APassword, 17 ), magic );
  PassHash :
= PassHash + Encryption.DesEcbEncrypt( Copy( APassword, 87 ), magic );
  PassHash :
= PassHash + #0#0#0#0#0;

  Result :
= Encryption.DesEcbEncrypt( Copy( PassHash, 17 ), ANonce );
  Result :
= Result + Encryption.DesEcbEncrypt( Copy( PassHash, 87 ), ANonce );
  Result :
= Result + Encryption.DesEcbEncrypt( Copy( PassHash, 157 ), ANonce );
end;

function TNTLM.GetNTHash(APassword: String; ANonce: Array of byte): String;
var
  Pass: String;
  PassHash: String;
  Context: PMD4Ctx;
  Encryption: IEncryption;
begin
  Encryption :
= TEncryption.Create;

  Pass :
= Unicode( APassword );
  
with Encryption do
  
begin
    GetMem( Context, SizeOf( TMD4Ctx ) );
    MDInit( Context );
    MDUpdate( Context, PChar(Pass), Length( Pass ) );
    PassHash :
= MDFinal( Context );
    PassHash :
= PassHash + #0#0#0#0#0;
    FreeMem(Context, SizeOf(TMD4Ctx));

    Result :
= Encryption.DesEcbEncrypt( Copy( PassHash, 17 ), ANonce );
    Result :
= Result + Encryption.DesEcbEncrypt( Copy( PassHash, 87 ), ANonce );
    Result :
= Result + Encryption.DesEcbEncrypt( Copy( PassHash, 157 ), ANonce );
  
end;
end;

function TNTLM.Unicode(AData: String): String;
var
  Data: String;
  i: Integer;
begin
  Data :
= '';
  
for i := 1 to Length( AData ) do
    Data :
= Data + AData[i] + #0;
  Result :
= Data;
end;

function TNTLM.ReverseMessage1(AString: string): TNTLM_Message1;
var
  Msg: TNTLM_Message1;
  NTLMReply: String;
  Encryption: IEncryption;
begin
  Encryption :
= TEncryption.Create;
  NTLMReply :
= Encryption.Base64toStr( AString );
  Move( NTLMReply[
1], Msg, sizeof( Msg ) );
  Result :
= Msg;

end;

end.

 

 

 

Code
unit Encryption;

interface

uses
  SysUtils, Math;
type
  PMD4Ctx 
= ^TMD4Ctx;
  TMD4Ctx 
= record
    state: 
array[0..3of LongWord;
    count: 
array[0..1of LongWord;
    buffer: 
array[0..63of Byte;
  
end;

  PByteArray 
= ^TByteArray;
  TByteArray 
= array[0..0of Byte;
  PDWordArray 
= ^TDWordArray;
  TDWordArray 
= array[0..0of LongWord;

  IEncryption 
= Interface
    [
'{3B5BA6D3-CC96-11D6-A883-0002B30B8C0F}']
    
procedure MDInit(context: PMD4Ctx);
    
procedure MDUpdate(context: PMD4Ctx; input: Pointer; inputLen: LongWord);
    
function MDFinal(context: PMD4Ctx): String;
    
function StrToBase64( const Buffer: String ): String;
    
function Base64ToStr( const Buffer: String ): String;
    
function DesEcbEncrypt( AKey: String; AData: Array of byte ): String;
  
end;

  TEncryption 
= Class( TInterfacedObject, IEncryption )
  
private
    FRoundKeys : Array [
1..161..48of Byte;
    FC: Array [
1..28of Byte;
    FD: Array [
1..28of Byte;
    FInputValue  : Array [
1..64of Byte;
    FOutputValue : Array [
1..64of Byte;
    FL, FR, FfunctionResult : Array [
1..32of Byte;
    FKey: String;
    FSmallBuffer: Array[
0..63of BYTE;

    
procedure MD4Transform (var state: array of LongWord; block: Pointer);
    
procedure MDEncode(output, input: Pointer; len: LongWord);
    
procedure MDDecode(output, input: Pointer; len: LongWord);
    
procedure FF(var a: LongWord; b, c, d, x, s: LongWord);
    
procedure GG(var a: LongWord; b, c, d, x, s: LongWord);
    
procedure HH(var a: LongWord; b, c, d, x, s: LongWord);
    
procedure DF( var FK );
    
procedure SetBit( var Data; Index, Value: Byte );
    
function GetBit( var Data; Index : Byte ): Byte;
    
procedure Shift( var SubKeyPart );
    
procedure SubKey( Round : Byte; var SubKey );
    
procedure SetKeys;
    
procedure EncipherBLOCK;
  
public
    
function StrToBase64( const Buffer: String ): String;
    
function Base64ToStr( const Buffer: String ): String;
    
procedure MDInit(context: PMD4Ctx);
    
procedure MDUpdate(context: PMD4Ctx; input: Pointer; inputLen: LongWord);
    
function MDFinal(context: PMD4Ctx): String;
    
function DesEcbEncrypt( AKey: String; AData: Array of byte ): String;
  
end;

implementation
const
  IP : Array [
1..64of Byte =58,50,42,34,26,18,10,2,
                                
60,52,44,36,28,20,12,4,
                                
62,54,46,38,30,22,14,6,
                                
64,56,48,40,32,24,16,8,
                                
57,49,41,33,25,179,1,
                                
59,51,43,35,27,19,11,3,
                                
61,53,45,37,29,21,13,5,
                                
63,55,47,39,31,23,15,7);
  InvIP : Array [
1..64of Byte =408,48,16,56,24,64,32,
                                   
397,47,15,55,23,63,31,
                                   
386,46,14,54,22,62,30,
                                   
375,45,13,53,21,61,29,
                                   
364,44,12,52,20,60,28,
                                   
353,43,11,51,19,59,27,
                                   
342,42,10,50,18,58,26,
                                   
331,419,49,17,57,25);
  E : Array [
1..48of Byte =3212345,
                                
456789,
                                
89,10,11,12,13,
                               
12,13,14,15,16,17,
                               
16,17,18,19,20,21,
                               
20,21,22,23,24,25,
                               
24,25,26,27,28,29,
                               
28,29,30,31,321);
  P : Array [
1..32of Byte =167,20,21,
                               
29,12,28,17,
                                
1,15,23,26,
                                
5,18,31,10,
                                
28,24,14,
                               
32,2739,
                               
19,13,306,
                               
22,114,25);
  SBoxes : Array [
1..8,0..3,0..15of Byte =
          ( ((
144,1312,15,1183,106,125907),
            (  
0,1574,142,131,106,12,119538),
            (  
41,148,1362,11,15,12973,1050),
            ( 
15,128249175,113,14,1006,13)),

            ((
1518,146,1134972,13,1205,10),
            (  
3,1347,1528,14,1201,1069,115),
            (  
0,147,11,104,13158,126932,15),
            ( 
138,1013,1542,1167,1205,149)),

            ((
1009,1463,1551,13,127,11428),
            ( 
13709346,10285,14,12,11,151),
            ( 
136498,1530,1112,125,10,147),
            (  
1,10,13069874,15,143,1152,12)),

            (( 
7,13,143069,101285,11,124,15),
            ( 
138,1156,1503472,121,10,149),
            ( 
10690,12,117,13,1513,145284),
            (  
3,1506,101,138945,11,1272,14)),

            (( 
2,12417,10,116853,15,130,149),
            ( 
14,112,1247,13150,15,103986),
            (  
421,11,10,1378,159,125630,14),
            ( 
118,1271,142,136,1509,10453)),

            ((
121,10,1592680,1334,1475,11),
            ( 
10,15427,129561,13,140,1138),
            (  
9,14,15528,123704,101,13,116),
            (  
432,1295,15,10,11,1417608,13)),

            (( 
4,112,14,1508,133,12975,1061),
            ( 
130,117491,10,1435,122,1586),
            (  
14,11,13,1237,14,10,15680592),
            (  
6,11,13814,107950,15,1423,12)),

            ((
132846,15,111,1093,1450,127),
            (  
1,15,138,10374,1256,110,1492),
            (  
7,11419,12,14206,10,13,15358),
            (  
21,1474,108,13,15,1290356,11)));

  PC_
1 : Array [1..56of Byte =57,49,41,33,25,179,
                                   
1,58,50,42,34,26,18,
                                  
102,59,51,43,35,27,
                                  
19,113,60,52,44,36,
                                  
63,55,47,39,31,23,15,
                                   
7,62,54,46,38,30,22,
                                  
146,61,53,45,37,29,
                                  
21,135,28,20,124);

  PC_
2 : Array [1..48of Byte =14,17,11,2415,
                                   
3,28,156,21,10,
                                  
23,19,124,268,
                                  
167,27,20,132,
                                  
41,52,31,37,47,55,
                                  
30,40,51,45,33,48,
                                  
44,49,39,56,34,53,
                                  
46,42,50,36,29,32);

  ShiftTable : Array [
1..16of Byte =1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1);

  PI_SUBST: 
array[0..255of Byte = (
    
41466720116221612416154841612362406,
    
1998167524319219911514015214743217188,
    
76130202301558760253212224221036611124,
    
13823229181907819621421815822273160251,
    
2451421874723812216910412114521178763,
    
1481941613711349533128127931549014450,
    
3953622042311912471513255254817972165,
    
1812092159414642172861701987918456210,
    
150164125182118252107226156116424169157,
    
11289100113135321349120710123045168227,
    
9637173174176185246287097105526412615,
    
857116335221811755819592249206186197,
    
2343844831311013340132921122320524465,
    
12977821062205520010819317125036225123,
    
8121891777412013614913922799232109233,
    
20321325459029572422391831410288208228,
    
1661191142482351177510496880180143237,
    
3126219153141511591713120
  );

const
  MD_PADDING: 
array[0..63of Byte = (
    $
8000000000000000000000,
    
0000000000000000000000,
    
000000000000000000000
  );

  S11 
= 3;
  S12 
= 7;
  S13 
= 11;
  S14 
= 19;
  S21 
= 3;
  S22 
= 5;
  S23 
= 9;
  S24 
= 13;
  S31 
= 3;
  S32 
= 9;
  S33 
= 11;
  S34 
= 15;

function rol(x: LongWord; y: Byte): LongWord; assembler;
asm
  mov   cl,dl
  rol   eax,cl
end;

function F(x, y, z: LongWord): LongWord; assembler;
asm
  
and   edx,eax
  
not   eax
  
and   eax,ecx
  
or    eax,edx
end;

function G(x, y, z: LongWord): LongWord; assembler;
asm
  push  ecx
  
and   ecx,eax
  
and   eax,edx
  
or    eax,ecx
  pop   ecx
  
and   edx,ecx
  
or    eax,edx
end;

function H(x, y, z: LongWord): LongWord; assembler;
asm
  
xor eax,edx
  
xor eax,ecx
end;

function TEncryption.StrToBase64(const Buffer: String): String;
const
    Codes 
= 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
var
    iRest, iLen, iQuad: Integer;
    Byte3: 
array[0..2of Byte;
    sBuffer: String;
begin
    Result :
= '';
    SetLength( sBuffer, 
4 * ( ( Length( Buffer ) + 2 ) div 3 ) );
    FillChar( sBuffer[
1], Length( sBuffer ), 0 );

    iQuad :
= 0;
    iLen :
= Length(Buffer);
    iRest :
= iLen;

    
while iRest > 0 do
    
begin
        Move(Buffer[iLen 
- iRest + 1], Byte3, Trunc(Min(3, iRest)));
        sBuffer[iQuad 
+ 1] := Codes[(Byte3[0div 4+ 1];

        
if iRest > 1 then
        
begin
            sBuffer[iQuad 
+ 2] := Codes[(Byte3[0mod 4* 16 + (Byte3[1div 16+ 1];
            
if iRest > 2 then
            
begin
                sBuffer[iQuad 
+ 3] := Codes[(Byte3[1mod 16* 4 + (Byte3[2div 64+ 1];
                sBuffer[iQuad 
+ 4] := Codes[Byte3[2mod 64 + 1];
            
end else
            
begin
                sBuffer[iQuad 
+ 3] := Codes[(Byte3[1mod 16* 4 + 1];
                sBuffer[iQuad 
+ 4] := '=';
            
end;
        
end else
        
begin
            sBuffer[iQuad 
+ 2] := Codes[(Byte3[0mod 4* 16 + 1];
            sBuffer[iQuad 
+ 3] := '=';
            sBuffer[iQuad 
+ 4] := '=';
        
end;

        Inc(iQuad, 
4);
        Dec(iRest, 
3);
    
end;

    Result :
= Trim(sBuffer);
end;

function TEncryption.Base64ToStr(const Buffer: String): String;
var
    i, iCount, iIdx, iLen, iBuild: Integer;
  EndReached: Boolean;
  Ptr: PChar;
begin
    Result :
= '';

  SetLength( Result, 
3 * ( Length( Buffer ) + 3 ) div 4 );
    iIdx :
= 0;
  iLen :
= 0;
  iBuild :
= 0;
  iCount :
= 3;
  EndReached :
= false;
  Ptr :
= @Result[ 1 ];

    
for i := 1 to Length(Buffer) do
    
begin
        Inc(iIdx);

        
case Buffer[i] of
            
'A'..'Z': iBuild := ( iBuild shl 6 ) + Ord(Buffer[i]) - 65;
            
'a'..'z': iBuild := ( iBuild shl 6 ) + Ord(Buffer[i]) - 71;
            
'0'..'9': iBuild := ( iBuild shl 6 ) + Ord(Buffer[i]) + 4;
            
'+':             iBuild := ( iBuild shl 6 ) + 62;
            
'/':             iBuild := ( iBuild shl 6 ) + 63;
            
'=':
        
begin
          
if not EndReached then
            
case iIdx of
            
1: iCount := 0;
            
2: iCount := 0;
            
3: iCount := 1;
            
4: iCount := 2;
            
end;
          EndReached :
= true;
        
end;
        
end;

        
if iIdx = 4 then
        
begin
      Ptr[ 
0 ] := Char( iBuild shr 16 );
      Ptr[ 
1 ] := Char( ( iBuild shr 8 ) and $FF );
      Ptr[ 
2 ] := Char( iBuild and $FF );
      Inc( Ptr, 
3 );

      Inc( iLen, iCount );
      iCount :
= 3;
      iBuild :
= 0;
            iIdx :
= 0;
      EndReached :
= false;
        
end;
    
end;

  
if ( iLen <> Length(Result) ) then
    SetLength(Result, iLen);
end;

procedure TEncryption.FF(var a: LongWord; b, c, d, x, s: LongWord);
begin
  a :
= a + (F(b, c, d) + x);
  a :
= rol(a, s);
end;

procedure TEncryption.GG(var a: LongWord; b, c, d, x, s: LongWord);
begin
  a :
= a + G(b, c, d) + x + $5a827999;
  a :
= rol(a, s);
end;

procedure TEncryption.HH(var a: LongWord; b, c, d, x, s: LongWord);
begin
  a :
= a + H(b, c, d) + x + $6ed9eba1;
  a :
= rol(a, s);
end;

procedure TEncryption.MDInit(context: PMD4Ctx);
begin
  context^.count[
0] := 0;
  context^.count[
1] := 0;
  context^.state[
0] := $67452301;
  context^.state[
1] := $efcdab89;
  context^.state[
2] := $98badcfe;
  context^.state[
3] := $10325476;
end;

procedure TEncryption.MDEncode(output, input: Pointer; len: LongWord);
var
  i, j: LongWord;
begin
  i :
= 0; j := 0;
  
while j < len do
  
begin
    PByteArray(output)^[j] :
= (PDWordArray(input)^[i] and $ff);
    PByteArray(output)^[j 
+ 1] := ((PDWordArray(input)^[i] shr 8and $ff);
    PByteArray(output)^[j 
+ 2] := ((PDWordArray(input)^[i] shr 16and $ff);
    PByteArray(output)^[j 
+ 3] := ((PDWordArray(input)^[i] shr 24and $ff);
    Inc(i); Inc(j, 
4);
  
end;
end;

procedure TEncryption.MDDecode(output, input: Pointer; len: LongWord);
var
  i, j: LongWord;
begin
  i :
= 0; j := 0;
  
while j < len do
  
begin
    PDWordArray(output)^[i] :
= PByteArray(input)^[j] or (PByteArray(input)^[j + 1shl 8or (PByteArray(input)^[j + 2shl 16or (PByteArray(input)^[j + 3shl 24);
    Inc(i); Inc(j, 
4);
  
end;
end;

procedure TEncryption.MD4Transform (var state: array of LongWord; block: Pointer);
var
  a, b, c, d: LongWord;
  x: 
array[0..15of LongWord;
begin
  a :
= state[0]; b := state[1]; c := state[2]; d := state[3];
  MDDecode(@x, block, 
64);

  FF (a, b, c, d, x[ 
0], S11);
  FF (d, a, b, c, x[ 
1], S12);
  FF (c, d, a, b, x[ 
2], S13);
  FF (b, c, d, a, x[ 
3], S14);
  FF (a, b, c, d, x[ 
4], S11);
  FF (d, a, b, c, x[ 
5], S12);
  FF (c, d, a, b, x[ 
6], S13);
  FF (b, c, d, a, x[ 
7], S14);
  FF (a, b, c, d, x[ 
8], S11);
  FF (d, a, b, c, x[ 
9], S12);
  FF (c, d, a, b, x[
10], S13);
  FF (b, c, d, a, x[
11], S14);
  FF (a, b, c, d, x[
12], S11);
  FF (d, a, b, c, x[
13], S12);
  FF (c, d, a, b, x[
14], S13);
  FF (b, c, d, a, x[
15], S14);

  GG (a, b, c, d, x[ 
0], S21);
  GG (d, a, b, c, x[ 
4], S22);
  GG (c, d, a, b, x[ 
8], S23);
  GG (b, c, d, a, x[
12], S24);
  GG (a, b, c, d, x[ 
1], S21);
  GG (d, a, b, c, x[ 
5], S22);
  GG (c, d, a, b, x[ 
9], S23);
  GG (b, c, d, a, x[
13], S24);
  GG (a, b, c, d, x[ 
2], S21);
  GG (d, a, b, c, x[ 
6], S22);
  GG (c, d, a, b, x[
10], S23);
  GG (b, c, d, a, x[
14], S24);
  GG (a, b, c, d, x[ 
3], S21);
  GG (d, a, b, c, x[ 
7], S22);
  GG (c, d, a, b, x[
11], S23);
  GG (b, c, d, a, x[
15], S24);

  HH (a, b, c, d, x[ 
0], S31);
  HH (d, a, b, c, x[ 
8], S32);
  HH (c, d, a, b, x[ 
4], S33);
  HH (b, c, d, a, x[
12], S34);
  HH (a, b, c, d, x[ 
2], S31);
  HH (d, a, b, c, x[
10], S32);
  HH (c, d, a, b, x[ 
6], S33);
  HH (b, c, d, a, x[
14], S34);
  HH (a, b, c, d, x[ 
1], S31);
  HH (d, a, b, c, x[ 
9], S32);
  HH (c, d, a, b, x[ 
5], S33);
  HH (b, c, d, a, x[
13], S34);
  HH (a, b, c, d, x[ 
3], S31);
  HH (d, a, b, c, x[
11], S32);
  HH (c, d, a, b, x[ 
7], S33);
  HH (b, c, d, a, x[
15], S34);

  state[
0] := state[0+ a;
  state[
1] := state[1+ b;
  state[
2] := state[2+ c;
  state[
3] := state[3+ d;
end;

procedure TEncryption.MDUpdate(context: PMD4Ctx; input: Pointer; inputLen: LongWord);
var
  i, index, partLen: LongWord;
begin
  index :
= (context^.count[0shr 3and $3F;

  context^.count[
0] := context^.count[0+ inputLen shl 3;
  
if (context^.count[0< (inputLen shl 3)) then
    Inc(context^.count[
1]);

  context^.count[
1] := context^.count[1+ inputLen shr 29;
  partLen :
= 64 - index;

  
if (inputLen >= partLen) then
  
begin
    Move(input^, context^.buffer[index], partLen);
    MD4Transform(context^.state, @context^.buffer);
    i :
= partLen;
    
while i + 63 < inputLen do
    
begin
      MD4Transform(context^.state, Addr(PByteArray(input)^[i]));
      Inc(i, 
64);
    
end;
    index :
= 0;
  
end
  
else
    i :
= 0;
  Move(PByteArray(input)^[i], context^.buffer[index], inputLen 
- i);
end;

function TEncryption.MDFinal(context: PMD4Ctx): String;
var
  digest: 
array[0..15of Char;
  bits: 
array[0..7of Char;
  index, padLen: LongWord;
begin
  MDEncode(@bits, @context^.count, 
8);

  index :
= (context^.count[0shr 3and $3f;
  
if (index < 56then
    padLen :
= 56 - index
  
else
    padLen :
= 120 - index;

  MDUpdate(context, @MD_PADDING, padLen);

  MDUpdate(context, @bits, 
8);
  MDEncode(@digest, @context^.state, 
16);

  FillChar(context^, 
0, SizeOf(TMD4Ctx));

  Result :
= Digest;
end;

function TEncryption.GetBit(var Data; Index: Byte): Byte;
var
  Bits: Array [
0..7of Byte absolute Data;
begin
  Dec( Index );
  
if Bits[Index div 8and ( 128 shr( Index mod 8 ) ) > 0 then
    GetBit :
= 1
  
else
    GetBit :
= 0;
end;

procedure TEncryption.SetBit( var Data; Index, Value : Byte );
var
  Bits: Array [
0..7] Of Byte absolute Data;
  Bit: Byte;
begin
  Dec( Index );
  Bit :
= 128 shr( Index mod 8 );
  
case Value of
    
0: Bits[Index div 8] := Bits[Index div 8and ( not Bit );
    
1: Bits[Index div 8] := Bits[Index div 8or Bit;
  
end;
end;

procedure TEncryption.DF( var FK );
var
  K : Array [
1..48] Of Byte absolute FK;
  Temp1 : Array [
1..48] Of Byte;
  Temp2 : Array [
1..32] Of Byte;
  n, h, i, j, Row, Column : Integer;
begin
  
for n:=1 to 48 do
    Temp1[n]:
=FR[E[n]] xor K[n];
  
for n:=1 to 8 do
  
begin
    i :
= ( n - 1 ) * 6;
    j :
= ( n -1 ) * 4;
    Row :
= Temp1[i+1* 2 + Temp1[i+6];
    Column :
= Temp1[i+2* 8 + Temp1[i+3* 4 + Temp1[i+4* 2 + Temp1[i+5];
    
for h := 1 to 4 Do
    
begin
      
case h of
        
1: Temp2[j+h] := ( SBoxes[n,Row,Column] and 8 ) div 8;
        
2: Temp2[j+h] := ( SBoxes[n,Row,Column] and 4 ) div 4;
        
3: Temp2[j+h] := ( SBoxes[n,Row,Column] and 2 ) div 2;
        
4: Temp2[j+h] := ( SBoxes[n,Row,Column] and 1 );
      
end;
    
end;
  
end;
  
for n := 1 to 32 do
    FfunctionResult[n] :
= Temp2[P[n]];
end;

procedure TEncryption.Shift( var SubKeyPart );
var
  SKP: Array [
1..28] Of Byte absolute SubKeyPart;
  n, b: Byte;
begin
  b :
= SKP[1];
  
for n := 1 to 27 do
    SKP[n] :
= SKP[n+1];
  SKP[
28] := b;
end;

procedure TEncryption.SubKey( Round: Byte; var SubKey );
var
  SK : Array [
1..48of Byte absolute SubKey;
  n, b : Byte;
begin
  
for n := 1 to ShiftTable[Round] do
  
begin
    Shift( FC );
    Shift( FD );
  
end;
  
for n := 1 to 48 do
  
begin
    b :
= PC_2[n];
    
if b <= 28 then
      SK[n] :
= FC[b]
    
else
      SK[n] :
= FD[b-28];
  
end;
end;

procedure TEncryption.SetKeys;
var
 n: Byte;
 Key: Array [
0..7of Byte;
begin
  move( FKey[
1], Key, 8 );
  
for n := 1 to 28 do
  
begin
    FC[n] :
= GetBit( Key, PC_1[n] );
    FD[n] :
= GetBit( Key, PC_1[n+28] );
  
end;
  
for n := 1 to 16 do
    SubKey( n,FRoundKeys[n] );
end;

procedure TEncryption.EncipherBlock;
var
  n, b, Round : Byte;
begin
  
for n := 1 to 64 do
    FInputValue[n]:
=GetBit( FSmallBuffer, n );
  
for n := 1 to 64 do
    
if n <= 32 then
      FL[n] :
= FInputValue[IP[n]]
    
else
      FR[n
-32] := FInputValue[IP[n]];
  
for Round := 1 to 16 do
  
begin
    DF( FRoundKeys[Round] );
    For n :
= 1 to 32 do
      FfunctionResult[n] :
= FfunctionResult[n] xor FL[n];
    FL :
= FR;
    FR :
= FfunctionResult;
  
end;
  
for n := 1 to 64 do
  
begin
    b :
= InvIP[n];
    
if b <= 32 then
      FOutputValue[n] :
= FR[b]
    
else
      FOutputValue[n] :
= FL[b-32];
  
end;
  
for n := 1 to 64 do
    SetBit( FSmallBuffer, n, FOutputValue[n] );
end;

function TEncryption.DesEcbEncrypt(AKey: String; AData: Array of byte): String;
var
  i, j, t, bit: Integer;
begin
  SetLength( FKey, 
8 );
  FKey[
1] := AKey[1];
  FKey[
2] := char( ( ( Byte( AKey[1] ) shl 7 ) and $FF ) or ( Byte( AKey[2] ) shr 1 ) );
  FKey[
3] := char( ( ( Byte( AKey[2] ) shl 6 ) and $FF ) or ( Byte( AKey[3] ) shr 2 ) );
  FKey[
4] := char( ( ( Byte( AKey[3] ) shl 5 ) and $FF ) or ( Byte( AKey[4] ) shr 3 ) );
  FKey[
5] := char( ( ( Byte( AKey[4] ) shl 4 ) and $FF ) or ( Byte( AKey[5] ) shr 4 ) );
  FKey[
6] := char( ( ( Byte( AKey[5] ) shl 3 ) and $FF ) or ( Byte( AKey[6] ) shr 5 ) );
  FKey[
7] := char( ( ( Byte( AKey[6] ) shl 2 ) and $FF ) or ( Byte( AKey[7] ) shr 6 ) );
  FKey[
8] := char( ( ( Byte( AKey[7] ) shl 1 ) and $FF ) );

  
for i := 1 to 8 do
  
begin
    
for j := 1 to 7 do
    
begin
      bit :
= 0;
      t :
= Byte( Fkey[i] ) shl j;
      bit :
=( t xor bit) and $1;
    
end;
    Fkey[i] :
= char( ( Byte( Fkey[i] ) and $FE ) or bit );
  
end;
  SetKeys;

  SetLength( Result, 
8 );
  move( AData, FSmallBuffer, 
8 );
  EncipherBlock;
  move( FSmallBuffer, Result[
1], 8 );
end;

end.

你可能感兴趣的:(ntlm 的 delphi for smtp)