MD2 Cipher

Share your advanced PureBasic knowledge/code with the community.
infratec
Always Here
Always Here
Posts: 7576
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

MD2 Cipher

Post by infratec »

Code: Select all

;
; https://oryx-embedded.com/doc/dir_a9aab978e0be629e504b25df915d67e8.html
;
; https://www.purebasic.fr/english/viewtopic.php?t=81309

CompilerIf #PB_Compiler_IsMainFile
  EnableExplicit
CompilerEndIf

#PB_Cipher_MD2 = 12

; MD2 block size
#MD2_BLOCK_SIZE = 16
; MD2 digest size
#MD2_DIGEST_SIZE = 16
; Minimum length of the padding string
#MD2_MIN_PAD_SIZE = 1
  
  
Structure Md2Context
  StructureUnion
    x.a[48]
    digest.a[16]
  EndStructureUnion
  m.a[16]
  c.a[16]
  size.l
EndStructure
  
   
; MD2 constants
DataSection
  MD2_s:
  Data.a  $29, $2E, $43, $C9, $A2, $D8, $7C, $01, $3D, $36, $54, $A1, $EC, $F0, $06, $13
  Data.a  $62, $A7, $05, $F3, $C0, $C7, $73, $8C, $98, $93, $2B, $D9, $BC, $4C, $82, $CA
  Data.a  $1E, $9B, $57, $3C, $FD, $D4, $E0, $16, $67, $42, $6F, $18, $8A, $17, $E5, $12
  Data.a  $BE, $4E, $C4, $D6, $DA, $9E, $DE, $49, $A0, $FB, $F5, $8E, $BB, $2F, $EE, $7A
  Data.a  $A9, $68, $79, $91, $15, $B2, $07, $3F, $94, $C2, $10, $89, $0B, $22, $5F, $21
  Data.a  $80, $7F, $5D, $9A, $5A, $90, $32, $27, $35, $3E, $CC, $E7, $BF, $F7, $97, $03
  Data.a  $FF, $19, $30, $B3, $48, $A5, $B5, $D1, $D7, $5E, $92, $2A, $AC, $56, $AA, $C6
  Data.a  $4F, $B8, $38, $D2, $96, $A4, $7D, $B6, $76, $FC, $6B, $E2, $9C, $74, $04, $F1
  Data.a  $45, $9D, $70, $59, $64, $71, $87, $20, $86, $5B, $CF, $65, $E6, $2D, $A8, $02
  Data.a  $1B, $60, $25, $AD, $AE, $B0, $B9, $F6, $1C, $46, $61, $69, $34, $40, $7E, $0F
  Data.a  $55, $47, $A3, $23, $DD, $51, $AF, $3A, $C3, $5C, $F9, $CE, $BA, $C5, $EA, $26
  Data.a  $2C, $53, $0D, $6E, $85, $28, $84, $09, $D3, $DF, $CD, $F4, $41, $81, $4D, $52
  Data.a  $6A, $DC, $37, $C8, $6C, $C1, $AB, $FA, $24, $E1, $7B, $08, $0C, $BD, $B1, $4A
  Data.a  $78, $88, $95, $8B, $E3, $63, $E8, $6D, $E9, $CB, $D5, $FE, $3B, $00, $1D, $39
  Data.a  $F2, $EF, $B7, $0E, $66, $58, $D0, $E4, $A6, $77, $72, $F8, $EB, $75, $4B, $0A
  Data.a  $31, $44, $50, $B4, $8F, $ED, $1F, $1A, $DB, $99, $8D, $33, $9F, $11, $83, $14
EndDataSection

  
Procedure md2Init(*context.Md2Context)
  ; Initialize the 48-byte buffer X
  FillMemory(@*context\x[0], 48, 0)
  ; Clear checksum
  FillMemory(@*context\c[0], 16, 0)
  ; Number of bytes in the buffer
  *context\size = 0
EndProcedure


Structure md2AsciiArray
  v.a[0]
EndStructure
 
Procedure md2ProcessBlock(*m.md2AsciiArray, *x.md2AsciiArray, *c.md2AsciiArray)
  
  Protected.i j, k, m, t
  
  
  ; Update checksum
  t = *c\v[15]
  For j = 0 To 15
    *c\v[j] ! PeekA(?MD2_s + (*m\v[j] ! t))
    t = *c\v[j]
  Next j
  
  ; Copy current block into X
  For j = 0 To 15
    *x\v[16 + j] = *m\v[j]
    *x\v[32 + j] = *x\v[16 + j] ! *x\v[j]
  Next j
  
  ; Encrypt block (18 rounds)
  t = 0
  For j = 0 To 17
    ; Round j
    For k = 0 To 47
       *x\v[k] ! PeekA(?MD2_s + t)
       t = *x\v[k]
    Next k
    
    ; Set t To (t + j) modulo 256
    t = (t + j) & $FF
  Next j
  
EndProcedure

  
Procedure md2Update(*context.Md2Context, *Data, length.i)
  
  Protected n.i
  
  ; Process the incoming Data
  While length > 0
    ; The buffer can hold at most 16 bytes
    If length < 16 - *context\size
      n = length
    Else
      n = 16 - *context\size
    EndIf
    
    ; Copy the Data To the buffer
    CopyMemory(*Data, @*context\m[0] + *context\size, n)
    
    ; Update the MD2 context
    *context\size + n
    ; Advance the Data pointer
    *Data + n
    ; Remaining bytes To process
    length - n
    
    ; Process message in 16-word blocks
    If *context\size = 16
      ; Transform the 16-word block
      md2ProcessBlock(@*context\m[0], @*context\x[0], @*context\c[0])
      ; Empty the buffer
      *context\size = 0
    EndIf
  Wend
EndProcedure
  
  
  
Procedure md2Final(*context.Md2Context, *digest.Ascii)

  Protected n.i
  
  ; Pad the message so that its length is congruent To 0 modulo 16
  n = 16 - *context\size
  
  ; Append padding bytes
  FillMemory(@*context\m[0] + *context\size, n, n)
  
  ; Transform the 16-word block
  md2ProcessBlock(@*context\m[0], @*context\x[0], @*context\c[0])
  
  ; Append the checksum
  CopyMemory(@*context\c[0], @*context\m[0], 16)
  ; Transform the 16-word block
  md2ProcessBlock(@*context\m[0], @*context\x[0], @*context\c[0])
  
  ; Copy the resulting digest
  If *digest <> #Null
    CopyMemory(@*context\digest[0], *digest, #MD2_DIGEST_SIZE)
  EndIf
EndProcedure
  



Procedure.s FingerPrintMD2(*buffer, size.i)
  
  Protected.i i
  Protected Context.Md2Context
  Protected Hash$
  Protected Dim Digest.a(15)
  
  
  If *buffer And Size > 0
    md2Init(@Context)
    md2Update(@Context, *buffer, size)
    md2Final(@Context, @Digest(0))
    For i = 0 To 15
      Hash$ + LCase(RSet(Hex(Digest(i)), 2, "0"))
    Next i
  EndIf
  
  ProcedureReturn Hash$
  
EndProcedure


Procedure.s StringFingerprintMD2(String$)
  
  Protected *UTF8
  Protected Hash$
  
  
  *UTF8 = UTF8(String$)
  If *UTF8
    Hash$ = FingerPrintMD2(*UTF8, MemorySize(*UTF8) - 1)
    FreeMemory(*UTF8)
  EndIf
  
  ProcedureReturn Hash$
  
EndProcedure


Procedure.s FileFingerprintMD2(Filename$, Offset.i=0, Length.i=0)
  
  Protected.i i, File, Size
  Protected Hash$
  Protected *Buffer
  
  
  File = ReadFile(#PB_Any, Filename$)
  If File
    
    If Offset > 0
      FileSeek(File, Offset)
    EndIf
    
    If Length
      Size = Length
    Else
      Size = Lof(File)
      If Offset
        Size - Offset
      EndIf
    EndIf
    
    *Buffer = AllocateMemory(Size, #PB_Memory_NoClear)
    If *Buffer
      If ReadData(File, *Buffer, Size) = Size
        Hash$ = FingerPrintMD2(*Buffer, Size)
      EndIf
      FreeMemory(*Buffer)
    EndIf
    
    CloseFile(File)
  EndIf
  
  ProcedureReturn Hash$
  
EndProcedure




CompilerIf #PB_Compiler_IsMainFile
  ;-Demo
  
  Debug "MD2:       " + StringFingerprintMD2("Hello World 1234567890")
  Debug "Should be: 2f31fac7bc62bd91d603b1e5f6c51362"
  
CompilerEndIf
Last edited by infratec on Sun Aug 04, 2024 8:52 pm, edited 1 time in total.
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5494
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Re: MD2 Cipher

Post by Kwai chang caine »

Works too here
I learn, thanks to you, there are many MD from 1 to 5 :idea:
Surely you need to use old encryptions, for create it ?
Or perhaps this encryptions always used in the world, again now ? :shock:
I'll go to bed a little less stupid tonight, notice... for me ...it's not hard :mrgreen:
Thanks for sharing 8)
ImageThe happiness is a road...
Not a destination
Post Reply