SHA-1 or SHA1 is a one-way hash function;
it computes a 160-bit message digest.
SHA-1 often appears in security protocols; for example,
many HTTPS websites use RSA with SHA-1 to secure their connections.
BitTorrent uses SHA-1 to verify downloads.
Git and Mercurial use SHA-1 digests to identify commits.

A US government standard, FIPS 180-1, defines SHA-1.

Find the SHA-1 message digest for a string of octets. You may either call a SHA-1 library, or implement SHA-1 in your language. Both approaches interest Rosetta Code.



 Warning: SHA-1 has known weaknesses. Theoretical attacks may find a collision after 252 operations, or perhaps fewer.
This is much faster than a brute force attack of 280 operations. USgovernment deprecated SHA-1.
For production-grade cryptography, users may consider a stronger alternative, such as SHA-256 (from the SHA-2 family) or the upcoming SHA-3.


' version 18-10-2016
' started with SHA-1/FIPS-180-1
' but used the BBC BASIC native version to finish. 
' compile with: fbc -s console
 
Function SHA_1(test_str As String) As String
 
  Dim As String message = test_str   ' strings are passed as ByRef's
 
  Dim As Long i, j
  Dim As UByte Ptr ww1 
  Dim As UInteger<32> Ptr ww4 
 
  Dim As ULongInt l = Len(message)
  ' set the first bit after the message to 1
  message = message + Chr(1 Shl 7)
  ' add one char to the length
  Dim As ULong padding = 64 - ((l +1) Mod (512 \ 8)) ' 512 \ 8 = 64 char.
 
  ' check if we have enough room for inserting the length
  If padding < 8 Then padding = padding + 64
 
  message = message + String(padding, Chr(0))   ' adjust length
  Dim As ULong l1 = Len(message)                ' new length
 
  l = l * 8    ' orignal length in bits
  ' create ubyte ptr to point to l ( = length in bits)
  Dim As UByte Ptr ub_ptr = Cast(UByte Ptr, @l)
 
  For i = 0 To 7  'copy length of message to the last 8 bytes
    message[l1 -1 - i] = ub_ptr[i]
  Next
 
  Dim As UInteger<32> A, B, C, D, E, k, temp, W(0 To 79)
  Dim As UInteger<32> H0 = &H67452301
  Dim As UInteger<32> H1 = &HEFCDAB89
  Dim As UInteger<32> H2 = &H98BADCFE
  Dim As UInteger<32> H3 = &H10325476
  Dim As UInteger<32> H4 = &HC3D2E1F0
 
 
  For j = 0 To (l1 -1) \ 64 ' split into block of 64 bytes
    ww1 = Cast(Ubyte Ptr, @message[j * 64])
    ww4 = Cast(UInteger<32> Ptr, @message[j * 64])
 
    For i = 0 To 60 Step 4  'little endian -> big endian 
      Swap ww1[i   ], ww1[i +3]
      Swap ww1[i +1], ww1[i +2]
    Next
 
    For i = 0 To 15    ' copy the 16 32bit block into the array
      W(i) = ww4[i]
    Next
 
    For i = 16 To 79   ' fill the rest of the array
      temp = W(i -3) Xor W(i -8) Xor W(i -14) Xor W(i -16)
      temp = temp Shl 1 + temp Shr 31
      W(i) = temp
    Next
 
    A = h0 : B = h1 : C = h2 : D = h3 : E = h4
 
    For i = 0 To 79
      Select Case As Const i
        Case 0 To 19
          temp = (B And C) or ((Not B) And D)
          k = &H5A827999
        Case 20 To 39
          temp = B Xor C Xor D
          k = &H6ED9EBA1
        Case 40 To 59
          temp = (B And C) Or (B And D) Or (C And D)
          k = &H8F1BBCDC
        Case 60 To 79
          temp = B Xor C Xor D
          k = &hCA62C1D6
      End Select
 
      temp = A Shl 5 + A Shr 27 + temp + E + k + W(i)
      E = D
      D = C
      C = (B Shl 30) or (B Shr 2)
      B = A
      A = temp
 
    Next
 
    h0 += A : h1 += B : h2 += C : h3 += D : h4 += E 
 
  Next
 
  Return Hex(h0, 8) + Hex(h1, 8) + Hex(h2, 8) + Hex(h3, 8) + Hex(h4, 8)
 
End Function
 
' ------=< MAIN >=------
 
Dim As String test = "Rosetta Code"
Print test; " => "; SHA_1(test)
 
 
' empty keyboard buffer
While InKey <> "" : Wend
Print : Print "hit any key to end program"
Sleep
End