* 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>>Can anyone point me to a routeine for doing an SHA-1 has encoding. I need one to send a username and password for authentication of a user to a seperate system. Can anyone recommend a free utility for this.
>*!* Objet : Implémention en VisualFoxPro de l'algorithme de hachage 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 > >** Si au départ, la taille du message n'est pas un multiple de 512, >** alors l'algorithme complète le message en ajoutant un 1 et >** autant de 0 que nécessaires et les 8 derniers octets servent >** à stocker la longueur du message. > >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 > >* NB! lisasin local i > >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) > > >** Pour chaque bloc de 512 bits, on divise le bloc en 16 mots de 32 bits >** et on les affecte respectivement à W1, W2...W16. > >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 > >** Pour I variant de 17 à 80, on affecte les mots Wi de la manière suivante : >** Wi = Wi-3 XOR Wi-8 XOR Wi-14 XOR Wi-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 > >** Pour I variant de 1 à 80 et avec Sn un décalage circulaire gauche de n bits, >** on effectue les calculs suivants : > >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))) >