HMAC Modul (mit MD5 und SHA1 Support)

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Christian+
Beiträge: 213
Registriert: 13.07.2008 10:05
Computerausstattung: Windows 8.1 Pro
AMD Phenom II X4 955 @ 3.2 GHz
4GB RAM
NVIDIA GeForce GTX 660

HMAC Modul (mit MD5 und SHA1 Support)

Beitrag von Christian+ »

Keyed-Hash Message Authentication Code (HMAC) Modul

Da ich aktuell für eines meiner Projekte die Möglichkeit verschiedene HMACs zu berechnen benötige habe ich dafür mal ein Modul erstellt.
Vielleicht kann es ja noch jemand brauchen oder mit Verbesserungsvorschlägen zur Weiterentwicklung beitragen.

Code: Alles auswählen

; ----------------------------------------------------------------------
;- HMAC.pb
; ----------------------------------------------------------------------
; | Title:   | HMAC
; ----------------------------------------------------------------------
; | Author:  | Christian+
; ----------------------------------------------------------------------
; | Date:    | 2014-03-26
; ----------------------------------------------------------------------
; | Version: | 1.0
; ----------------------------------------------------------------------
; | URL:     | http://www.purebasic.fr/german/viewtopic.php?p=321343#p321343
; ----------------------------------------------------------------------

DeclareModule HMAC
  
  EnableExplicit
  
  Enumeration Mode
    #Hash_MD5
    #Hash_SHA1
  EndEnumeration
  
  Declare.i ExamineHMAC(*Key, KeySize.i, Mode.i)
  Declare  NextHMAC(*HMAC, *Message, MessageSize.i = -1)
  Declare.s FinishHMAC(*HMAC)
  
  Declare.s HMAC(*Key, KeySize.i, *Message, MessageSize.i, Mode.i)
  
  Declare.s StringHMAC(Key.s, Message.s, Mode.i)
  
EndDeclareModule

Module HMAC
  
  EnableExplicit
  
  Structure HMAC_DATA
    Mode.i
    *OKeyPad
    Fingerprint.i
  EndStructure
  
  Global Dim HashByteSize.i(1)
  HashByteSize(#Hash_MD5) = 16
  HashByteSize(#Hash_SHA1) = 20
  
  Global Dim HashBlockSize.i(1)
  HashBlockSize(#Hash_MD5) = 64
  HashBlockSize(#Hash_SHA1) = 64
  
  Procedure.i ConvertHexToBin(String.s)
    Protected Index.i, Len.i = Len(String), *DestMemory = AllocateMemory(Len / 2)
    For Index = 1 To Len Step 2
      PokeA(*DestMemory + (Index - 1) / 2, Val("$" + Mid(String, Index, 2)))
    Next
    ProcedureReturn *DestMemory
  EndProcedure
  
  Procedure.i ExamineFingerprint(Mode.i)
    Protected Fingerprint.i
    Select Mode
      Case #Hash_MD5
        Fingerprint = ExamineMD5Fingerprint(#PB_Any)
      Case #Hash_SHA1
        Fingerprint = ExamineSHA1Fingerprint(#PB_Any)
    EndSelect
    ProcedureReturn Fingerprint
  EndProcedure
  
  Procedure.i ExamineHMAC(*Key, KeySize.i, Mode.i)
    Protected *NewKey, Fingerprint.i, HashString.s, *Hash, *OKeyPad, *IKeyPad, Index.i, *HMAC.HMAC_DATA
    *HMAC = AllocateMemory(SizeOf(HMAC_DATA))
    *HMAC\Mode = Mode
    *NewKey = AllocateMemory(HashBlockSize(Mode))
    If KeySize > HashBlockSize(Mode)
      Fingerprint = ExamineFingerprint(Mode)
      NextFingerprint(Fingerprint, *Key, KeySize)
      HashString = FinishFingerprint(Fingerprint)
      *Hash = ConvertHexToBin(HashString)
      CopyMemory(*Hash, *NewKey, HashByteSize(Mode))
      FreeMemory(*Hash)
    Else
      CopyMemory(*Key, *NewKey, KeySize)
    EndIf
    *HMAC\OKeyPad = AllocateMemory(HashBlockSize(Mode), #PB_Memory_NoClear)
    *IKeyPad = AllocateMemory(HashBlockSize(Mode), #PB_Memory_NoClear)
    For Index = 0 To HashBlockSize(Mode) - 1
      PokeB(*HMAC\OKeyPad + Index, PeekB(*NewKey + Index) ! $5c)
      PokeB(*IKeyPad + Index, PeekB(*NewKey + Index) ! $36)
    Next
    FreeMemory(*NewKey)
    *HMAC\Fingerprint = ExamineFingerprint(Mode)
    NextFingerprint(*HMAC\Fingerprint, *IKeyPad, HashBlockSize(Mode))
    FreeMemory(*IKeyPad)
    ProcedureReturn *HMAC
  EndProcedure
  
  Procedure NextHMAC(*HMAC.HMAC_DATA, *Message, MessageSize.i = -1)
    If MessageSize = -1 : MessageSize = MemorySize(*Message) : EndIf
    If MessageSize > 0 : NextFingerprint(*HMAC\Fingerprint, *Message, MessageSize) : EndIf
  EndProcedure
  
  Procedure.s FinishHMAC(*HMAC.HMAC_DATA)
    Protected HashString.s, *Hash, Fingerprint.i
    HashString = FinishFingerprint(*HMAC\Fingerprint)
    *Hash = ConvertHexToBin(HashString)
    Fingerprint = ExamineFingerprint(*HMAC\Mode)
    NextFingerprint(Fingerprint, *HMAC\OKeyPad, HashBlockSize(*HMAC\Mode))
    NextFingerprint(Fingerprint, *Hash, HashByteSize(*HMAC\Mode))
    HashString = FinishFingerprint(Fingerprint)
    FreeMemory(*Hash)
    FreeMemory(*HMAC\OKeyPad)
    FreeMemory(*HMAC)
    ProcedureReturn HashString
  EndProcedure
  
  Procedure.s HMAC(*Key, KeySize.i, *Message, MessageSize.i, Mode.i)
    Protected *HMAC = ExamineHMAC(*Key, KeySize, Mode)
    NextHMAC(*HMAC, *Message, MessageSize)
    ProcedureReturn FinishHMAC(*HMAC)
  EndProcedure
  
  Procedure.s StringHMAC(Key.s, Message.s, Mode.i)
    Protected KeySize.i, *Key, MessageSize.i, *Message, HMAC.s
    KeySize = StringByteLength(Key, #PB_UTF8)
    *Key = AllocateMemory(KeySize + SizeOf(Character))
    PokeS(*Key, Key, -1, #PB_UTF8)
    MessageSize = StringByteLength(Message, #PB_UTF8)
    *Message = AllocateMemory(MessageSize + SizeOf(Character))
    PokeS(*Message, Message, -1, #PB_UTF8)
    HMAC = HMAC(*Key, KeySize, *Message, MessageSize, Mode)
    FreeMemory(*Key)
    FreeMemory(*Message)
    ProcedureReturn HMAC
  EndProcedure
  
EndModule

;- Beispiel
CompilerIf #PB_Compiler_IsMainFile
  
  EnableExplicit
  
  UseModule HMAC
  
  Define Key.s = ""
  Define Message.s = ""
  
  Debug "Key = ''  Message = ''"
  Debug "HMAC_MD5: " + StringHMAC(Key, Message, #Hash_MD5)
  Debug "HMAC_SHA1: " + StringHMAC(Key, Message, #Hash_SHA1)
  
  Debug ""
  
  Define Key.s = "key"
  Define Message.s = "The quick brown fox jumps over the lazy dog"
  
  Debug "Key = 'key'  Message = 'The quick brown fox jumps over the lazy dog'"
  Debug "HMAC_MD5: " + StringHMAC(Key, Message, #Hash_MD5)
  Debug "HMAC_SHA1: " + StringHMAC(Key, Message, #Hash_SHA1)
  
CompilerEndIf
Windows 8.1 Pro 64Bit | AMD Phenom II X4 955 @ 3.2 GHz | 4GB RAM | NVIDIA GeForce GTX 660