Plateforme Level Extreme
Abonnement
Profil corporatif
Produits & Services
Support
Légal
English
SHA-1 Hash Encoding
Message
De
13/02/2005 13:52:12
 
 
À
21/01/2005 16:06:35
Information générale
Forum:
Visual FoxPro
Catégorie:
Classes - VCX
Divers
Thread ID:
00979446
Message ID:
00986433
Vues:
44
Andrus, after implementing this and testing, I was not getting matching results with the Java system I was interfacing with. I investigated the Secure Hash Standard at www.itl.nist.gov/fipspubs/fip180-1.htm.

I ran the test examples that were in the document and the algorithm here did not return the expected results. The problem found was that local variables do not respect the 32 bit words used in the SHA-1 algorithm.

Here is the code I am using which does match the examples in the aforementioned document and does get the same results as the Java system I am interfacing to.

Jason
* 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.
>>
>>Thanks
>
>Jason,
>
>there is the code for you
>
>
>*!*    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)))
>
Précédent
Suivant
Répondre
Fil
Voir

Click here to load this message in the networking platform