SHA3 Module (Keccak Module)

Share your advanced PureBasic knowledge/code with the community.
sec
Enthusiast
Enthusiast
Posts: 789
Joined: Sat Aug 09, 2003 3:13 am
Location: 90-61-92 // EU or ASIA
Contact:

SHA3 Module (Keccak Module)

Post by sec »

Code: Select all

    ;======================================================================
    ; Module:          SHA3.pbi
    ;
    ; Author:          sec, wilbert
    ; Date:            Sep 11, 2013
    ; Version:         1.4.8
    ; Target Compiler: PureBasic 5.20+
    ; Target OS:       All
    ; License:         Free, unrestricted, no warranty whatsoever
    ;                  Use at your own risk
    ;======================================================================

    DeclareModule SHA3
     
      #Keccakf_MMX = 1 ; 1 for CPU with MMX - 0 for oringal
     
      Structure SHA3Context
        state.q[25]
        pos.a
        rsiz.a ;        number of message bytes processed by permutation
        hsiz.a ;        size of hash in bytes
      EndStructure
     
      ;-Exported functions
      Declare$ Fingerprint(*Buffer, Size, Mode=224)   
      Declare$ FileFingerprint(Filename$, Mode=224, Offset.q=0, Length.q=0, ProgressBarGadgetNr=-1)
      Declare SHA3_init(*ctx.SHA3Context, hsiz.i)
      Declare SHA3_update(*ctx.SHA3Context, *Data, len)
      Declare$ SHA3_final(*ctx.SHA3Context)
     
    EndDeclareModule

    Module SHA3
      EnableExplicit
      ;- Variable, Structure, Data
      ;credit: Danilo
     
      Structure QuadArray
        q.q[0]
      EndStructure
     
      Structure WordArray
        w.w[0]
      EndStructure
     
      Structure AArray
        a.a[0]
      EndStructure       
     
      DataSection
        _rndc:
        !dq 0x0000000000000001, 0x0000000000008082, 0x800000000000808A, 0x8000000080008000, 0x000000000000808B, 0x0000000080000001
        !dq 0x8000000080008081, 0x8000000000008009, 0x000000000000008A, 0x0000000000000088, 0x0000000080008009, 0x000000008000000A
        !dq 0x000000008000808B, 0x800000000000008B, 0x8000000000008089, 0x8000000000008003, 0x8000000000008002, 0x8000000000000080
        !dq 0x000000000000800A, 0x800000008000000A, 0x8000000080008081, 0x8000000000008080, 0x0000000080000001, 0x8000000080008008
       
        _rotc:
        !dq 1,  3,  6,  10, 15, 21, 28, 36, 45, 55, 2,  14
        !dq 27, 41, 56, 8,  25, 43, 62, 18, 39, 61, 20, 44
       
        _piln:
        !dq 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1
       
        _hex_bytes:
        !db '000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f'
        !db '202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f'
        !db '404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f'
        !db '606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f'
        !db '808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f'
        !db 'a0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebf'
        !db 'c0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedf'
        !db 'e0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff'
       
      EndDataSection
     
      Procedure BufferXOR(*Src, *Dest, Length)
        !mov ecx, [p.v_Length]
        CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
          !mov r8, [p.p_Src]
          !mov r9, [p.p_Dest]
        CompilerElse
          !mov eax, [p.p_Src]
          !mov edx, [p.p_Dest]
          !push ebx
        CompilerEndIf
        !cmp ecx, 1
        !jge sha3.l_bufferxor_loop0_ep
        !jmp sha3.l_bufferxor_exit
        !sha3.l_bufferxor_loop0:
        !dec ecx
        CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
          !mov al, [r8 + rcx]
          !xor [r9 + rcx], al
        CompilerElse
          !mov bl, [eax + ecx]
          !xor [edx + ecx], bl
        CompilerEndIf
        !sha3.l_bufferxor_loop0_ep:
        !test ecx, 7
        !jz sha3.l_bufferxor_loop1_ep
        !jmp sha3.l_bufferxor_loop0
        !sha3.l_bufferxor_loop1:
        CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
          !mov rax, [r8 + rcx]
          !xor [r9 + rcx], rax
        CompilerElse
          !mov ebx, [eax + ecx]
          !xor [edx + ecx], ebx
          !mov ebx, [eax + ecx + 4]
          !xor [edx + ecx + 4], ebx
        CompilerEndIf
        !sha3.l_bufferxor_loop1_ep:
        !sub ecx, 8
        !jnc sha3.l_bufferxor_loop1
        !sha3.l_bufferxor_exit:
        CompilerIf #PB_Compiler_Processor <> #PB_Processor_x64
          !pop ebx
        CompilerEndIf
      EndProcedure
     
      CompilerIf #Keccakf_MMX = 1   
        CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
          Macro KECCAKF_M_MEM2MM(mm_reg, offset)
            !movq mm_reg, [rdx + offset]
          EndMacro
          Macro KECCAKF_M_MM2MEM(mm_reg, offset)
            !movq [rdx + offset], mm_reg
          EndMacro
          Macro KECCAKF_M_THETA_XOR(reg, offset)
            !pxor reg, [rdx + rcx + offset]
          EndMacro
        CompilerElse
          Macro KECCAKF_M_MEM2MM(mm_reg, offset)
            !movq mm_reg, [edx + offset]
          EndMacro
          Macro KECCAKF_M_MM2MEM(mm_reg, offset)
            !movq [edx + offset], mm_reg
          EndMacro
          Macro KECCAKF_M_THETA_XOR(reg, offset)
            !pxor reg, [edx + ecx + offset]
          EndMacro
        CompilerEndIf
       
        Macro KECCAKF_M_THETA_(offset)
          KECCAKF_M_MEM2MM(mm6, offset)
          !pxor mm6, mm5
          KECCAKF_M_MM2MEM(mm6, offset)
        EndMacro
       
        Macro KECCAKF_M_THETA(reg1, reg2, offset)
          CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
            !movq r9, reg2
            !rol r9, 1
            !movq mm5, r9
          CompilerElse
            !movq mm5, reg2
            !movq mm6, mm5
            !psllq mm5, 1
            !psrlq mm6, 63
            !por mm5, mm6
          CompilerEndIf
          !pxor mm5, reg1
          KECCAKF_M_THETA_(offset)
          KECCAKF_M_THETA_(offset + 40)
          KECCAKF_M_THETA_(offset + 80)
          KECCAKF_M_THETA_(offset + 120)
          KECCAKF_M_THETA_(offset + 160)
        EndMacro
       
        Macro KECCAKF_M_RHO_PHI(piln, rotc)
          CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
            !movq r9, mm7
            !rol r9, rotc
            !movq mm7, [rdx + piln * 8]
            !mov [rdx + piln * 8], r9
          CompilerElse
            !movq mm6, mm7
            !movq mm5, mm6
            !psllq mm5, rotc
            !psrlq mm6, 64-rotc
            !por mm5, mm6
            !movq mm7, [edx + piln * 8]
            !movq [edx + piln * 8], mm5
          CompilerEndIf   
        EndMacro
       
        Macro KECCAKF_M_CHI_(reg1, reg2, reg3, offset)
          !movq mm5, reg1
          !pandn mm5, reg2
          !pxor mm5, reg3
          KECCAKF_M_MM2MEM(mm5, offset)
        EndMacro
       
        Macro KECCAKF_M_CHI(offset)
          KECCAKF_M_MEM2MM(mm0, offset)
          KECCAKF_M_MEM2MM(mm1, offset + 8)
          KECCAKF_M_MEM2MM(mm2, offset + 16)
          KECCAKF_M_MEM2MM(mm3, offset + 24)
          KECCAKF_M_MEM2MM(mm4, offset + 32)
          KECCAKF_M_CHI_(mm1, mm2, mm0, offset)
          KECCAKF_M_CHI_(mm2, mm3, mm1, offset + 8)
          KECCAKF_M_CHI_(mm3, mm4, mm2, offset + 16)
          KECCAKF_M_CHI_(mm4, mm0, mm3, offset + 24)
          KECCAKF_M_CHI_(mm0, mm1, mm4, offset + 32)
        EndMacro
       
        Procedure keccakf(*st); mmx version (mm0 - mm4 = bc)
          CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
            !lea r8, [sha3.l__rndc]
            !mov rdx, [p.p_st]
          CompilerElse
            !mov edx, [p.p_st]
          CompilerEndIf
          !xor eax, eax
          !sha3.l_keccakf_loop:
         
          ;Theta
          KECCAKF_M_MEM2MM(mm0, 0)
          KECCAKF_M_MEM2MM(mm1, 8)
          KECCAKF_M_MEM2MM(mm2, 16)
          KECCAKF_M_MEM2MM(mm3, 24)
          KECCAKF_M_MEM2MM(mm4, 32)
          !mov ecx, 160
          !sha3.l_keccakf_theta_loop:
          KECCAKF_M_THETA_XOR(mm0, 0)
          KECCAKF_M_THETA_XOR(mm1, 8)
          KECCAKF_M_THETA_XOR(mm2, 16)
          KECCAKF_M_THETA_XOR(mm3, 24)
          KECCAKF_M_THETA_XOR(mm4, 32)
          !sub ecx, 40
          !jnz sha3.l_keccakf_theta_loop
          KECCAKF_M_THETA(mm4, mm1, 0)
          KECCAKF_M_THETA(mm0, mm2, 8)
          KECCAKF_M_THETA(mm1, mm3, 16)
          KECCAKF_M_THETA(mm2, mm4, 24)
          KECCAKF_M_THETA(mm3, mm0, 32)
         
          ;Rho Pi
          KECCAKF_M_MEM2MM(mm7, 8)
          KECCAKF_M_RHO_PHI(10, 1)
          KECCAKF_M_RHO_PHI(7, 3)
          KECCAKF_M_RHO_PHI(11, 6)
          KECCAKF_M_RHO_PHI(17, 10)
          KECCAKF_M_RHO_PHI(18, 15)
          KECCAKF_M_RHO_PHI(3, 21)
          KECCAKF_M_RHO_PHI(5, 28)
          KECCAKF_M_RHO_PHI(16, 36)
          KECCAKF_M_RHO_PHI(8, 45)
          KECCAKF_M_RHO_PHI(21, 55)
          KECCAKF_M_RHO_PHI(24, 2)
          KECCAKF_M_RHO_PHI(4, 14)
          KECCAKF_M_RHO_PHI(15, 27)
          KECCAKF_M_RHO_PHI(23, 41)
          KECCAKF_M_RHO_PHI(19, 56)
          KECCAKF_M_RHO_PHI(13, 8)
          KECCAKF_M_RHO_PHI(12, 25)
          KECCAKF_M_RHO_PHI(2, 43)
          KECCAKF_M_RHO_PHI(20, 62)
          KECCAKF_M_RHO_PHI(14, 18)
          KECCAKF_M_RHO_PHI(22, 39)
          KECCAKF_M_RHO_PHI(9, 61)
          KECCAKF_M_RHO_PHI(6, 20)
          KECCAKF_M_RHO_PHI(1, 44)
         
          ;Chi
          KECCAKF_M_CHI(0)
          KECCAKF_M_CHI(40)
          KECCAKF_M_CHI(80)
          KECCAKF_M_CHI(120)
          KECCAKF_M_CHI(160)
         
          ;Iota
          KECCAKF_M_MEM2MM(mm5, 0)
          CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
            !pxor mm5, [r8 + rax * 8]
          CompilerElse
            !pxor mm5, [sha3.l__rndc + eax * 8]
          CompilerEndIf   
          KECCAKF_M_MM2MEM(mm5, 0)
          !inc eax
          !cmp eax, 24; keccak rounds
          !jne sha3.l_keccakf_loop
          !emms
         
        EndProcedure   
      CompilerElse
       
        Procedure.q Rotl64(val.q, n)   
          !mov ecx, [p.v_n]
          CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
            !mov rax, [p.v_val]
            !rol rax, cl
          CompilerElse
            !btr ecx, 5
            !jc rotl64_1
            !mov eax, [p.v_val]
            !mov edx, [p.v_val + 4]
            !jmp rotl64_2
            !rotl64_1:
            !mov edx, [p.v_val]
            !mov eax, [p.v_val + 4]
            !rotl64_2:
            !push ebx
            !mov ebx, eax
            !shld eax, edx, cl
            !shld edx, ebx, cl
            !pop ebx
          CompilerEndIf
          ProcedureReturn
        EndProcedure
       
        Procedure keccakf(*st.QuadArray)     
          Define *rndc.QuadArray = ?_rndc
          Define *rotc.QuadArray = ?_rotc
          Define *piln.QuadArray = ?_piln
          Define.i i, j, round
          Define.q t
          Dim bc.q(5-1)
         
          For round = 0 To 23       
            ;Theta
            For i = 0 To 4
              bc(i) = *st\q[i] ! *st\q[i + 5] ! *st\q[i + 10] ! *st\q[i + 15] ! *st\q[i + 20]         
            Next           
            For i = 0 To 4
              t = bc((i + 4) % 5) ! ROTL64(bc((i + 1) % 5), 1)       
              For j = 0 To 24 Step 5
                *st\q[j + i] ! t
              Next
            Next
           
            ;Rho Pi
            t = *st\q[1]     
            For i = 0 To 23
              j = *piln\q[i]       
              bc(0) = *st\q[j]
              *st\q[j] = ROTL64(t, *rotc\q[i])         
              t = bc(0)
            Next       
           
            ;Chi
            For j = 0 To 24 Step 5       
              For i = 0 To 4
                bc(i) = *st\q[j + i]
              Next       
              For i = 0 To 4
                *st\q[j + i] ! ((~bc((i + 1) % 5)) & bc((i + 2) % 5))
              Next         
            Next
           
            ;Iota
            *st\q[0] ! *rndc\q[round]
          Next
         
        EndProcedure
       
      CompilerEndIf
     
      Procedure SHA3_init(*ctx.SHA3Context, hsiz.i)
        FillMemory(*ctx, SizeOf(SHA3Context))
        Select hsiz
          Case 512
            *ctx\hsiz = 64
            *ctx\rsiz = 72
          Case 384
            *ctx\hsiz = 48
            *ctx\rsiz = 104
          Case 256
            *ctx\hsiz = 32
            *ctx\rsiz = 136
          Default; 224
            *ctx\hsiz = 28
            *ctx\rsiz = 144
        EndSelect   
      EndProcedure
     
      Procedure SHA3_update(*ctx.SHA3Context, *Data, len)
        Define.i absorb
        While len
          absorb = *ctx\rsiz - *ctx\pos
          If len < absorb
            absorb = len
          EndIf
          BufferXOR(*Data, *ctx + *ctx\pos, absorb)
          *Data + absorb
          len - absorb
          *ctx\pos + absorb
          If *ctx\pos = *ctx\rsiz
            keccakf(*ctx)
            *ctx\pos = 0
          EndIf
        Wend
      EndProcedure
     
      Procedure$ SHA3_final(*ctx.SHA3Context)
        Dim hash.w(64)
        Define *hex_bytes.WordArray = ?_hex_bytes
        Define *st.AArray = *ctx
        Define.i i
       
        *st\a[*ctx\pos] ! 1
        *st\a[*ctx\rsiz - 1] ! $80
        keccakf(*ctx)
       
        While i < *ctx\hsiz
          hash(i) = *hex_bytes\w[*st\a[i]]
          i + 1
        Wend
        ProcedureReturn PeekS(@hash(), -1, #PB_Ascii)
      EndProcedure
     
     
      ;-Exported functions
      Procedure$ FileFingerprint(Filename$, Mode=224, Offset.q=0, Length.q=0, ProgressBarGadgetNr=-1)
       
        #gnChunkSize = 1024 * 32; 32 KiB
        Dim DataChunk.q(#gnChunkSize >> 3)
       
        Define hash.s, file.i, error.i, ctx.SHA3Context
        Define.q nBytes, nTotalBytes, nTotalBytesRead
       
        file = ReadFile(#PB_Any, Filename$)
        If file
          nTotalBytes = Lof(file)
          If Offset < nTotalBytes
            FileSeek(file, Offset)
            If Length = 0
              Length = nTotalBytes
            EndIf
            If Offset + Length > nTotalBytes
              Length = nTotalBytes - Offset
            EndIf
            nTotalBytes = Length
           
            SHA3_init(@ctx, Mode)
           
            While Length > 0
              nBytes = ReadData(file, @DataChunk(), #gnChunkSize)
              If nBytes
                If nBytes > Length
                  nBytes = Length
                EndIf
                SHA3_update(@ctx, @DataChunk(), nBytes)
                Length - nBytes
                nTotalBytesRead + nBytes
                If ProgressBarGadgetNr >= 0 And IsGadget(ProgressBarGadgetNr)
                  SetGadgetState(ProgressBarGadgetNr, 100 * nTotalBytesRead / nTotalBytes)
                EndIf
              Else
                error = #True
                Break
              EndIf
            Wend
           
            If error <> #True
              hash = SHA3_final(@ctx)
            EndIf
           
          EndIf
          CloseFile(file)
        EndIf
       
        ProcedureReturn hash
      EndProcedure
     
      Procedure$ Fingerprint(*Buffer, Size, Mode=224)               
        Define ctx.SHA3Context
        SHA3_init(@ctx, Mode)
        SHA3_update(@ctx, *Buffer, Size)
        ProcedureReturn SHA3_final(@ctx)   
      EndProcedure
     
    EndModule
Have fun

Version: 1.4.1
- initiation
Version: 1.4.2
- Threadsafe (remove Global variables)
Version: 1.4.3
- Remove junks
Version: 1.4.4
- use PeekA instead of PeekC (@wilbert)
Version: 1.4.5
- add support CPU MMX it's 20x faster, #Keccakf_MMX switch and turn on by default :mrgreen:
- add wilbert to author 8)
Version: 1.4.6
- Many things changed, the sha3 function has better speed than the popular hash on internet (hat off to guru wilbert )
- Here is exported functions, structure, const:
#Keccakf_MMX = 1 ; 1 for CPU with MMX - 0 for oringal

Structure SHA3Context
state.q[25]
pos.a
rsiz.a ; number of message bytes processed by permutation
hsiz.a ; size of hash in bytes
EndStructure

;-Exported functions
Declare$ Fingerprint(*Buffer, Size, Mode=224)
Declare$ FileFingerprint(Filename$, Mode=224, Offset.q=0, Length.q=0, ProgressBarGadgetNr=-1)
Declare SHA3_init(*ctx.SHA3Context, hsiz.i)
Declare SHA3_update(*ctx.SHA3Context, *Data, len)
Declare$ SHA3_final(*ctx.SHA3Context)
- Remove junks
Version: 1.4.7
- optimize the 64 bit code by guru wilbert

Version: 1.4.8
- another update improving speed by wilbert
Last edited by sec on Thu Sep 12, 2013 3:40 am, edited 13 times in total.
User_Russian
Addict
Addict
Posts: 1443
Joined: Wed Nov 12, 2008 5:01 pm
Location: Russia

Re: SHA3 Module (Keccak Module)

Post by User_Russian »

The module will not work correctly with multiple threads, because of the globals arrays.
sec
Enthusiast
Enthusiast
Posts: 789
Joined: Sat Aug 09, 2003 3:13 am
Location: 90-61-92 // EU or ASIA
Contact:

Re: SHA3 Module (Keccak Module)

Post by sec »

User_Russian wrote:The module will not work correctly with multiple threads, because of the globals arrays.
Thanks, How do you fix it?
Fred
Administrator
Administrator
Posts: 16618
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Re: SHA3 Module (Keccak Module)

Post by Fred »

You can use 'Threaded'
sec
Enthusiast
Enthusiast
Posts: 789
Joined: Sat Aug 09, 2003 3:13 am
Location: 90-61-92 // EU or ASIA
Contact:

Re: SHA3 Module (Keccak Module)

Post by sec »

Thanks, the module is updated v1.4.2 for threadsafe :mrgreen:
User avatar
RichAlgeni
Addict
Addict
Posts: 914
Joined: Wed Sep 22, 2010 1:50 am
Location: Bradenton, FL

Re: SHA3 Module (Keccak Module)

Post by RichAlgeni »

Nicely done!
User avatar
flaith
Enthusiast
Enthusiast
Posts: 704
Joined: Mon Apr 25, 2005 9:28 pm
Location: $300:20 58 FC 60 - Rennes
Contact:

Re: SHA3 Module (Keccak Module)

Post by flaith »

Thanks for the code sec :)

EDIT: When I tried in unicode, the values returned are different
“Fear is a reaction. Courage is a decision.” - WC
sec
Enthusiast
Enthusiast
Posts: 789
Joined: Sat Aug 09, 2003 3:13 am
Location: 90-61-92 // EU or ASIA
Contact:

Re: SHA3 Module (Keccak Module)

Post by sec »

flaith wrote:Thanks for the code sec :)

EDIT: When I tried in unicode, the values returned are different
@ RichAlgeni: Thanks bro :)
@flaith: updated version 1.4.4

Thanks.
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: SHA3 Module (Keccak Module)

Post by wilbert »

I converted the keccakf procedure to asm.
It should be a bit faster but I haven't actually compared yet

Code: Select all

;======================================================================
; Module:          SHA3.pbi
;
; Author:          sec
; Date:            Sep 06, 2013
; Version:         1.4.5 (MMX)
; Target Compiler: PureBasic 5.20+
; Target OS:       All
; License:         Free, unrestricted, no warranty whatsoever
;                  Use at your own risk
;======================================================================

DeclareModule SHA3  
  Declare$ sha224(*Buffer, Size)
  Declare$ sha256(*Buffer, Size)
  Declare$ sha384(*Buffer, Size)
  Declare$ sha512(*Buffer, Size)    
EndDeclareModule

Module SHA3
  EnableExplicit
  ;-Internal functions  
  
  CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
    Macro KECCAKF_M_MEM2MM(mm_reg, offset)
      !movq mm_reg, [rdx + offset]
    EndMacro
    Macro KECCAKF_M_MM2MEM(mm_reg, offset)
      !movq [rdx + offset], mm_reg
    EndMacro
    Macro KECCAKF_M_THETA_XOR(reg, offset)
      !pxor reg, [rdx + rcx + offset]
    EndMacro
  CompilerElse
    Macro KECCAKF_M_MEM2MM(mm_reg, offset)
      !movq mm_reg, [edx + offset]
    EndMacro
    Macro KECCAKF_M_MM2MEM(mm_reg, offset)
      !movq [edx + offset], mm_reg
    EndMacro
    Macro KECCAKF_M_THETA_XOR(reg, offset)
      !pxor reg, [edx + ecx + offset]
    EndMacro
  CompilerEndIf  
  
  Macro KECCAKF_M_THETA_(offset)
    KECCAKF_M_MEM2MM(mm6, offset)
    !pxor mm6, mm5
    KECCAKF_M_MM2MEM(mm6, offset)
  EndMacro
  
  Macro KECCAKF_M_THETA(reg1, reg2, offset)
    !movq mm5, reg2
    !movq mm6, mm5
    !psllq mm5, 1
    !psrlq mm6, 63
    !por mm5, mm6
    !pxor mm5, reg1
    KECCAKF_M_THETA_(offset)
    KECCAKF_M_THETA_(offset + 40)
    KECCAKF_M_THETA_(offset + 80)
    KECCAKF_M_THETA_(offset + 120)
    KECCAKF_M_THETA_(offset + 160)
  EndMacro
  
  Macro KECCAKF_M_CHI_(reg1, reg2, reg3, offset)
    !movq mm5, reg1
    !pandn mm5, reg2
    !pxor mm5, reg3
    KECCAKF_M_MM2MEM(mm5, offset)
  EndMacro
  
  Macro KECCAKF_M_CHI(offset)
    KECCAKF_M_MEM2MM(mm0, offset)
    KECCAKF_M_MEM2MM(mm1, offset + 8)
    KECCAKF_M_MEM2MM(mm2, offset + 16)
    KECCAKF_M_MEM2MM(mm3, offset + 24)
    KECCAKF_M_MEM2MM(mm4, offset + 32)
    KECCAKF_M_CHI_(mm1, mm2, mm0, offset)
    KECCAKF_M_CHI_(mm2, mm3, mm1, offset + 8)
    KECCAKF_M_CHI_(mm3, mm4, mm2, offset + 16)
    KECCAKF_M_CHI_(mm4, mm0, mm3, offset + 24)
    KECCAKF_M_CHI_(mm0, mm1, mm4, offset + 32)
  EndMacro
  
  Procedure keccakf(*st); mmx version (mm0 - mm4 = bc)
    CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
      !lea r8, [keccakf_rotc]
      !lea r9, [keccakf_piln]
      !lea r10, [keccakf_rndc]
      !mov rdx, [p.p_st]
      !push rbx
    CompilerElse
      !mov edx, [p.p_st]
      !push ebx
    CompilerEndIf 
    !xor ebx, ebx
    !keccakf_loop:
    
    ;Theta
    KECCAKF_M_MEM2MM(mm0, 0)
    KECCAKF_M_MEM2MM(mm1, 8)
    KECCAKF_M_MEM2MM(mm2, 16)
    KECCAKF_M_MEM2MM(mm3, 24)
    KECCAKF_M_MEM2MM(mm4, 32)
    !mov ecx, 160
    !keccakf_theta_loop:
    KECCAKF_M_THETA_XOR(mm0, 0)
    KECCAKF_M_THETA_XOR(mm1, 8)
    KECCAKF_M_THETA_XOR(mm2, 16)
    KECCAKF_M_THETA_XOR(mm3, 24)
    KECCAKF_M_THETA_XOR(mm4, 32)
    !sub ecx, 40
    !jnz keccakf_theta_loop
    KECCAKF_M_THETA(mm4, mm1, 0)
    KECCAKF_M_THETA(mm0, mm2, 8)
    KECCAKF_M_THETA(mm1, mm3, 16)
    KECCAKF_M_THETA(mm2, mm4, 24)
    KECCAKF_M_THETA(mm3, mm0, 32)
    
    ;Rho Pi
    KECCAKF_M_MEM2MM(mm7, 8)
    !xor ecx, ecx
    !keccakf_rho_phi_loop:
    !movq mm6, mm7
    !movq mm5, mm6
    CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
      !mov eax, [r9 + rcx]
      !movq mm7, [rdx + rax * 8]
      !psllq mm5, [r8 + rcx * 2]
      !psrlq mm6, [r8 + rcx * 2 + 8]
      !por mm5, mm6
      !movq [rdx + rax * 8], mm5
    CompilerElse
      !mov eax, [keccakf_piln + ecx]
      !movq mm7, [edx + eax * 8]
      !psllq mm5, [keccakf_rotc + ecx * 2]
      !psrlq mm6, [keccakf_rotc + ecx * 2 + 8]
      !por mm5, mm6
      !movq [edx + eax * 8], mm5
    CompilerEndIf      
    !add ecx, 8
    !cmp ecx, 192
    !jb keccakf_rho_phi_loop
    
    ;Chi
    KECCAKF_M_CHI(0)
    KECCAKF_M_CHI(40)
    KECCAKF_M_CHI(80)
    KECCAKF_M_CHI(120)
    KECCAKF_M_CHI(160)
    
    ;Iota
    KECCAKF_M_MEM2MM(mm5, 0)
    CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
      !pxor mm5, [r10 + rbx * 8]
    CompilerElse
      !pxor mm5, [keccakf_rndc + ebx * 8]
    CompilerEndIf   
    KECCAKF_M_MM2MEM(mm5, 0)
    !inc ebx
    !cmp ebx, 24; keccak rounds
    !jne keccakf_loop
    !emms
    
    CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
      !pop rbx
    CompilerElse
      !pop ebx
    CompilerEndIf   
    ProcedureReturn
    
    !align 8
    !keccakf_rndc:
    !dq 0x0000000000000001, 0x0000000000008082, 0x800000000000808A, 0x8000000080008000, 0x000000000000808B, 0x0000000080000001
    !dq 0x8000000080008081, 0x8000000000008009, 0x000000000000008A, 0x0000000000000088, 0x0000000080008009, 0x000000008000000A
    !dq 0x000000008000808B, 0x800000000000008B, 0x8000000000008089, 0x8000000000008003, 0x8000000000008002, 0x8000000000000080
    !dq 0x000000000000800A, 0x800000008000000A, 0x8000000080008081, 0x8000000000008080, 0x0000000080000001, 0x8000000080008008
    !keccakf_rotc:
    !dq 1,63,  3,61,  6,58,  10,54,  15,49,  21,43,  28,36,  36,28,  45,19,  55,9,  2,62,  14,50
    !dq 27,37,  41,23,  56,8,  8,56,  25,39,  43,21,  62,2,  18,46,  39,25,  61,3,  20,44,  44,20
    !keccakf_piln:
    !dq 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1    
  EndProcedure   
  
  
  Procedure$ keccak(in, inlen, mdlen)
    Dim st.q(25)
    Dim temp.a(144)
    Define.i i, rsiz, rsizw
    Define stemp$
    
    rsiz = 200 - 2 * mdlen
    rsizw = rsiz / 8
    
    FillMemory(@st(),SizeOf(Quad) + SizeOf(Quad)*ArraySize(st()))
    
    While inlen >= rsiz
      For i = 0 To rsizw-1       
        st(i) ! PeekQ(in+i*SizeOf(Quad))        
      Next
      keccakf(@st())
      inlen - rsiz 
      in + rsiz
    Wend    
    
    ;last block And padding
    CopyMemory(in, @temp(), inlen)
    
    temp(inlen) = 1
    inlen+1   
    
    FillMemory(@temp() + inlen,rsiz - inlen + 1 ,0)   
    
    temp(rsiz - 1) | $80       
    For i = 0 To rsizw -1    
      st(i) ! PeekQ(@temp(i*SizeOf(Quad)))
    Next    
    
    keccakf(@st())
    
    
    stemp$=""
    For i = 0 To mdlen -1
      stemp$ + RSet(Hex(PeekA(@st()+i)),2,"0")
    Next
    ProcedureReturn stemp$ 
  EndProcedure
  
  
  ;-SHA3 functions
  Procedure$ sha224(*Buffer, Size)    
    ProcedureReturn keccak(*Buffer, Size, 28)
  EndProcedure
  
  Procedure$ sha256(*Buffer, Size)   
    ProcedureReturn keccak(*Buffer, Size, 32)
  EndProcedure
  
  Procedure$ sha384(*Buffer, Size)
    ProcedureReturn keccak(*Buffer, Size, 48)
  EndProcedure
  
  Procedure$ sha512(*Buffer, Size)
    ProcedureReturn keccak(*Buffer, Size, 64)
  EndProcedure
  
  
EndModule

;-Usage - Example
CompilerIf #PB_Compiler_IsMainFile
  EnableExplicit
  
  Define msg$ = "The quick brown fox jumps over the lazy dog."
  Define msglen = StringByteLength(msg$)
  
  Debug SHA3::sha224(@msg$, msglen)
  Debug SHA3::sha256(@msg$, msglen)
  Debug SHA3::sha384(@msg$, msglen)
  Debug SHA3::sha512(@msg$, msglen)
  
  
CompilerEndIf
Windows (x64)
Raspberry Pi OS (Arm64)
sec
Enthusiast
Enthusiast
Posts: 789
Joined: Sat Aug 09, 2003 3:13 am
Location: 90-61-92 // EU or ASIA
Contact:

Re: SHA3 Module (Keccak Module)

Post by sec »

@wilbert: It's ~20x faster :shock:

Added your MMX version to first post (and enable by default).

Thanks man.
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: SHA3 Module (Keccak Module)

Post by wilbert »

sec wrote:@wilbert: It's ~20x faster :shock:
That's a nice number :D
Windows (x64)
Raspberry Pi OS (Arm64)
sec
Enthusiast
Enthusiast
Posts: 789
Joined: Sat Aug 09, 2003 3:13 am
Location: 90-61-92 // EU or ASIA
Contact:

Re: SHA3 Module (Keccak Module)

Post by sec »

Version: 1.4.6
- Many things changed, the sha3 function has better speed than the popular hash tool on internet (hat off to guru wilbert )
- Here is exported functions, structure, const:
#Keccakf_MMX = 1 ; 1 for CPU with MMX - 0 for oringal

Structure SHA3Context
state.q[25]
pos.a
rsiz.a ; number of message bytes processed by permutation
hsiz.a ; size of hash in bytes
EndStructure

;-Exported functions
Declare$ Fingerprint(*Buffer, Size, Mode=224)
Declare$ FileFingerprint(Filename$, Mode=224, Offset.q=0, Length.q=0, ProgressBarGadgetNr=-1)
Declare SHA3_init(*ctx.SHA3Context, hsiz.i)
Declare SHA3_update(*ctx.SHA3Context, *Data, len)
Declare$ SHA3_final(*ctx.SHA3Context)
Last edited by sec on Tue Sep 10, 2013 8:23 am, edited 1 time in total.
walbus
Addict
Addict
Posts: 929
Joined: Sat Mar 02, 2013 9:17 am

Re: SHA3 Module (Keccak Module)

Post by walbus »

fine, many thanks.
Please looking, i have tested SHA256

The quick brown fox jumps over the lazy dog.

The Module means 578951E24EFD62A3D63A86F7CD19AAA53C898FE287D2552133220370240B572D

correct is [SHA256_EF537F25C895BFA782526529A9B63D97AA631564D5D789C2B765448C8635FB6C]
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: SHA3 Module (Keccak Module)

Post by wilbert »

This topic is about SHA3.
Keccak was chosen from a competition to become the SHA3 standard.
The hash you are mentioning is a SHA2-256 hash and not a SHA3-256 one. :wink:
Windows (x64)
Raspberry Pi OS (Arm64)
sec
Enthusiast
Enthusiast
Posts: 789
Joined: Sat Aug 09, 2003 3:13 am
Location: 90-61-92 // EU or ASIA
Contact:

Re: SHA3 Module (Keccak Module)

Post by sec »

... And the module has tested with testvector from NIST, 100% passed :mrgreen:
Post Reply