sha1 fingerprint string

Share your advanced PureBasic knowledge/code with the community.
User avatar
eddy
Addict
Addict
Posts: 1479
Joined: Mon May 26, 2003 3:07 pm
Location: Nantes

sha1 fingerprint string

Post 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 
Last edited by eddy on Thu Aug 09, 2007 10:20 pm, edited 1 time in total.
Imagewin10 x64 5.72 | IDE | PB plugin | Tools | Sprite | JSON | visual tool
CherokeeStalker
User
User
Posts: 66
Joined: Fri Oct 17, 2003 2:42 am

BUG FOUND !

Post 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]
User avatar
eddy
Addict
Addict
Posts: 1479
Joined: Mon May 26, 2003 3:07 pm
Location: Nantes

Post by eddy »

[bug fixed]

Ok ... It was a little bug. :) ( HEX conversions at the end of function )
Imagewin10 x64 5.72 | IDE | PB plugin | Tools | Sprite | JSON | visual tool
Karbon
PureBasic Expert
PureBasic Expert
Posts: 2010
Joined: Mon Jun 02, 2003 1:42 am
Location: Ashland, KY
Contact:

Re: sha1 fingerprint string

Post 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!
-Mitchell
Check out kBilling for all your billing software needs!
http://www.k-billing.com
Code Signing / Authenticode Certificates (Get rid of those Unknown Publisher warnings!)
http://codesigning.ksoftware.net
SFSxOI
Addict
Addict
Posts: 2970
Joined: Sat Dec 31, 2005 5:24 pm
Location: Where ya would never look.....

Re: sha1 fingerprint string

Post 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
Last edited by SFSxOI on Mon May 17, 2010 10:01 pm, edited 2 times in total.
The advantage of a 64 bit operating system over a 32 bit operating system comes down to only being twice the headache.
Karbon
PureBasic Expert
PureBasic Expert
Posts: 2010
Joined: Mon Jun 02, 2003 1:42 am
Location: Ashland, KY
Contact:

Re: sha1 fingerprint string

Post 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 ;-)
-Mitchell
Check out kBilling for all your billing software needs!
http://www.k-billing.com
Code Signing / Authenticode Certificates (Get rid of those Unknown Publisher warnings!)
http://codesigning.ksoftware.net
SFSxOI
Addict
Addict
Posts: 2970
Joined: Sat Dec 31, 2005 5:24 pm
Location: Where ya would never look.....

Re: sha1 fingerprint string

Post 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.
The advantage of a 64 bit operating system over a 32 bit operating system comes down to only being twice the headache.
infratec
Always Here
Always Here
Posts: 7623
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: sha1 fingerprint string

Post 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
Last edited by infratec on Tue May 18, 2010 1:11 pm, edited 1 time in total.
Karbon
PureBasic Expert
PureBasic Expert
Posts: 2010
Joined: Mon Jun 02, 2003 1:42 am
Location: Ashland, KY
Contact:

Re: sha1 fingerprint string

Post by Karbon »

#Byte needs to be #PB_Byte but other than that, yep, it works with 4.41!
-Mitchell
Check out kBilling for all your billing software needs!
http://www.k-billing.com
Code Signing / Authenticode Certificates (Get rid of those Unknown Publisher warnings!)
http://codesigning.ksoftware.net
infratec
Always Here
Always Here
Posts: 7623
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: sha1 fingerprint string

Post 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
infratec
Always Here
Always Here
Posts: 7623
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: sha1 fingerprint string

Post 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
Post Reply