Thread: FoxPro Some General Questions/SHA1 and others cryptography (VFP)

SHA1 and others cryptography (VFP)
source

*!*    SHA1
*!*    Auteur : C.Chenavier
*!*    Version : 1.00 - 15/11/2004


FUNCTION SHA1( cMessage )

PRIVATE HO, H1, H2, H3, H4
LOCAL nNbBlocs, nHigh, nLow

H0 = 0x67452301
H1 = 0xEFCDAB89
H2 = 0x98BADCFE
H3 = 0x10325476
H4 = 0xC3D2E1F0

M.nNbBlocs = LEN(M.cMessage) / 64

M.nLen = LEN(M.cMessage)
M.nReste = MOD(M.nLen, 64)
IF M.nReste > 0 OR M.nLen = 0
   M.nNbBlocs = M.nNbBlocs + 1
   IF M.nReste > 55
      M.cMessage = M.cMessage + CHR(2^7) + REPLICATE(CHR(0), (64 - M.nReste) + 55)
      M.nNbBlocs = M.nNbBlocs + 1
   ELSE
      M.cMessage = M.cMessage + CHR(2^7) + REPLICATE(CHR(0), (55 - M.nReste))
   ENDIF
   M.nHigh = (M.nLen*8) / 2^32
   M.nLow = MOD(M.nLen*8, 2^32)
   M.cMessage = M.cMessage + CHR(BITAND(BITRSHIFT(M.nHigh, 24), 0xFF)) ;    && 56
                           + CHR(BITAND(BITRSHIFT(M.nHigh, 16), 0xFF)) ;    && 57
                           + CHR(BITAND(BITRSHIFT(M.nHigh, 8), 0xFF))  ;    && 58
                           + CHR(BITAND(M.nHigh, 0xFF)) ;                   && 59
                           + CHR(BITAND(BITRSHIFT(M.nLow, 24), 0xFF)) ;     && 60
                           + CHR(BITAND(BITRSHIFT(M.nLow, 16), 0xFF)) ;     && 61
                           + CHR(BITAND(BITRSHIFT(M.nLow, 8), 0xFF))  ;     && 62
                           + CHR(BITAND(M.nLow, 0xFF))                      && 63
ENDIF

LOCAL i

FOR I = 1 TO M.nNbBlocs
    DO SHA1_ProcessBloc WITH SUBSTR(M.cMessage, 1 + 64*(I-1), 64)
ENDFOR

RETURN SUBSTR(TRANSFORM(H0,"@0"),3) + ;
       SUBSTR(TRANSFORM(H1,"@0"),3) + ;
       SUBSTR(TRANSFORM(H2,"@0"),3) + ;
       SUBSTR(TRANSFORM(H3,"@0"),3) + ;
       SUBSTR(TRANSFORM(H4,"@0"),3)


PROCEDURE SHA1_ProcessBloc

LPARAMETERS cBloc

LOCAL I, A, B, C, D, E, nTemp
LOCAL ARRAY W(80)

FOR I = 1 TO 16
    W(I) = BITLSHIFT(ASC(SUBSTR(M.cBloc, (I-1) * 4 + 1, 1)), 24) + ;
           BITLSHIFT(ASC(SUBSTR(M.cBloc, (I-1) * 4 + 2, 1)), 16) + ;
           BITLSHIFT(ASC(SUBSTR(M.cBloc, (I-1) * 4 + 3, 1)), 8) + ;
           ASC(SUBSTR(M.cBloc, (I-1) * 4 + 4, 1))
ENDFOR

FOR I = 17 TO 80
    W(i) = BitLRotate(1, BITXOR(W(i-3), W(i-8), W(i-14), W(i-16)))
ENDFOR

A = H0
B = H1
C = H2
D = H3
E = H4

FOR I = 1 TO 20
    M.nTemp = BitLRotate(5,A) + BITOR(BITAND(B,C), BITAND(BITNOT(B), D)) + ;
              E + W(i) + 0x5A827999
    E = D
    D = C
    C = BitLRotate(30,B)
    B = A
    A = M.nTemp
ENDFOR

FOR I = 21 TO 40
    M.nTemp = BitLRotate(5,A) + BITXOR(B, C, D) + E + W(i) + 0x6ED9EBA1
    E = D
    D = C
    C = BitLRotate(30,B)
    B = A
    A = M.nTemp
ENDFOR

FOR I = 41 TO 60
    M.nTemp = BitLRotate(5,A) + BITOR(BITAND(B,C), BITAND(B,D), BITAND(C,D)) + ;
              E + W(i) + 0x8F1BBCDC
    E = D
    D = C
    C = BitLRotate(30,B)
    B = A
    A = M.nTemp
ENDFOR

FOR I = 61 TO 80
    M.nTemp = BitLRotate(5,A) + BITXOR(B, C, D) + E + W(i) + 0xCA62C1D6
    E = D
    D = C
    C = BitLRotate(30,B)
    B = A
    A = M.nTemp
ENDFOR

H0 = H0 + A
H1 = H1 + B
H2 = H2 + C
H3 = H3 + D
H4 = H4 + E

RETURN

FUNCTION BitLRotate( nBits, nWord )

RETURN BITLSHIFT(M.nWord, M.nBits) + BITRSHIFT(M.nWord, (32-(M.nBits)))



source of the Variant 2

* Function:      sha1encoder
* Description:   Perform an SHA1 encoding on a text parameter

FUNCTION sha1encoder(lcMessage)

PRIVATE HO, H1, H2, H3, H4
LOCAL lnNumberOfBlocks, lnHigh, lnLow

H0 = 0x67452301
H1 = 0xEFCDAB89
H2 = 0x98BADCFE
H3 = 0x10325476
H4 = 0xC3D2E1F0

* Concatenate to the message a "1" followed by as many zeros as necessary
* to make the length a multiple of 512 with the last 8 bytes storing the length
* of the message.

lnLength = LEN(lcMessage)

* append bits 10000000
lcMessage = lcMessage + CHR(2^7)

* add as many 0 bytes as required to have message bit length a multiple of 512
* with the last 8 bytes being the number of bits in the original message.
lnRemainder = MOD(LEN(lcMessage), 64)
IF lnRemainder > 56
   lcMessage = lcMessage + REPLICATE(CHR(0), (64 - lnRemainder) + 56)
ELSE
   lcMessage = lcMessage + REPLICATE(CHR(0), (56 - lnRemainder))
ENDIF
lnHigh = (lnLength*8) / 2^32
lnLow = MOD(lnLength*8, 2^32)
lcMessage = lcMessage + CHR(BITAND(BITRSHIFT(lnHigh, 24), 0xFF)) ;    && 56
   + CHR(BITAND(BITRSHIFT(lnHigh, 16), 0xFF)) ;    && 57
   + CHR(BITAND(BITRSHIFT(lnHigh, 8), 0xFF))  ;    && 58
   + CHR(BITAND(lnHigh, 0xFF)) ;                   && 59
   + CHR(BITAND(BITRSHIFT(lnLow, 24), 0xFF)) ;     && 60
   + CHR(BITAND(BITRSHIFT(lnLow, 16), 0xFF)) ;     && 61
   + CHR(BITAND(BITRSHIFT(lnLow, 8), 0xFF))  ;     && 62
   + CHR(BITAND(lnLow, 0xFF))                      && 63

lnNumberOfBlocks = LEN(lcMessage) / 64

LOCAL I
FOR I = 1 TO lnNumberOfBlocks
   DO SHA1_ProcessBlock WITH SUBSTR(lcMessage, 1 + 64*(I-1), 64)
ENDFOR

lcDigest = SUBSTR(TRANSFORM(H0,"@0"),3) + ;
   SUBSTR(TRANSFORM(H1,"@0"),3) + ;
   SUBSTR(TRANSFORM(H2,"@0"),3) + ;
   SUBSTR(TRANSFORM(H3,"@0"),3) + ;
   SUBSTR(TRANSFORM(H4,"@0"),3)

* return the 20 character string for the 40 hex digit message digest.

lcReturnValue = ""
FOR i = 1 TO 20
   lnValue = HexCharToDec(lcDigest, i * 2 - 1) * 16 + HexCharToDec(lcDigest, i * 2)
   lcReturnValue = lcReturnValue + CHR(lnValue)
ENDFOR

RETURN lcReturnValue

PROCEDURE SHA1_ProcessBlock

   LPARAMETERS cBlock

   LOCAL I, A, B, C, D, E, nTemp
   LOCAL ARRAY W(80)

   * For each block of 512 bits, divide the block into 16 words of 32 bits and
   * assign them to W1, W2... W16.

   FOR I = 1 TO 16
      W(I) = Word32Bits(BITLSHIFT(ASC(SUBSTR(cBlock, (I - 1) * 4 + 1, 1)), 24) ;
         + BITLSHIFT(ASC(SUBSTR(cBlock, (I - 1) * 4 + 2, 1)), 16) ;
         + BITLSHIFT(ASC(SUBSTR(cBlock, (I - 1) * 4 + 3, 1)), 8) ;
         + ASC(SUBSTR(cBlock, (I - 1) * 4 + 4, 1)))
   ENDFOR

   * For I varying from 17 to 80, one affects the W(I) words in the following way:
   * W(I) = W(I-3) XOR W(I-8) XOR W(I-14) XOR W(I-16)

   FOR I = 17 TO 80
      W(I) = BitLRotate(1, BITXOR(W(I - 3), W(I - 8), W(I - 14), W(I - 16)))
   ENDFOR

   A = H0
   B = H1
   C = H2
   D = H3
   E = H4

   *For I varying from 1 to 80 and with Sn a left circular shift of N bits,
   * one carries out following calculations:

   FOR I = 1 TO 80
      nTemp = BitLRotate(5, A) + E + W(I)
      DO CASE
      CASE I <= 20
         nTemp = nTemp + BITOR(BITAND(B, C), BITAND(BITNOT(B), D)) + 0x5A827999
      CASE BETWEEN(I, 21, 40)
         nTemp = nTemp + BITXOR(B, C, D) + 0x6ED9EBA1
      CASE BETWEEN(I, 41, 60)
         nTemp = nTemp + BITOR(BITAND(B, C), BITAND(B, D), BITAND(C, D)) + 0x8F1BBCDC
      CASE I >= 61
         nTemp = nTemp + BITXOR(B, C, D) + 0xCA62C1D6
      ENDCASE
      nTemp = Word32Bits(nTemp)

      E = D
      D = C
      C = BitLRotate(30, B)
      B = A
      A = nTemp
   ENDFOR

   H0 = Word32Bits(H0 + A)
   H1 = Word32Bits(H1 + B)
   H2 = Word32Bits(H2 + C)
   H3 = Word32Bits(H3 + D)
   H4 = Word32Bits(H4 + E)
RETURN

FUNCTION BitLRotate(nBits, nWord)
   RETURN Word32Bits(BITOR(BITLSHIFT(nWord, nBits), BITRSHIFT(nWord, (32 - nBits))))
ENDFUNC

FUNCTION Word32Bits(lnValue)
   LOCAL ln32Bits
   ln32Bits = BITAND(lnValue, 2^32 - 1)
   DO WHILE ln32Bits < 0
      ln32Bits = ln32Bits + 2^32
   ENDDO
   RETURN ln32Bits
ENDFUNC

FUNCTION HexCharToDec(lcString, lnPosition)
   lcChar = SUBSTR(lcString,lnPosition,1)
   IF BETWEEN(lcChar, '0', '9')
      RETURN VAL(lcChar)
   ELSE && BETWEEN(lcChar, 'A', 'F')
      RETURN ASC(lcChar) - ASC('A') + 10
   ENDIF
ENDFUNC



SECURE HASH STANDARD



SPS library for VFP
Cryptography Code