*!* Objet : Implémention en VisualFoxPro de l'algorithme de hachage SHA1
*!* Auteur : C.Chenavier
*!* Version : 1.00 - 15/11/2004
*!* modifiée le : 22/12/2006
*!* Les tests ont été réalisés avec le programme HashCalc : http://www.slavasoft.com
*!* SHA signifie Secure Hash Algorithme et on utilise souvent le terme SHA-1,
*!* pour noter la version.
*!* SHA est une fonction de hachage qui produit des empreintes de 160 bits,
*!* contrairement à MD5 qui produit des empreintes de 128 bits.
*!* Cette fonction de hachage a été développée conjointement par la NSA et le NIST
*!* pour être le standard des fonctions de hachage (FIPS PUB 180-1).
*!* SHA est basé sur MD4 et est réputé plus sûr que MD5.
*!* SHA fonctionne sur des messages dont la taille est inférieure à 2^64 bits
*!* et travaille sur des blocs de 512 bits.
*!* ---------- SHA-1 TEST SUITE ----------
*!* SHA-1("") = da39a3ee5e6b4b0d3255bfef95601890afd80709, ok
*!* SHA-1("a") = 86f7e437faa5a7fce15d1ddcb9eaeaea377667b8, ok
*!* SHA-1("abc") = a9993e364706816aba3e25717850c26c9cd0d89d, ok
*!* SHA-1("message digest") = c12252ceda8be8994d5fa0290a47231c1d16aae3, ok
*!* SHA-1(a..z) = 32d10c7b8cf96570ca04ce37f2a19d84240d3a89, ok
*!* SHA-1(A..Za..z0..9) = 761c457bf73b14d27e9e9265c46f4b4dda11f940, ok
*!* SHA-1(8 times "1234567890") = 50abf5706a150990a08b2c5ea40fa0e585554732, ok
*!* Exemples de test :
*!* MessageBox(SHA1("")="da39a3ee5e6b4b0d3255bfef95601890afd80709")
*!* MessageBox(SHA1("a")="86f7e437faa5a7fce15d1ddcb9eaeaea377667b8")
*!* MessageBox(SHA1("abc")="a9993e364706816aba3e25717850c26c9cd0d89d")
*!* MessageBox(SHA1("message digest")="c12252ceda8be8994d5fa0290a47231c1d16aae3")
*!* MessageBox(SHA1("abcdefghijklmnopqrstuvwxyz")="32d10c7b8cf96570ca04ce37f2a19d84240d3a89")
*!* MessageBox(SHA1("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")="761c457bf73b14d27e9e9265c46f4b4dda11f940")
*!* MessageBox(SHA1(REPLICATE("1234567890",8))="50abf5706a150990a08b2c5ea40fa0e585554732")
*!* MessageBox(SHA1("ceci est un test")="71438dc237b45f04759c41e1b2d34f42a46318f3")
FUNCTION SHA1
LPARAMETERS 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 + 1
** 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 > 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 + BINTOC(M.nHigh, 'S') + BINTOC(M.nLow, 'S')
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
LPARAMETERS nBits, nWord
RETURN BITLSHIFT(M.nWord, M.nBits) + BITRSHIFT(M.nWord, (32-(M.nBits)))
|
C'est beau, on dirait du Chopin...