PureBasic - форум

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » PureBasic - форум » OpenSource » Аппартаная поддержка процессором хеширования SHA1


Аппартаная поддержка процессором хеширования SHA1

Сообщений 1 страница 4 из 4

1

В процессоры была добавлена поддержка инструкций хеширования включая SHA1 и SHA256 https://en.wikipedia.org/wiki/Intel_SHA_extensions
Как показала практика на процессоре вычисление SHA1 выполняется примерно в 3 раза быстрее чем функциями PB.
Нужна версия PB не ниже 6.00 (или придется заменить компилятор фасма на версию из 6.00).

Код:
CompilerIf #PB_Compiler_Processor <> #PB_Processor_x64
  CompilerError "Поддерживается только x64 платформа"
CompilerEndIf
CompilerIf #PB_Compiler_Version>=600
  CompilerIf #PB_Compiler_Backend <> #PB_Backend_Asm
    CompilerError "Поддерживается только компилятор ассемблера"
  CompilerEndIf
CompilerElse
  CompilerError "FASM не поддерживает SHA1 инструкции"
CompilerEndIf


DeclareModule CPU_SHA1
  Declare IsCPU_SHA()
  Declare CPU_StartFingerprint()
  Declare CPU_CopyInstance(*Sha)
  Declare CPU_AddFingerprintBuffer(*Sha, *Buffer, Size)
  Declare.s CPU_GetSHA(*Sha)
  Declare.s CPU_FinishFingerprint(*Sha)
  Declare.s CPU_Fingerprint(*Buffer, Size)
  Declare.s CPU_StringFingerprint(s.s)
EndDeclareModule

Module CPU_SHA1
  EnableExplicit
  
  #SHA1_ChunksSize = 64
  
  Structure SHA_Data Align #PB_Structure_AlignC
    xmm0.M128A
    xmm1.M128A
    AllSize.q
    Buff.a[#SHA1_ChunksSize]
    BuffSize.a
  EndStructure
  
  Procedure SetReg(*Sha.SHA_Data)
    Protected xmm.M128A, *p
    
    xmm = *Sha\xmm0
    !movdqu xmm0, dqword[p.v_xmm]
    xmm = *Sha\xmm1
    !movdqu xmm1, dqword[p.v_xmm]
    *p = ?PSHUFFLE_BYTE_FLIP_MASK
    !mov rdi,[p.p_p]
    !movdqu xmm7,[rdi]
    
    DataSection 
      PSHUFFLE_BYTE_FLIP_MASK:
      Data.q $08090a0b0c0d0e0f, $0001020304050607  ; like "bswap"
    EndDataSection
  EndProcedure
  
  Procedure GetReg(*Sha.SHA_Data)
    Protected *xmm.M128A
    
    *xmm = *Sha\xmm0
    !mov rdi,[p.p_xmm]
    !movdqu [rdi],xmm0
    
    *xmm = *Sha\xmm1
    !mov rdi,[p.p_xmm]
    !movdqu [rdi],xmm1
  EndProcedure
  
  
  Procedure SHA1_Calc(*Buff, CountChunks)
    !mov rsi,[p.p_Buff]
    !mov rcx,[p.v_CountChunks]

    !@@:
    !movdqa xmm8,xmm1
    !movdqa xmm9,xmm0
    ;Rounds 0-3
    !movdqu xmm3,[rsi]
    !pshufb xmm3,xmm7
    !paddd xmm1,xmm3
    !movdqa xmm2,xmm0
    !sha1rnds4 xmm0,xmm1,0
    ;Rounds 4-7
    !movdqu xmm4,[rsi+16]
    !pshufb xmm4,xmm7
    !sha1nexte xmm2,xmm4
    !movdqa xmm1,xmm0
    !sha1rnds4 xmm0,xmm2,0
    !sha1msg1 xmm3,xmm4
    ;Rounds 8-11
    !movdqu xmm5,[rsi+32]
    !pshufb xmm5,xmm7
    !sha1nexte xmm1,xmm5
    !movdqa xmm2,xmm0
    !sha1rnds4 xmm0,xmm1,0
    !sha1msg1 xmm4,xmm5
    !pxor xmm3,xmm5
    ;Rounds 12-15
    !movdqu xmm6,[rsi+48]
    !pshufb xmm6,xmm7
    !sha1nexte xmm2,xmm6
    !movdqa xmm1,xmm0
    !sha1msg2 xmm3,xmm6
    !sha1rnds4 xmm0,xmm2,0
    !sha1msg1 xmm5,xmm6
    !pxor xmm4,xmm6
    ;Rounds 16-19
    !sha1nexte xmm1,xmm3
    !movdqa xmm2,xmm0
    !sha1msg2 xmm4,xmm3
    !sha1rnds4 xmm0,xmm1,0
    !sha1msg1 xmm6,xmm3
    !pxor xmm5,xmm3
    ;Rounds 20-23
    !sha1nexte xmm2,xmm4
    !movdqa xmm1,xmm0
    !sha1msg2 xmm5,xmm4
    !sha1rnds4 xmm0,xmm2,1
    !sha1msg1 xmm3,xmm4
    !pxor xmm6,xmm4
    ;Rounds 24-27
    !sha1nexte xmm1,xmm5
    !movdqa xmm2,xmm0
    !sha1msg2 xmm6,xmm5
    !sha1rnds4 xmm0,xmm1,1
    !sha1msg1 xmm4,xmm5
    !pxor xmm3,xmm5
    ;Rounds 28-31
    !sha1nexte xmm2,xmm6
    !movdqa xmm1,xmm0
    !sha1msg2 xmm3,xmm6
    !sha1rnds4 xmm0,xmm2,1
    !sha1msg1 xmm5,xmm6
    !pxor xmm4,xmm6
    ;Rounds 32-35
    !sha1nexte xmm1,xmm3
    !movdqa xmm2,xmm0
    !sha1msg2 xmm4,xmm3
    !sha1rnds4 xmm0,xmm1,1
    !sha1msg1 xmm6,xmm3
    !pxor xmm5,xmm3
    ;Rounds 36-39
    !sha1nexte xmm2,xmm4
    !movdqa xmm1,xmm0
    !sha1msg2 xmm5,xmm4
    !sha1rnds4 xmm0,xmm2,1
    !sha1msg1 xmm3,xmm4
    !pxor xmm6,xmm4
    ;Rounds 40-43
    !sha1nexte xmm1,xmm5
    !movdqa xmm2,xmm0
    !sha1msg2 xmm6,xmm5
    !sha1rnds4 xmm0,xmm1,2
    !sha1msg1 xmm4,xmm5
    !pxor xmm3,xmm5
    ;Rounds 44-47
    !sha1nexte xmm2,xmm6
    !movdqa xmm1,xmm0
    !sha1msg2 xmm3,xmm6
    !sha1rnds4 xmm0,xmm2,2
    !sha1msg1 xmm5,xmm6
    !pxor xmm4,xmm6
    ;Rounds 48-51
    !sha1nexte xmm1,xmm3
    !movdqa xmm2,xmm0
    !sha1msg2 xmm4,xmm3
    !sha1rnds4 xmm0,xmm1,2
    !sha1msg1 xmm6,xmm3
    !pxor xmm5,xmm3
    ;Rounds 52-55
    !sha1nexte xmm2,xmm4
    !movdqa xmm1,xmm0
    !sha1msg2 xmm5,xmm4
    !sha1rnds4 xmm0,xmm2,2
    !sha1msg1 xmm3,xmm4
    !pxor xmm6,xmm4
    ;Rounds 56-59
    !sha1nexte xmm1,xmm5
    !movdqa xmm2,xmm0
    !sha1msg2 xmm6,xmm5
    !sha1rnds4 xmm0,xmm1,2
    !sha1msg1 xmm4,xmm5
    !pxor xmm3,xmm5
    ;Rounds 60-63
    !sha1nexte xmm2,xmm6
    !movdqa xmm1,xmm0
    !sha1msg2 xmm3,xmm6
    !sha1rnds4 xmm0,xmm2,3
    !sha1msg1 xmm5,xmm6
    !pxor xmm4,xmm6
    ;Rounds 64-67
    !sha1nexte xmm1,xmm3
    !movdqa xmm2,xmm0
    !sha1msg2 xmm4,xmm3
    !sha1rnds4 xmm0,xmm1,3
    !sha1msg1 xmm6,xmm3
    !pxor xmm5,xmm3
    ;Rounds 68-71
    !sha1nexte xmm2,xmm4
    !movdqa xmm1,xmm0
    !sha1msg2 xmm5,xmm4
    !sha1rnds4 xmm0,xmm2,3
    !pxor xmm6,xmm4
    ;Rounds 72-75
    !sha1nexte xmm1,xmm5
    !movdqa xmm2,xmm0
    !sha1msg2 xmm6,xmm5
    !sha1rnds4 xmm0,xmm1,3
    ;Rounds 76-79
    !sha1nexte xmm2,xmm6
    !movdqa xmm1,xmm0
    !sha1rnds4 xmm0,xmm2,3
    
    ;Add current hash values with previously saved
    !sha1nexte xmm1,xmm8
    !paddd xmm0,xmm9
    
    !add rsi,64
    !dec rcx                     ;Chunks
    !jnz @b
  EndProcedure
  
  
  ; *****************
  ;- **** Public ****
  ; *****************
  
  Procedure IsCPU_SHA()
    Protected x.l=0
    
    !mov eax,7
    !xor ecx,ecx
    !cpuid
    !mov dword [p.v_x], ebx
    
    ProcedureReturn Bool(x & $20000000)
  EndProcedure
  
  Procedure CPU_StartFingerprint()
    Protected *p.SHA_Data = 0
    
    *p = AllocateStructure(SHA_Data)
    If *p
      With *p
        \BuffSize=0
        \AllSize=0
        CopyMemory(?CONST_H0_H4, @\xmm0, 16)
        CopyMemory(?CONST_H0_H4+16, @\xmm1, 16)
      EndWith
    EndIf
    
    ProcedureReturn *p
    
    DataSection
      CONST_H0_H4:
      Data.l $10325476, $98BADCFE, $0EFCDAB89, $67452301, 0, 0, 0, $0C3D2E1F0  ; Start-Values H0-H4
    EndDataSection
  EndProcedure
  
  Procedure CPU_CopyInstance(*Sha.SHA_Data)
    Protected *p=0
    
    If *Sha
      *p = AllocateStructure(SHA_Data)
      If *p
        CopyStructure(*Sha, *p, SHA_Data)
      EndIf
    EndIf
    
    ProcedureReturn *p
  EndProcedure
  
  Procedure CPU_AddFingerprintBuffer(*Sha.SHA_Data, *Buffer, Size)
    Protected r = #False, *p=0, x, BuffPos=0
    
    If *Sha And *Buffer And Size>0
      r = #True
      With *Sha
        If \BuffSize>0
          If \BuffSize+Size<=#SHA1_ChunksSize
            CopyMemory(*Buffer, @\Buff[\BuffSize], Size)
            \BuffSize+Size
            Size=0
          Else
            x=#SHA1_ChunksSize-\BuffSize
            CopyMemory(*Buffer, @\Buff[\BuffSize], x)
            SetReg(*Sha)
            SHA1_Calc(@\Buff, 1)
            GetReg(*Sha)
            \AllSize + #SHA1_ChunksSize
            \BuffSize=0
            BuffPos = x
            Size - x
          EndIf
        EndIf
        
        If Size>0
          x = Size / #SHA1_ChunksSize
          If x > 0
            SetReg(*Sha)
            SHA1_Calc(*Buffer + BuffPos, x)
            GetReg(*Sha)
            \AllSize + x * #SHA1_ChunksSize
          EndIf
          
          x = Size % #SHA1_ChunksSize
          If x>0
            CopyMemory(*Buffer + BuffPos + (Size-x), @\Buff[\BuffSize], x)
            \BuffSize+x
          EndIf
        EndIf
      EndWith
      
    EndIf
    
    ProcedureReturn r
  EndProcedure
  
  Procedure.s CPU_GetSHA(*Sha.SHA_Data)
    Protected r.s, Size, *p=0, i
    If *Sha
      *p = AllocateMemory(#SHA1_ChunksSize)
      If *p
        
        With *Sha
          If (\BuffSize=0 Or \BuffSize>=56) And \BuffSize<#SHA1_ChunksSize
            \Buff[\BuffSize]=$80
            For i=\BuffSize+1 To #SHA1_ChunksSize-1
              \Buff[i]=0
            Next
            i=\AllSize+\BuffSize
            !mov rax,[p.v_i]
            !shl rax,3
            !bswap rax
            !mov [p.v_i],rax  ;Bits to encoded
            If \BuffSize=0
              PokeB(*p, $80)
            EndIf
            PokeQ(*p + #SHA1_ChunksSize - 8, i)
            SetReg(*Sha)
            If \BuffSize>0
              SHA1_Calc(@\Buff, 1)
            EndIf
            SHA1_Calc(*p, 1)
          ElseIf \BuffSize<56
            \Buff[\BuffSize]=$80
            i=\AllSize+\BuffSize
            !mov rax,[p.v_i]
            !shl rax,3
            !bswap rax
            !mov [p.v_i],rax  ;Bits to encoded
            PokeQ(@\Buff[56], i)
            SetReg(*Sha)
            SHA1_Calc(@\Buff, 1)
          Else
            CallDebugger
          EndIf
        EndWith
        
        !mov rdi,[p.p_p]
        !pshufd xmm0,xmm0,1bh
        !movdqu [rdi],xmm0
        !pextrd [rdi+16],xmm1,3
        
        For i = 0 To 16 Step 4
          r + RSet(Hex(PeekL(*p + i) & $FFFFFFFF), 8, "0")
        Next
        
        FreeMemory(*p)
      EndIf
    EndIf
    ProcedureReturn r
  EndProcedure
  
  Procedure.s CPU_FinishFingerprint(*Sha.SHA_Data)
    Protected r.s
    
    If *Sha
      r = CPU_GetSHA(*Sha)
      FreeStructure(*Sha)
    EndIf
    
    ProcedureReturn r
  EndProcedure
  
  Procedure.s CPU_Fingerprint(*Buffer, Size)
    Protected r.s, *p
    
    *p=CPU_StartFingerprint()
    If *p
      CPU_AddFingerprintBuffer(*p, *Buffer, Size)
      r = CPU_FinishFingerprint(*p)
    EndIf
    
    ProcedureReturn r
  EndProcedure
  
  
  Procedure.s CPU_StringFingerprint(s.s)
    Protected r.s, *p=UTF8(s)
    
    If *p
      r = CPU_Fingerprint(*p, MemorySize(*p)-1)
      FreeMemory(*p)
    EndIf
    
    ProcedureReturn r
  EndProcedure
EndModule

В первую очередь проверьте поддерживает ли процессор необходимые инструкции.

Код:
UseModule CPU_SHA1

If IsCPU_SHA()
  Debug "SHA инструкции поддерживаются"
Else
  Debug "SHA инструкции НЕ поддерживаются"
EndIf

Если не поддерживает, значит пора обновлять комп. :tomato:  :dontknow:

Стандартный тест из вики

Код:
UseSHA1Fingerprint()

UseModule CPU_SHA1

s.s="В чащах юга жил бы цитрус? Да, но фальшивый экземпляр!"
Debug CPU_StringFingerprint(s)
Debug StringFingerprint(s, #PB_Cipher_SHA1)

Тоже с лисицей и собакой

Код:
UseSHA1Fingerprint()

UseModule CPU_SHA1

s.s="The quick brown fox jumps over the lazy dog."
Debug CPU_StringFingerprint(s)
Debug StringFingerprint(s, #PB_Cipher_SHA1)

Хеширование 1 ГБ случайных данных для сравнения скорости CPU и функций PB.

Код:
UseSHA1Fingerprint()

UseModule CPU_SHA1

Count = 100
Size=10*1024*1024
*Buff = AllocateMemory(Size)
If *Buff
  RandomData(*Buff, Size)
  
  Define sPB.s, sCPU.s, tPB, tCPU, i
  
  tPB = ElapsedMilliseconds()
  If StartFingerprint(0, #PB_Cipher_SHA1)
    For i = 1 To Count
      AddFingerprintBuffer(0, *Buff, Size)
    Next
    sPB = UCase(FinishFingerprint(0))
  EndIf
  tPB = ElapsedMilliseconds() - tPB
  
  tCPU = ElapsedMilliseconds()
  *p=CPU_StartFingerprint()
  If *p
    For i = 1 To Count
      CPU_AddFingerprintBuffer(*p, *Buff, Size)
    Next
    sCPU = CPU_FinishFingerprint(*p)
  EndIf
  tCPU = ElapsedMilliseconds() - tCPU
  
  MessageRequester("",~"PB \nВремя = "+tPB+~" мс\n"+sPB+~"\n\nCPU\nВремя = "+tCPU+~" мс\n"+sCPU)
  
  FreeMemory(*Buff)
EndIf

0

2

при замене "FASM.EXE" в папке компиллятора из последней версии flat assembler
https://flatassembler.net/download.php
начинают поддерживаться и версии ниже 6.0, конечно же без всех этих "CompilerIf.."

0

3

bizdon написал(а):

начинают поддерживаться и версии ниже 6.0, конечно же без всех этих "CompilerIf.."

Собственно в этом и смысл сообщения "FASM не поддерживает SHA1 инструкции".
Это лучше чем сообщение об ошибке

Код:
PureBasic - Assembler error
---------------------------
PureBasic.asm [863]:
sha1rnds4 xmm0,xmm1,0
error: illegal instruction.

0

4

FASM не поддерживает SHA1 инструкции

Наверное, лучше написать: "старый FASM, входящий в состав PB не поддерживает SHA1 инструкции" 8-)

0


Вы здесь » PureBasic - форум » OpenSource » Аппартаная поддержка процессором хеширования SHA1