Serveur et client securiser

Codes specifiques à Windows
Avatar de l’utilisateur
caussatjerome
Messages : 50
Inscription : lun. 24/sept./2012 20:57
Localisation : Somme

Serveur et client securiser

Message par caussatjerome »

Bonjours à tous !
Voici le code source d'un serveur et d'un client sécuriser avec le chiffrement RSA et RC5, avec authentification HMAC SHA1, multi-threader.
Il s'agit d'un code de base pour que toute personne souhaitant créer une application réseau sécuriser, avec sont propre protocole puisse le faire simplement, le code est commenter.
REMARQUE dans ces codes, l'identifiant est "Jerome", et le Mot de passe est SHA1("Password").

Code source du serveur :

Code : Tout sélectionner

;-Base d'un serveur multi-threader securiser avec openssl:

;Necessaire : OPENSSL installer dans C:\OPENSSL\BIN

;-Fonctionnement du serveur :
;-1 Le client initialise la connection securiser, il ne peut faire rien d'autre sans cela.
;-2 Le serveur confirme la connection securiser
;REMARQUE : La connection sécuriser est initialiser avec du RSA, et ensuite ce poursuit en RC5
;-3 Le client envoi sont identifiant
;-4 Le serveur confirme l'identifiant et envoi un SALT pour l'opération de validation du mot de passe (HMAC SHA1)
;-5 Le client envoi le resultat de l'opération de validation de sont mot de passe avec le salt (HMAC SHA1)
;-6 Le serveur confirme l'authentification
;-7 Le client peut effectuer des action en tant qu'utilisateur authentifier (içi LOGOUT ou QUIT....)
;-8 Le Serveur repond au demande d'action...
;-9 Le client indique la fin de la session.
;-10 Le serveur confirme, et deconnecte, supprimme le THREAD du client.
;REMARQUE : Si le client tarde à envoyer une commande, le serveur coupe la connection et supprime le THREAD du client (au bout d'une minute dans ce code)

;-Protocole :
;Etablisement de la connection securiser :
;C : TUNN CKEY
;S : TOK SKEY | TNO   (TOK = Initialisation de la connection securiser ok, TNO = pas ok et pas implementer..)

;Identification :
;C : USER LOGIN
;S : UOK HMACKEY | UNO   (UOK = Identifiant existant, UNO = Identifiant inéxistant)
;C : PASS HMACRESULT
;S : POK | PNO    (POK = Mot de passe corecte,  PNO = Mot de passe incorecte)
;Deconnection :
;C : LOUT
;S : LOK
;Quitter :
;C : QUIT
;S : QOK

;-Constantes pour RC5
;crypt provider:
#MS_DEF_PROV = "Microsoft Base Cryptographic Provider v1.0"
#MS_ENHANCED_PROV = "Microsoft Enhanced Cryptographic Provider v1.0"
#MS_STRONG_PROV = "Microsoft Strong Cryptographic Provider v1.0"
#MS_AES_PROV ="Microsoft AES Cryptographic Provider v1.0"
#MS_RSA_PROV ="Microsoft RSA Signature Cryptographic Provider v1.0"

;Crypt-Constants
#PROV_RSA_FULL = 1
#ALG_SID_MD5 = 3
#ALG_SID_RC4 = 1
#ALG_SID_RC5 = 13
#ALG_CLASS_DATA_ENCRYPT = 24576 ;$6000
#ALG_CLASS_HASH = 32768 ;$8000
#ALG_TYPE_ANY = 0
#ALG_TYPE_STREAM = 2048
#ALG_TYPE_BLOCK = 1536
#CRYPT_OAEP = $40
#CRYPT_CREATE_SALT = 4
#CRYPT_EXPORTABLE = 1
#CRYPT_NEWKEYSET = 8

; Valid hashing algorithms:
;
#ALG_SID_HMAC = 9
#ALG_SID_MAC = 5
#ALG_SID_MD2 = 1
#ALG_SID_SHA = 4
#ALG_SID_SHA1 = 4
#ALG_SID_SSL3SHAMD5 = 8
#ALG_SID_DES = 1
#ALG_SID_3DES = 3
#ALG_SID_3DES_112 = 9
#CALG_HMAC = #ALG_CLASS_HASH|#ALG_TYPE_ANY|#ALG_SID_HMAC
#CALG_MAC = #ALG_CLASS_HASH|#ALG_TYPE_ANY|#ALG_SID_MAC
#CALG_MD2 = #ALG_CLASS_HASH|#ALG_TYPE_ANY|#ALG_SID_MD2
#CALG_MD5 = #ALG_CLASS_HASH|#ALG_TYPE_ANY|#ALG_SID_MD5
#CALG_SHA = #ALG_CLASS_HASH|#ALG_TYPE_ANY|#ALG_SID_SHA
#CALG_SHA1 = #ALG_CLASS_HASH|#ALG_TYPE_ANY|#ALG_SID_SHA1
#CALG_SSL3_SHAMD5 = #ALG_CLASS_HASH|#ALG_TYPE_ANY|#ALG_SID_SSL3SHAMD5
#CALG_RC4 = #ALG_CLASS_DATA_ENCRYPT|#ALG_TYPE_STREAM|#ALG_SID_RC4
#CALG_RC5 = #ALG_CLASS_DATA_ENCRYPT|#ALG_TYPE_BLOCK|#ALG_SID_RC5
#CALG_DES = #ALG_CLASS_DATA_ENCRYPT|#ALG_TYPE_BLOCK|#ALG_SID_DES
#CALG_3DES = #ALG_CLASS_DATA_ENCRYPT|#ALG_TYPE_BLOCK|#ALG_SID_3DES
#CALG_3DES2 = #ALG_CLASS_DATA_ENCRYPT|#ALG_TYPE_BLOCK|#ALG_SID_3DES_112
;-Fin de Constantes pour RC5

;-debut de variables
Global ClientID.l,SEvent.l, quit.l=0
Global path.s="C:\openssl\bin\"
Global currentdir.s=GetPathPart(ProgramFilename())
;-fin de variables

Procedure.s hextoasc(entrer.s)
For a = 1 To Len(entrer.s) Step 2
sortie.s+Chr(Val("$"+Mid(entrer.s,a,2)))
Next a
ProcedureReturn sortie.s
EndProcedure

Procedure.s hmac_sha1(key.s,msg.s)
If(Len(key.s)>64); Si key est plus grand que 64 octets...
key.s=SHA1Fingerprint(@key.s,Len(key.s))
key.s=hextoasc(key.s)
EndIf
key.s=LSet(key.s,64,Chr(0));Il faut que la clef soit de 64 octets, on ajoute donc autant de fois que necessaire le caractères ASCII 0.
ipad.s=LSet(ipad.s,64,Chr($36));On prépare la variable ipad (64 fois le caractère $36)
opad.s=LSet(opad.s,64,Chr($5c));On prépare la variable opad (64 fois le caractère $5c)
For a=1 To 64
opadt.s+Chr(Asc(Mid(opad,a,1))!Asc(Mid(key,a,1))); on prépare la variable opadt (opad XOR key)
ipadt.s+Chr(Asc(Mid(ipad,a,1))!Asc(Mid(key,a,1))); on prépare la variable ipadt (ipad XOR key)
Next a
ipadt.s+msg.s;on ajoute le message a ipad.
hipad.s=SHA1Fingerprint(@ipadt.s,Len(ipadt.s))
opadt.s+hextoasc(hipad.s)
hopad.s=SHA1Fingerprint(@opadt.s,Len(opadt.s))
ProcedureReturn hopad.s
EndProcedure

Procedure.s rc5encrypt(String$, Key$);-Chiffrement RC5 grce à l'API WINDOWS
Protected *Buffer
Protected DataLength.l
Protected hProv
Protected hHash
Protected result.s
*Buffer = AllocateMemory(Len(String$) * 2 + 64)
DataLength.l = Len(String$)
PokeS(*Buffer, String$)
If CryptAcquireContext_(@hProv, #Null, #MS_ENHANCED_PROV, #PROV_RSA_FULL, 0) = 0
CryptAcquireContext_(@hProv, #Null, #MS_ENHANCED_PROV, #PROV_RSA_FULL, #CRYPT_NEWKEYSET)
EndIf
If hProv
CryptCreateHash_(hProv, #CALG_MD5, 0, 0, @hHash)
If hHash
CryptHashData_(hHash, @Key$, Len(Key$), 0)
CryptDeriveKey_(hProv, #CALG_3DES2, hHash, #CRYPT_EXPORTABLE, @hKey)
If hKey
If CryptEncrypt_(hKey, 0, #True, #Null, *Buffer, @DataLength, Len(String$) * 2 + 64)
EndIf
CryptDestroyKey_(hKey)
EndIf
CryptDestroyHash_(hHash)
EndIf
CryptReleaseContext_(hProv, 0)
EndIf
result.s = Space(DataLength * 3)
Base64Encoder(*Buffer, DataLength, @result, DataLength * 3)
FreeMemory(*Buffer)
ProcedureReturn result
EndProcedure

Procedure.s rc5decrypt(String$, Key$);-DéChiffrement RC5 grce à l'API WINDOWS
Protected *Buffer
Protected DataLength.l
Protected hProv
Protected hHash
Protected result.s
*Buffer = AllocateMemory(Len(String$) * 2 + 64)
DataLength.l = Base64Decoder(@String$, Len(String$), *Buffer, Len(String$) * 2 + 64)
If CryptAcquireContext_(@hProv, #Null, #MS_ENHANCED_PROV, #PROV_RSA_FULL, 0) = 0
CryptAcquireContext_(@hProv, #Null, #MS_ENHANCED_PROV, #PROV_RSA_FULL, #CRYPT_NEWKEYSET)
EndIf
If hProv
CryptCreateHash_(hProv, #CALG_MD5, 0, 0, @hHash)
If hHash
CryptHashData_(hHash, @Key$, Len(Key$), 0)
CryptDeriveKey_(hProv, #CALG_3DES2, hHash, #CRYPT_EXPORTABLE, @hKey)
If hKey
If CryptDecrypt_(hKey, 0, #True, 0, *Buffer, @DataLength)
result.s = PeekS(*Buffer, DataLength)
EndIf
CryptDestroyKey_(hKey)
EndIf
CryptDestroyHash_(hHash)
EndIf
CryptReleaseContext_(hProv, 0)
EndIf
FreeMemory(*Buffer)
ProcedureReturn result
EndProcedure

Procedure.s gen_key(taille);-Générateur de string pseudo-aléatoire (Je n'utilise pas toute la table ASCII, car cela pose des problème avec les caractères spéciaux)
Protected a.l,sortie.s
For a=1 To taille
sortie.s+Chr(CryptRandom(110)+33)
Next a
ProcedureReturn sortie.s
EndProcedure

;-Procedure RSA:
Procedure.s rsa_openssl_gen(taille,dossier.s)
RunProgram(path.s+"openssl.exe","rand -out random.bin "+Str(taille),dossier.s,#PB_Program_Wait| #PB_Program_Hide)
RunProgram(path.s+"openssl.exe","genrsa -rand random.bin -out mykey.pem "+Str(taille),dossier.s,#PB_Program_Wait| #PB_Program_Hide)
RunProgram(path.s+"openssl.exe","rsa -in mykey.pem -out mycert.pem -outform PEM -pubout",dossier.s,#PB_Program_Wait| #PB_Program_Hide)
DeleteFile(dossier.s+"random.bin")
EndProcedure

Procedure.s rsa_openssl_encrypt(entrer.s,dossier.s)
OpenFile(1,dossier.s+"entrer.dat")
WriteData(1,@entrer.s,Len(entrer.s))
CloseFile(1)
RunProgram(path.s+"openssl.exe","rsautl -encrypt -in entrer.dat -inkey mycert.pem -pubin -out coder.dat",dossier.s,#PB_Program_Wait|#PB_Program_Hide)
RunProgram(path.s+"openssl.exe","base64 -in coder.dat -out base64.dat",dossier.s,#PB_Program_Wait|#PB_Program_Hide)
OpenFile(1,dossier.s+"base64.dat")
sortie.s=Space(Lof(1))
ReadData(1,@sortie.s,Lof(1))
CloseFile(1)
DeleteFile(dossier.s+"entrer.dat")
DeleteFile(dossier.s+"coder.dat")
DeleteFile(dossier.s+"base64.dat")
ProcedureReturn sortie.s
EndProcedure

Procedure.s rsa_openssl_decrypt(entrer.s,dossier.s)
OpenFile(1,dossier.s+"entrer.dat")
WriteData(1,@entrer.s,Len(entrer.s))
CloseFile(1)
RunProgram(path.s+"openssl.exe","base64 -d -in entrer.dat -out coder.dat",dossier.s,#PB_Program_Wait|#PB_Program_Hide)
RunProgram(path.s+"openssl.exe","rsautl -decrypt -in coder.dat -inkey mykey.pem -out decoder.dat",dossier.s,#PB_Program_Wait|#PB_Program_Hide)
OpenFile(1,dossier.s+"decoder.dat")
sortie.s=Space(Lof(1))
ReadData(1,@sortie.s,Lof(1))
CloseFile(1)
DeleteFile(dossier.s+"entrer.dat")
DeleteFile(dossier.s+"decoder.dat")
DeleteFile(dossier.s+"coder.dat")
ProcedureReturn sortie.s
EndProcedure
;-Fin de Procedure RSA:

Procedure send(id,entrer.s,key.s);-Procedure d'envoi de reponse chiffrer
SendNetworkString(id,rc5encrypt(entrer.s,key.s))
EndProcedure

Procedure threadclient(id)
Protected *Buffer=AllocateMemory(1024),commande.s,param.s,hkey.s,user.s,status.l=0,calc.s,total.s,taille.l,security.l=0,ckey.s,skey.s=gen_key(32),start.l=ElapsedMilliseconds()
PrintN("Thread commencer pour le client : "+Str(id)+"   "+FormatDate("%hh:%ii:%ss", Date()))
Repeat
If SEvent And ClientID=id;-Test si il y a un evenement reseau, et si cela concerne le client de ce thread...
Select SEvent
Case #PB_NetworkEvent_Data
PrintN("Client : "+Str(id)+" Envoi une commande.   "+FormatDate("%hh:%ii:%ss", Date()))

retourrecu:FillMemory(*Buffer,1024):taille=ReceiveNetworkData(id, *Buffer, 1024);-c'est plus rapide de faire un FILLMEMORY qu'un ALLOCATEMEMORY + FREEMEMORY et on peut pas laisser en memoire les commandes précédantes...
total.s+PeekS(*Buffer,taille)
If taille=1024:Goto retourrecu:EndIf;-Si le packet recu est = a la taille maximum definit par packet, alors on a recu q'une partie du packet complet.... on retourne a retourrecu.

If security.l=0:total.s=rsa_openssl_decrypt(total.s,currentdir.s):ElseIf security.l=1:total.s=rc5decrypt(total.s,skey.s):EndIf;-si la connection securiser à été établie alors on dechiffre avec RC5, sinon on dechiffre avec RSA...

commande.s=Mid(total.s,1,4):param.s=Mid(total.s,6):total.s="";-Les commande dans ce programme sont sur 4 octets, ensuite il y a un caractères espace de separation avec les paramètres (optionnel).
PrintN("Client envoi commande : "+commande.s+"           "+FormatDate("%hh:%ii:%ss", Date()))
PrintN("Client envoi parametres : "+param.s+"           "+FormatDate("%hh:%ii:%ss", Date()))
Select security.l;-Si la connection securiser est établie ou non....
Case 0;-Connection securiser non etablie
Select commande.s
Case "TUNN"
PrintN("Client demande connection securiser.           "+FormatDate("%hh:%ii:%ss", Date()))
ckey.s=param.s
security.l=1
send(id,"TOK "+skey.s,ckey.s)
PrintN("Serveur repond : TOK "+skey.s+"           "+FormatDate("%hh:%ii:%ss", Date()))
Default;Erreur la commande n'est pas reconnue mauvait certificat ? ou erreur de chiffrement/dechiffrement RSA
CloseNetworkConnection(id):quit=id
EndSelect

Case 1;-Connection securiser etablie
Select status.l;-Status d'identification, 0 = non identifier, 1 = identifier
Case 0;-Identification non effectuer
Select commande.s
Case "USER"
PrintN("Client envoi identifiant : "+param.s+"           "+FormatDate("%hh:%ii:%ss", Date()))
If param.s="Jerome"
PrintN("Identifiant valide :          "+FormatDate("%hh:%ii:%ss", Date()))
user.s=param.s
hkey.s=gen_key(32)
PrintN("Serveur genere HMACKEY : "+hkey.s+"         "+FormatDate("%hh:%ii:%ss", Date()))
send(id,"UOK "+hkey.s,ckey.s)
PrintN("Serveur repond UOK "+hkey.s+"         "+FormatDate("%hh:%ii:%ss", Date()))
Else
PrintN("Identifiant incorecte : "+param.s+"           "+FormatDate("%hh:%ii:%ss", Date()))
send(id,"UNO",ckey.s)
EndIf
Case "PASS"
PrintN("Client envoi Resultat HMAC : "+param.s+"           "+FormatDate("%hh:%ii:%ss", Date()))
If user.s="Jerome"
PrintN("Identifiant valide :          "+FormatDate("%hh:%ii:%ss", Date()))
calc.s=hmac_sha1("8be3c943b1609fffbfc51aad666d0a04adf83c9d",hkey.s)
PrintN("Serveur calcul resultat HMAC : "+calc.s+"         "+FormatDate("%hh:%ii:%ss", Date()))
If param=calc.s
PrintN("Client : "+Str(id)+" Authentifier.     "+FormatDate("%hh:%ii:%ss", Date()))
status.l=1
send(id,"POK",ckey.s)
PrintN("Serveur repond : POK         "+FormatDate("%hh:%ii:%ss", Date()))
Else
PrintN("Calcul HMAC ECHEC :          "+FormatDate("%hh:%ii:%ss", Date()))
send(id,"PNO",ckey.s)
PrintN("Serveur repond : PNO         "+FormatDate("%hh:%ii:%ss", Date()))
EndIf
Else
send(id,"PNO",ckey.s)
EndIf

;CASE "COMMANDE" (sur 4 octets dans cet example)
;....


Case "QUIT"
PrintN("Client demande fin de session.         "+FormatDate("%hh:%ii:%ss", Date()))
send(id,"QOK",ckey.s)
PrintN("Serveur repond : QOK         "+FormatDate("%hh:%ii:%ss", Date()))
Delay(1000):CloseNetworkConnection(id):quit=id
PrintN("Serveur Ferme connection du client : "+Str(id)+"         "+FormatDate("%hh:%ii:%ss", Date()))
Default;-Commande non reconnu...
EndSelect

Case 1;-Identification effectuer
Select commande.s
Case "LOUT"
status.l=0
PrintN("Client demande deconnection        "+FormatDate("%hh:%ii:%ss", Date()))
send(id,"LOK",ckey.s)
PrintN("Serveur repond : LOK        "+FormatDate("%hh:%ii:%ss", Date()))

;CASE "COMMANDE" (sur 4 octets dans cet example)
;....


Case "QUIT"
PrintN("Client demande fin de session.         "+FormatDate("%hh:%ii:%ss", Date()))
send(id,"QOK",ckey.s)
PrintN("Serveur repond : QOK         "+FormatDate("%hh:%ii:%ss", Date()))
Delay(100):CloseNetworkConnection(id):quit=id
PrintN("Serveur Ferme connection du client : "+Str(id)+"         "+FormatDate("%hh:%ii:%ss", Date()))
EndSelect
EndSelect
EndSelect
EndSelect
start.l=ElapsedMilliseconds()
Else;-Pas d'evenement reseau
If ElapsedMilliseconds()-start.l=>1000*60;-Time out
CloseNetworkConnection(id):PrintN("Client Time Out, Deconnection..."):quit=id
EndIf
Delay(30);-Aucun evenement reseau, on ajoute un timer de 30 mili-seconde pour pas bouffer des ressources processeur...
EndIf;-Fin test evenement reseau
Until quit=id;-boucle evenement reseau
PrintN("Thread terminer           "+FormatDate("%hh:%ii:%ss", Date())):Shared quit.l:quit.l=0
EndProcedure;-Fin de threadclient

If Not OpenConsole("Serveur de base securiser"):MessageRequester("Serveur de base securiser","Erreur 1 (OpenConsole)"):End 1:EndIf
EnableGraphicalConsole(1)

PrintN("Serveur de base securiser")
PrintN("Console Initialiser.        "+FormatDate("%hh:%ii:%ss", Date()))
If Not OpenCryptRandom():MessageRequester("Serveur de base securiser","Erreur 2 (OpenCryptRandom)"):End 2:EndIf
PrintN("Cryptrandom Initialiser.     "+FormatDate("%hh:%ii:%ss", Date()))
If FileSize("mykey.pem")<0:PrintN("CLEF RSA NON EXISTANTE, CREATION EN COUR..."):rsa_openssl_gen(1024,currentdir.s):Else:PrintN("Clef RSA existante."):EndIf
If Not InitNetwork():MessageRequester("Serveur de base securiser","Erreur 3 (INITNETWORK)"):End 3:EndIf
PrintN("Network Initialiser.     "+FormatDate("%hh:%ii:%ss", Date()))
If Not CreateNetworkServer(0,24,#PB_Network_TCP,"127.0.0.1"):MessageRequester("Serveur de base securiser","Erreur 5 (CreateNetworkServer)"):End 5:EndIf
PrintN("Serveur operationnel.     "+FormatDate("%hh:%ii:%ss", Date()))
start.l=ElapsedMilliseconds()

Repeat;-Boucle principal du programme.
SEvent = NetworkServerEvent();-detecte les evenements reseaux (SEvent est en GLOBAL pour que les thread client puisse le vérifier)
If SEvent;-Si il y a un evenement alors....
ClientID = EventClient();-On récupère le numéro client.
Select SEvent;-Quel type d'evennement...
Case #PB_NetworkEvent_Connect;-Un nouveau client = un nouveau THREAD...
CreateThread(@threadclient(),ClientID)
Case #PB_NetworkEvent_Disconnect;-Un client en moins = un thread en moins....
PrintN("Client : "+Str(ClientID)+" est partie.    "+FormatDate("%hh:%ii:%ss", Date()))
quit.l=ClientID.l
EndSelect
Else;-Pas de nouveau evennement...
Delay(30);-Un petit delay pour pas monopoliser les ressources CPU....
EndIf;-Fin du test evennement.
ForEver;-Fin de Boucle principal du programme.
Code source du client :

Code : Tout sélectionner

;Base d'un client securiser avec openssl:

;Necessaire : OPENSSL installer dans C:\OPENSSL\BIN

;-Fonctionnement du client :
;-1 Le client initialise la connection securiser, il ne peut faire rien d'autre sans cela.
;-2 Le serveur confirme la connection securiser
;(REMARQUE : La connection sécuriser est initialiser avec du RSA, et ensuite ce poursuit en RC5)
;-3 Le client envoi sont identifiant
;-4 Le serveur confirme l'identifiant et envoi un SALT pour l'opération de validation du mot de passe (HMAC SHA1)
;-5 Le client envoi le resultat de l'opération de validation de sont mot de passe avec le salt (HMAC SHA1)
;-6 Le serveur confirme l'authentification
;-7 Le client peut effectuer des action en tant qu'utilisateur authentifier (içi LOGOUT ou QUIT....)
;-8 Le Serveur repond au demande d'action...
;-9 Le client indique la fin de la session.
;-10 Le serveur confirme, et deconnecte, supprimme le THREAD du client.
;REMARQUE : Si le client tarde à envoyer une commande, le serveur coupe la connection et supprime le THREAD du client (au bout d'une minute dans ce code)

;-Protocole :
;Etablisement de la connection securiser :
;C : TUNN CKEY
;S : TOK SKEY | TNO   (TOK = Initialisation de la connection securiser ok, TNO = pas ok et pas implementer..)

;Identification :
;C : USER LOGIN
;S : UOK HMACKEY | UNO   (UOK = Identifiant existant, UNO = Identifiant inéxistant)
;C : PASS HMACRESULT
;S : POK | PNO    (POK = Mot de passe corecte,  PNO = Mot de passe incorecte)
;Deconnection :
;C : LOUT
;S : LOK
;Quitter :
;C : QUIT
;S : QOK

;-Constantes pour RC5:
;crypt provider:
#MS_DEF_PROV = "Microsoft Base Cryptographic Provider v1.0"
#MS_ENHANCED_PROV = "Microsoft Enhanced Cryptographic Provider v1.0"
#MS_STRONG_PROV = "Microsoft Strong Cryptographic Provider v1.0"
#MS_AES_PROV ="Microsoft AES Cryptographic Provider v1.0"
#MS_RSA_PROV ="Microsoft RSA Signature Cryptographic Provider v1.0"

;Crypt-Constants
#PROV_RSA_FULL = 1
#ALG_SID_MD5 = 3
#ALG_SID_RC4 = 1
#ALG_SID_RC5 = 13
#ALG_CLASS_DATA_ENCRYPT = 24576 ;$6000
#ALG_CLASS_HASH = 32768 ;$8000
#ALG_TYPE_ANY = 0
#ALG_TYPE_STREAM = 2048
#ALG_TYPE_BLOCK = 1536
#CRYPT_OAEP = $40
#CRYPT_CREATE_SALT = 4
#CRYPT_EXPORTABLE = 1
#CRYPT_NEWKEYSET = 8

; Valid hashing algorithms:
;
#ALG_SID_HMAC = 9
#ALG_SID_MAC = 5
#ALG_SID_MD2 = 1
#ALG_SID_SHA = 4
#ALG_SID_SHA1 = 4
#ALG_SID_SSL3SHAMD5 = 8
#ALG_SID_DES = 1
#ALG_SID_3DES = 3
#ALG_SID_3DES_112 = 9
#CALG_HMAC = #ALG_CLASS_HASH|#ALG_TYPE_ANY|#ALG_SID_HMAC
#CALG_MAC = #ALG_CLASS_HASH|#ALG_TYPE_ANY|#ALG_SID_MAC
#CALG_MD2 = #ALG_CLASS_HASH|#ALG_TYPE_ANY|#ALG_SID_MD2
#CALG_MD5 = #ALG_CLASS_HASH|#ALG_TYPE_ANY|#ALG_SID_MD5
#CALG_SHA = #ALG_CLASS_HASH|#ALG_TYPE_ANY|#ALG_SID_SHA
#CALG_SHA1 = #ALG_CLASS_HASH|#ALG_TYPE_ANY|#ALG_SID_SHA1
#CALG_SSL3_SHAMD5 = #ALG_CLASS_HASH|#ALG_TYPE_ANY|#ALG_SID_SSL3SHAMD5
#CALG_RC4 = #ALG_CLASS_DATA_ENCRYPT|#ALG_TYPE_STREAM|#ALG_SID_RC4
#CALG_RC5 = #ALG_CLASS_DATA_ENCRYPT|#ALG_TYPE_BLOCK|#ALG_SID_RC5
#CALG_DES = #ALG_CLASS_DATA_ENCRYPT|#ALG_TYPE_BLOCK|#ALG_SID_DES
#CALG_3DES = #ALG_CLASS_DATA_ENCRYPT|#ALG_TYPE_BLOCK|#ALG_SID_3DES
#CALG_3DES2 = #ALG_CLASS_DATA_ENCRYPT|#ALG_TYPE_BLOCK|#ALG_SID_3DES_112
;-Fin de Constantes pour RC5

;-debut de variables
Global ClientID.l,SEvent.l, quit.l=0
Global path.s="C:\openssl\bin\"
Global currentdir.s=GetPathPart(ProgramFilename())
;-fin de variables

Procedure.s hextoasc(entrer.s)
For a = 1 To Len(entrer.s) Step 2
sortie.s+Chr(Val("$"+Mid(entrer.s,a,2)))
Next a
ProcedureReturn sortie.s
EndProcedure

Procedure.s hmac_sha1(key.s,msg.s)
If(Len(key.s)>64); Si key est plus grand que 64 octets...
key.s=SHA1Fingerprint(@key.s,Len(key.s))
key.s=hextoasc(key.s)
EndIf
key.s=LSet(key.s,64,Chr(0));Il faut que la clef soit de 64 octets, on ajoute donc autant de fois que necessaire le caractères ASCII 0.
ipad.s=LSet(ipad.s,64,Chr($36));On prépare la variable ipad (64 fois le caractère $36)
opad.s=LSet(opad.s,64,Chr($5c));On prépare la variable opad (64 fois le caractère $5c)
For a=1 To 64
opadt.s+Chr(Asc(Mid(opad,a,1))!Asc(Mid(key,a,1))); on prépare la variable opadt (opad XOR key)
ipadt.s+Chr(Asc(Mid(ipad,a,1))!Asc(Mid(key,a,1))); on prépare la variable ipadt (ipad XOR key)
Next a
ipadt.s+msg.s;on ajoute le message a ipad.
hipad.s=SHA1Fingerprint(@ipadt.s,Len(ipadt.s))
opadt.s+hextoasc(hipad.s)
hopad.s=SHA1Fingerprint(@opadt.s,Len(opadt.s))
ProcedureReturn hopad.s
EndProcedure

Procedure.s rc5encrypt(String$, Key$);-Chiffrement RC5 grce à l'API WINDOWS
Protected *Buffer
Protected DataLength.l
Protected hProv
Protected hHash
Protected result.s
*Buffer = AllocateMemory(Len(String$) * 2 + 64)
DataLength.l = Len(String$)
PokeS(*Buffer, String$)
If CryptAcquireContext_(@hProv, #Null, #MS_ENHANCED_PROV, #PROV_RSA_FULL, 0) = 0
CryptAcquireContext_(@hProv, #Null, #MS_ENHANCED_PROV, #PROV_RSA_FULL, #CRYPT_NEWKEYSET)
EndIf
If hProv
CryptCreateHash_(hProv, #CALG_MD5, 0, 0, @hHash)
If hHash
CryptHashData_(hHash, @Key$, Len(Key$), 0)
CryptDeriveKey_(hProv, #CALG_3DES2, hHash, #CRYPT_EXPORTABLE, @hKey)
If hKey
If CryptEncrypt_(hKey, 0, #True, #Null, *Buffer, @DataLength, Len(String$) * 2 + 64)
EndIf
CryptDestroyKey_(hKey)
EndIf
CryptDestroyHash_(hHash)
EndIf
CryptReleaseContext_(hProv, 0)
EndIf
result.s = Space(DataLength * 3)
Base64Encoder(*Buffer, DataLength, @result, DataLength * 3)
FreeMemory(*Buffer)
ProcedureReturn result
EndProcedure

Procedure.s rc5decrypt(String$, Key$);-DéChiffrement RC5 grce à l'API WINDOWS
Protected *Buffer
Protected DataLength.l
Protected hProv
Protected hHash
Protected result.s
*Buffer = AllocateMemory(Len(String$) * 2 + 64)
DataLength.l = Base64Decoder(@String$, Len(String$), *Buffer, Len(String$) * 2 + 64)
If CryptAcquireContext_(@hProv, #Null, #MS_ENHANCED_PROV, #PROV_RSA_FULL, 0) = 0
CryptAcquireContext_(@hProv, #Null, #MS_ENHANCED_PROV, #PROV_RSA_FULL, #CRYPT_NEWKEYSET)
EndIf
If hProv
CryptCreateHash_(hProv, #CALG_MD5, 0, 0, @hHash)
If hHash
CryptHashData_(hHash, @Key$, Len(Key$), 0)
CryptDeriveKey_(hProv, #CALG_3DES2, hHash, #CRYPT_EXPORTABLE, @hKey)
If hKey
If CryptDecrypt_(hKey, 0, #True, 0, *Buffer, @DataLength)
result.s = PeekS(*Buffer, DataLength)
EndIf
CryptDestroyKey_(hKey)
EndIf
CryptDestroyHash_(hHash)
EndIf
CryptReleaseContext_(hProv, 0)
EndIf
FreeMemory(*Buffer)
ProcedureReturn result
EndProcedure

Procedure.s gen_key(taille);-Générateur de string pseudo-aléatoire (Je n'utilise pas toute la table ASCII, car cela pose des problème avec les caractères spéciaux)
Protected a.l,sortie.s
For a=1 To taille
sortie.s+Chr(CryptRandom(110)+33)
Next a
ProcedureReturn sortie.s
EndProcedure

;-Procedure RSA:
Procedure.s rsa_openssl_gen(taille,dossier.s)
RunProgram(path.s+"openssl.exe","rand -out random.bin "+Str(taille),dossier.s,#PB_Program_Wait| #PB_Program_Hide)
RunProgram(path.s+"openssl.exe","genrsa -rand random.bin -out mykey.pem "+Str(taille),dossier.s,#PB_Program_Wait| #PB_Program_Hide)
RunProgram(path.s+"openssl.exe","rsa -in mykey.pem -out mycert.pem -outform PEM -pubout",dossier.s,#PB_Program_Wait| #PB_Program_Hide)
DeleteFile(dossier.s+"random.bin")
EndProcedure

Procedure.s rsa_openssl_encrypt(entrer.s,dossier.s)
OpenFile(1,dossier.s+"entrer.dat")
WriteData(1,@entrer.s,Len(entrer.s))
CloseFile(1)
RunProgram(path.s+"openssl.exe","rsautl -encrypt -in entrer.dat -inkey mycert.pem -pubin -out coder.dat",dossier.s,#PB_Program_Wait|#PB_Program_Hide)
RunProgram(path.s+"openssl.exe","base64 -in coder.dat -out base64.dat",dossier.s,#PB_Program_Wait|#PB_Program_Hide)
OpenFile(1,dossier.s+"base64.dat")
sortie.s=Space(Lof(1))
ReadData(1,@sortie.s,Lof(1))
CloseFile(1)
DeleteFile(dossier.s+"entrer.dat")
DeleteFile(dossier.s+"coder.dat")
DeleteFile(dossier.s+"base64.dat")
ProcedureReturn sortie.s
EndProcedure

Procedure.s rsa_openssl_decrypt(entrer.s,dossier.s)
OpenFile(1,dossier.s+"entrer.dat")
WriteData(1,@entrer.s,Len(entrer.s))
CloseFile(1)
RunProgram(path.s+"openssl.exe","base64 -d -in entrer.dat -out coder.dat",dossier.s,#PB_Program_Wait|#PB_Program_Hide)
RunProgram(path.s+"openssl.exe","rsautl -decrypt -in coder.dat -inkey mykey.pem -out decoder.dat",dossier.s,#PB_Program_Wait|#PB_Program_Hide)
OpenFile(1,dossier.s+"decoder.dat")
sortie.s=Space(Lof(1))
ReadData(1,@sortie.s,Lof(1))
CloseFile(1)
DeleteFile(dossier.s+"entrer.dat")
DeleteFile(dossier.s+"decoder.dat")
DeleteFile(dossier.s+"coder.dat")
ProcedureReturn sortie.s
EndProcedure
;-Fin de Procedure RSA:

Procedure send(id,entrer.s,key.s);-Procedure d'envoi de reponse chiffrer
SendNetworkString(id,rc5encrypt(entrer.s,key.s))
EndProcedure

If Not InitNetwork():MessageRequester("Client de base securiser","Erreur 1 (INITNETWORK)"):End 1:EndIf
If Not OpenConsole("Client de base securiser"):MessageRequester("Client de base securiser","Erreur 2 (OpenConsole)"):End 2:EndIf
If Not OpenCryptRandom():MessageRequester("Client de base securiser","Erreur 3 (OpenCryptRandom)"):End 3:EndIf

PrintN("Client de base securiser")
Connection=OpenNetworkConnection("127.0.0.1",24)
If Not Connection:MessageRequester("Client de base securiser","Erreur 4 (OpenNetworkConnection)"):End 4:EndIf
*buffer=AllocateMemory(1024):ckey.s=gen_key(32):Delay(1000)
PrintN("Client envoi : TUNN "+ckey.s)
SendNetworkString(Connection,rsa_openssl_encrypt("TUNN "+ckey.s,currentdir.s))

Repeat
CEvent = NetworkClientEvent(Connection):start.l=ElapsedMilliseconds()
If CEvent;-Evenement reseau
Select CEvent
Case #PB_NetworkEvent_Data
retourrecu:FillMemory(*Buffer,1024):taille=ReceiveNetworkData(Connection, *Buffer, 1024)
total.s+PeekS(*Buffer,taille)
If taille=1024:Goto retourrecu:EndIf
total.s=rc5decrypt(total.s,ckey.s)
PrintN("Client recoit reponse.    "+FormatDate("%hh:%ii:%ss", Date()))
PrintN("Packet recu : ["+total.s+"]")
reponse.s=Mid(total.s,1,3):param.s=Mid(total.s,5):total.s=""
Select reponse.s
Case "TOK"
PrintN("Serveur envoi clef de connection securiser.")
skey.s=param.s:controle=2
Case "UOK"
PrintN("Identifiant valider par le serveur."):controle=3
hkey.s=param.s
Case "UNO"
PrintN("Identifiant non valider par le serveur."):controle=2
Case "POK"
PrintN("Mot de passe Corecte, Acces authoriser"):controle=1
Case "PNO"
PrintN("Mot de passe incorecte"):send(Connection,"USER "+login.s,skey.s):controle=0:Delay(30)
Case "QOK"
PrintN("Fermeture confirmer"):controle=0
Case "LOK"
PrintN("Déconnection effectuer"):controle=2
EndSelect

Case #PB_NetworkEvent_Disconnect
quit=1
EndSelect


Else;-Pas d'evenement reseau

If controle=2
PrintN("Identifiant :")
retourlogin:login.s=Input():If login.s="":Goto retourlogin:EndIf
controle=0:send(Connection,"USER "+login.s,skey.s)
PrintN("Envoi de la commande  : USER "+login.s)
EndIf

If controle=3
PrintN("Mot de passe :")
retourpass:password.s=Input():If password.s="":Goto retourpass:EndIf
password.s=SHA1Fingerprint(@password.s,Len(password.s)):calc.s=hmac_sha1(password.s,hkey.s)
controle=0:send(Connection,"PASS "+calc.s,skey.s)
PrintN("Envoi de la commande  : PASS "+calc.s)
EndIf

If controle=1;-Debut Controle
back:
PrintN("Veuillez entrer la commande :")
PrintN("QUIT | LOGOUT")
commande.s=Input()
Select UCase(commande.s)
Case "LOGOUT"
PrintN("Demande de deconnection...")
send(Connection,"LOUT",skey.s)
PrintN("Envoi de la commande  : LOUT")
Case "QUIT"
send(Connection,"QUIT",skey.s):controle=0
PrintN("Envoi de la commande  : QUIT")
EndSelect
controle=0
EndIf;-Fin de controle

If ElapsedMilliseconds()-start.l=>1000*60
PrintN("Timer ecouler")
start.l=ElapsedMilliseconds()
EndIf
Delay(10)
EndIf;-Fin evenement reseau
Until quit=1
Dites moi ce que vous en pensez, ci cela vous sert.
Cordiallement Caussat Jerome.
comtois
Messages : 5172
Inscription : mer. 21/janv./2004 17:48
Contact :

Re: Serveur et client securiser

Message par comtois »

pas trop le temps de tester et je n'ai pas forcément l'usage pour l'instant. Mais c'est sympa de partager, merci à toi.
http://purebasic.developpez.com/
Je ne réponds à aucune question technique en PV, utilisez le forum, il est fait pour ça, et la réponse peut profiter à tous.
Avatar de l’utilisateur
Kwai chang caine
Messages : 6962
Inscription : sam. 23/sept./2006 18:32
Localisation : Isere

Re: Serveur et client securiser

Message par Kwai chang caine »

Tout à fait d'accord, je t'ai déjà remercié sur l'autre post, mais c'est rien du tout par rapport à la générosité d'un partage surtout à ce niveau.
Et puis ce n'est pas toujours obligé que les besoins des uns correspondent aux offres des autres dans le même instant.
Mais qu'est ce qu'il est bon de faire une simple recherche et tomber sur des petits bijoux tel que tes codes, ou ceux des autres copains que ce soit ici ou chez les "français qui parlent pas français", codés par des gens qui maîtrisent ou ont tout compris, pour des gens comme moi qui ne comprennent jamais quedal, mais n'en ont pas moins les mêmes besoins ou envies :oops:
Je crois même pouvoir dire, sans trop me tromper, car fortement concerné, que moins on est bon, et plus on a des idées et des besoins, :mrgreen:
Alors imagine la frustration quotidienne :D
Alors merci 8)
ImageLe bonheur est une route...
Pas une destination

PureBasic Forum Officiel - Site PureBasic
nico
Messages : 3702
Inscription : ven. 13/févr./2004 0:57

Re: Serveur et client securiser

Message par nico »

J'ai une erreur de syntaxe ligne 240
nico
Messages : 3702
Inscription : ven. 13/févr./2004 0:57

Re: Serveur et client securiser

Message par nico »

On ne peut pas se connecter à partir d'un browser avec ce code, connaissez vous un code qui permet de créer un serveur sécurisé avec lequel on peut se connecter avec un navigateur web?
jejedelajungle
Messages : 1
Inscription : dim. 01/janv./2012 23:57

Re: Serveur et client securiser

Message par jejedelajungle »

Non je ne connais pas de code qui le permets, il faudrait pour cela implémenter le protocole SSL/TLS et coder un serveur http.
Répondre