Page 1 of 1

sha1 fingerprint string

Posted: Sat Aug 04, 2007 2:17 am
by eddy
Check if it works ...
Make some tests : http://outils-en-ligne.uzabnet.com/gene ... -ligne.php

Code: Select all

;{ FUNCTIONS AND MARCO } 

;circular 32bits left shift 
Procedure.l ROL(val, shift) 
  Protected v1.q = 0 
  PokeL(@v1,val) 
  v1 << shift 
  ProcedureReturn PeekL(@v1) | PeekL(@v1+4) 
EndProcedure 

Macro STRING_POINTER_(str,posPointer) 
  Asc(Mid(str,posPointer+1,1)) 
EndMacro 

Macro CPY_ARRAY_(toArr,fromArr,fromArrIndex,length,dataType=Long) 
  CopyMemory(@fromArr(fromArrIndex),@toArr(0),SizeOf(dataType)*length)  
EndMacro 

;} 

Procedure$ SHA1(in$) 
  #SHA1_ROUND1 = $5A827999 ;SHA1 Constants 
  #SHA1_ROUND2 = $6ED9EBA1 
  #SHA1_ROUND3 = $8F1BBCDC 
  #SHA1_ROUND4 = $CA62C1D6 
  
  Protected h0 = $67452301, h1 = $EFCDAB89, h2 = $98BADCFE ;Intermediate Hash 
  Protected h3 = $10325476, h4 = $C3D2E1F0                 ;Intermediate Hash 
  Protected a,b,c,d,e ;Word buffer 
  Protected t         ;Temporary word Value 
  
  Protected in_length.l = Len(in$) 
  Protected in_length_quad.q = in_length 
  Protected datas_length.l = (((in_length + 8) >> 6) + 1) << 4 
  Dim datas.l(datas_length) 
  
  For k=0 To in_length-1 
    datas(k >> 2) = (datas(k >> 2) << 8) | (STRING_POINTER_(in$,k) & $FF) 
  Next 
  
  datas(in_length >> 2) = ((datas(in_length >> 2)<< 8) | $80) << ((3 - (in_length & 3))<< 3) 
  datas(datas_length - 2) = (in_length_quad * 8) >> 32 
  datas(datas_length - 1) = (in_length_quad * 8) & $FFFFFFFF 
  
  For chunkStart=0 To datas_length-1 Step 16 
    a = h0 : b = h1 : c = h2 : d = h3 : e = h4 
    
    Dim w.l(80)                       ;Word sequence                
    CPY_ARRAY_(w,datas,chunkStart,16) ;Init first 16 Words 
    For i=16 To 79 
      w(i) = ROL(w(i - 3) ! w(i - 8) ! w(i - 14) ! w(i - 16), 1) 
    Next 
    
    ;Round 1 
    For i=0 To 19 
      t = #SHA1_ROUND1 + ROL(a, 5) + (d ! (b & (c ! d))) + e + w(i) 
      
      e = d : d = c 
      c = ROL(b, 30) 
      b = a : a = t 
    Next 
    ;Round 2 
    For i=20 To 39 
      t = #SHA1_ROUND2 + ROL(a, 5) + (b ! c ! d) + e + w(i) 
      
      e = d : d = c 
      c = ROL(b, 30) 
      b = a : a = t 
    Next 
    ;Round 3 
    For i=40 To 59 
      t = #SHA1_ROUND3 + ROL(a, 5) + ((b & c) | (d & (b | c))) + e + w(i) 
      
      e = d : d = c 
      c = ROL(b, 30) 
      b = a : a = t 
    Next 
    ;Round 4 
    For i=60 To 79 
      t = #SHA1_ROUND4 + ROL(a, 5) + (b ! c ! d) + e + w(i) 
      
      e = d : d = c 
      c = ROL(b, 30) 
      b = a : a = t 
    Next 
    
    h0 + a : h1 + b : h2 + c : h3 + d : h4 + e 
  Next 
   
  ProcedureReturn LCase(RSet(Hex(h0),8,"0") + RSet(Hex(h1),8,"0") + RSet(Hex(h2),8,"0") + RSet(Hex(h3),8,"0") + RSet(Hex(h4),8,"0")) 
EndProcedure 

If OpenConsole() 
  PrintN(SHA1("iNiQuiTy"))  
  PrintN("0a4dd0f633b7e5cd5520bcad12331a65f6b9dac7 ") 
  Input() 
EndIf 

BUG FOUND !

Posted: Thu Aug 09, 2007 4:11 am
by CherokeeStalker
This returns only a 39 character result for the string "iNiQuiTy" - no quotes,
not a 40 character result ! It drops the leading '0' !

Result using your code : a4dd0f633b7e5cd5520bcad12331a65f6b9dac7
Result using site above : 0a4dd0f633b7e5cd5520bcad12331a65f6b9dac7
[/b]

Posted: Thu Aug 09, 2007 10:23 pm
by eddy
[bug fixed]

Ok ... It was a little bug. :) ( HEX conversions at the end of function )

Re: sha1 fingerprint string

Posted: Mon May 17, 2010 6:40 pm
by Karbon
Has anyone else tried this with PB 4.41? I've been looking for an all-PB implementation of SHA1 (yes, I know there is a built in function but I have my reasons ;)).

I'm getting pretty different results. With his test string :


PB Built-in 0a4dd0f633b7e5cd5520bcad12331a65f6b9dac7
All PB : 0a4dd0f633b7e5cd5520bcad12331a65ffffffff

**** Geeze, if I'd taken 10 seconds to look...

Fixed for PB 4.41 (just changed some variable types to quads)

Code: Select all

;{ FUNCTIONS AND MARCO }

;circular 32bits left shift
Procedure.l ROL(val, shift)
  Protected v1.q = 0
  PokeL(@v1,val)
  v1 << shift
  ProcedureReturn PeekL(@v1) | PeekL(@v1+4)
EndProcedure

Macro STRING_POINTER_(str,posPointer)
  Asc(Mid(str,posPointer+1,1))
EndMacro

Macro CPY_ARRAY_(toArr,fromArr,fromArrIndex,length,dataType=Long)
  CopyMemory(@fromArr(fromArrIndex),@toArr(0),SizeOf(dataType)*length) 
EndMacro

;}

Procedure$ SHA1(in$)
  #SHA1_ROUND1 = $5A827999 ;SHA1 Constants
  #SHA1_ROUND2 = $6ED9EBA1
  #SHA1_ROUND3 = $8F1BBCDC
  #SHA1_ROUND4 = $CA62C1D6
 
  Protected h0.q = $67452301, h1.q = $EFCDAB89, h2.q = $98BADCFE ;Intermediate Hash
  Protected h3.q = $10325476, h4.q = $C3D2E1F0                 ;Intermediate Hash
  Protected a,b,c,d,e ;Word buffer
  Protected t         ;Temporary word Value
 
  Protected in_length.l = Len(in$)
  Protected in_length_quad.q = in_length
  Protected datas_length.l = (((in_length + 8) >> 6) + 1) << 4
  Dim datas.l(datas_length)
 
  For k=0 To in_length-1
    datas(k >> 2) = (datas(k >> 2) << 8) | (STRING_POINTER_(in$,k) & $FF)
  Next
 
  datas(in_length >> 2) = ((datas(in_length >> 2)<< 8) | $80) << ((3 - (in_length & 3))<< 3)
  datas(datas_length - 2) = (in_length_quad * 8) >> 32
  datas(datas_length - 1) = (in_length_quad * 8) & $FFFFFFFF
 
  For chunkStart=0 To datas_length-1 Step 16
    a = h0 : b = h1 : c = h2 : d = h3 : e = h4
   
    Dim w.l(80)                       ;Word sequence               
    CPY_ARRAY_(w,datas,chunkStart,16) ;Init first 16 Words
    For i=16 To 79
      w(i) = ROL(w(i - 3) ! w(i - 8) ! w(i - 14) ! w(i - 16), 1)
    Next
   
    ;Round 1
    For i=0 To 19
      t = #SHA1_ROUND1 + ROL(a, 5) + (d ! (b & (c ! d))) + e + w(i)
     
      e = d : d = c
      c = ROL(b, 30)
      b = a : a = t
    Next
    ;Round 2
    For i=20 To 39
      t = #SHA1_ROUND2 + ROL(a, 5) + (b ! c ! d) + e + w(i)
     
      e = d : d = c
      c = ROL(b, 30)
      b = a : a = t
    Next
    ;Round 3
    For i=40 To 59
      t = #SHA1_ROUND3 + ROL(a, 5) + ((b & c) | (d & (b | c))) + e + w(i)
     
      e = d : d = c
      c = ROL(b, 30)
      b = a : a = t
    Next
    ;Round 4
    For i=60 To 79
      t = #SHA1_ROUND4 + ROL(a, 5) + (b ! c ! d) + e + w(i)
     
      e = d : d = c
      c = ROL(b, 30)
      b = a : a = t
    Next
   
    h0 + a : h1 + b : h2 + c : h3 + d : h4 + e
  Next
   
  ProcedureReturn LCase(RSet(Hex(h0),8,"0") + RSet(Hex(h1),8,"0") + RSet(Hex(h2),8,"0") + RSet(Hex(h3),8,"0") + RSet(Hex(h4),8,"0"))
EndProcedure

If OpenConsole()
  PrintN(SHA1("iNiQuiTy")) 
  PrintN("0a4dd0f633b7e5cd5520bcad12331a65f6b9dac7 ")
  Input()
EndIf 

******************** OK, so it's gonna take a little longer than 10 seconds.. Something still isn't right there. If anyone else sees it before I do, let me know!

Re: sha1 fingerprint string

Posted: Mon May 17, 2010 9:47 pm
by SFSxOI
@eddy > your code does not work here - gives different hash for 'iNiQuiTy' then the compared hash. It gives this:

0a4dd0f633b7e5cd5520bcad12331a65ffffffff
0a4dd0f633b7e5cd5520bcad12331a65f6b9dac7

Its all the same up to the end 8 character end when it just gives ffffffff

Re: sha1 fingerprint string

Posted: Mon May 17, 2010 9:53 pm
by Karbon
Are you sure? I've been on the phone since I posted this so I haven't had time to take any sort of a deeper look but this is the result I get :

From the code : 0a4dd0f6133b7e5c5520bcad12331a65f6b9dac7

The Real SHA-1 hash 0a4dd0f633b7e5cd5520bcad12331a65f6b9dac7

differences :

0a4d-d0f6-133b-7e5c-5520-bcad-1233-1a65-f6b9-dac7
************
0a4d-d0f6-33b7-e5cd-5520-bcad-1233-1a65-f6b9-dac7

Notice those differences.. It's *almost* right ;-)

Re: sha1 fingerprint string

Posted: Mon May 17, 2010 9:58 pm
by SFSxOI
OK, took a closer look, this is what i get:

0a4dd0f6133b7e5c5520bcad12331a65f6b9dac7
0a4dd0f633b7e5cd5520bcad12331a65f6b9dac7

so yeah, i was mistaken, its almost righ, but not really. it looks about the same at first glance, but when you break it down you see the differences, sorry 'bout that.

Re: sha1 fingerprint string

Posted: Tue May 18, 2010 8:24 am
by infratec
Hi eddy,

found this with an internet search engine :)

Code: Select all

; German forum: http://www.purebasic.fr/german/viewtopic.php?t=1385&highlight=
; Author: andi256 (updated for PB 4.00 by Andre + Helle)
; Date: 29. December 2004
; OS: Windows
; Demo: Yes

; SHA Algorithmus
; ------------------
; Fingerabdruck (Hashcode) von Daten. Dieser Code hat die Eigenschaft, nicht
; zurückgerechnet werden zu können. Also aus dem Fingerabdruck (zB MD5 oder
; SHA-1) kann der ursprüngliche Datensatz nicht zurückgerechnet werden.

; Das schöne ist, dass auch nur ein verändertes Bit am Ursprungsdatensatz den
; Fingerabdruck stark und fast nicht vorherzusehen verändert. Demnach kann
; man die Integrität von z.B. Dateien etc. testen (Erweiterung dazu ist die
; Digitale Signatur, in der Hashcodes auch eine grosse Rolle spielen).
; Desweiteren kann man Passwörter nur als Fingerabdruck speichern (also nur
; den Hashcode) und später so vorgehen, dass man das eingegebene Passwort
; durch den Hash-Algorithmus jagt und dann das Ergebnis mit dem gespeicherten
; Hash vergleicht. Somit kann man feststellen, ob es das selbe Passwort war.
; Allerdings ist das Passwort selbst nicht wiederherstellbar oder
; herauszufinden und demnach sehr sicher verpackt.

; Weitere Info's zu SHA-1:
; http://de.wikipedia.org/wiki/SHA-1


Global Dim state.l(4)
Global Dim magic.l(4)
Global Dim w.l(80)

;Procedure UpeekB(*mem)
;  ProcedureReturn Val(StrU(PeekB(*mem),#PB_Byte))
;EndProcedure

Procedure.s speicherout_hex(*mem,l,q$)
  For i = 0 To l-1
    q$ = q$ + RSet(Hex(PeekA(*mem+i)),2,"0") + " "
  Next i
  ProcedureReturn q$
EndProcedure

Procedure toLE(value)
  dummy1 = ((value >> 24) & $FF)
  dummy2 = ((value >> 8) & $FF00)
  dummy3 = ((value & $FF) << 24)
  dummy4 = ((value & $FF00) << 8)
  dummy5 = dummy1 |dummy2 |dummy3 |dummy4
  ProcedureReturn dummy5
EndProcedure

Procedure RotL(num,count) ; rotate left
  If count>0 And count<32
    !MOV dword ECX,[p.v_count]
    !ROL dword [p.v_num],cl
  EndIf
  ProcedureReturn num
EndProcedure

Procedure f(round,x,y,z)
  If round < 20
    dummy = ( x & y ) | ( ~x & z )
  Else
    If round < 40
      dummy = ( x ! y ! z )
    Else
      If round < 60
        dummy = ( x & y ) | ( x & z ) | ( y & z )
      Else
        dummy = ( x ! y ! z )
      EndIf
    EndIf
  EndIf
  ProcedureReturn dummy
EndProcedure

Procedure SHA_1(*digest,*buf,len,pad,ende)

  magic(0) = $5A827999
  magic(1) = $6ED9EBA1
  magic(2) = $8F1BBCDC
  magic(3) = $CA62C1D6

  *databuf = AllocateMemory(64)

  state(0) = $67452301
  state(1) = $EFCDAB89
  state(2) = $98BADCFE
  state(3) = $10325476
  state(4) = $C3D2E1F0

  blocks = (len + 3 + 63) >> 6
  bytes_left = len
  If (pad|ende) = #True
    len=0
    Debug "len : " +Str(len)
  EndIf

  For i=0 To blocks-1
    If bytes_left >= 64
      CopyMemory(*buf,*databuf, 64)
      buf = buf + 64
      bytes_left = bytes_left - 64
    Else
      j=0
      If bytes_left > 0
        CopyMemory(*buf,*databuf,bytes_left)
        j = bytes_left
      EndIf
      If bytes_left >= 0
        PokeB(*databuf+j,Ende)
        j = j + 1
        bytes_left = -1
      EndIf
      For  j = j To 61
        PokeB(*databuf+j,pad)
      Next j

      If j=62
        dummy = ((8*len) >> 8) & $FF
        PokeB(*databuf+62,dummy)
        j = j + 1
      EndIf
      If j=63
        dummy = (8*len) & $FF
        PokeB(*databuf+63,((8*len) & $FF))
      EndIf
    EndIf

    CopyMemory(*databuf,@w(0),64)

    For j=0 To 15
      w(j)= toLE(w(j))
    Next j

    For j=16 To 79
      w(j) = RotL(w(j-3) ! w(j-8) ! w(j-14) ! w(j-16),1)
    Next j

    a = state(0)
    b = state(1)
    c = state(2)
    d = state(3)
    e = state(4)

    For j=0 To 79
      t= RotL(a,5) + f(j,b,c,d) + e + w(j) + magic(j/20)
      e = d
      d = c
      c = RotL(b,30)
      b = a
      a = t
    Next j

    state(0) = state(0) + a
    state(1) = state(1) + b
    state(2) = state(2) + c
    state(3) = state(3) + d
    state(4) = state(4) + e


  Next i

  state(0) = toLE(state(0))
  state(1) = toLE(state(1))
  state(2) = toLE(state(2))
  state(3) = toLE(state(3))
  state(4) = toLE(state(4))

  CopyMemory(@state(0),*digest,20)

EndProcedure

OpenConsole()

Input.s = "iNiQuiTy"
;Input.s = "abc"
*digest = AllocateMemory(20)

sha_1(*digest,@input,Len(Input),0,$80)
PrintN(speicherout_hex(*digest,20,"ist   : "))

;PrintN ("soll  : A9 99 3E 36 47 06 81 6A BA 3E 25 71 78 50 C2 6C 9C D0 D8 9D")


PrintN ("soll  : 0a 4d d0 f6 33 b7 e5 cd 55 20 bc ad 12 33 1a 65 f6 b9 da c7")
Input()
CloseConsole()
It works correct.
I made a few modifications for PB 4.41.

The original code is here:
http://www.purearea.net/pb/CodeArchiv/E ... erPrint.pb

It works also with your ROL() procedure.

Best regards,

Bernd

Re: sha1 fingerprint string

Posted: Tue May 18, 2010 1:06 pm
by Karbon
#Byte needs to be #PB_Byte but other than that, yep, it works with 4.41!

Re: sha1 fingerprint string

Posted: Tue May 18, 2010 1:16 pm
by infratec
Hi Karbon,

oh, mistake by me.
I first changed it to #PB_Byte, than I removed the complete procedure
and replaced the call with PeekA().

Later I thought I should provide the 'original' code and copied the procedure back in the code. :(
Sh.. happens.

Now I commented it out, because it is not needed.

Best regards,

Bernd

Re: sha1 fingerprint string

Posted: Tue May 18, 2010 1:48 pm
by infratec
@eddy

maybe something with the attachment of a 1 bit and padding with 0 is wrong/missing.


And why did you do this

Code: Select all

STRING_POINTER_(in$,k) & $FF
It is faster and easier to use

Code: Select all

PeekA(@in$ + k)
Bernd