PureBasic

Forums PureBasic
Nous sommes le Mar 12/Nov/2019 2:46

Heures au format UTC + 1 heure




Poster un nouveau sujet Répondre au sujet  [ 6 messages ] 
Auteur Message
 Sujet du message: Serveur et client securiser
MessagePosté: Jeu 09/Mai/2013 16:40 
Hors ligne
Avatar de l’utilisateur

Inscription: Lun 24/Sep/2012 20:57
Messages: 46
Localisation: Somme
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:
;-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:
;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.


Haut
 Profil  
Répondre en citant le message  
 Sujet du message: Re: Serveur et client securiser
MessagePosté: Ven 17/Mai/2013 20:12 
Hors ligne

Inscription: Mer 21/Jan/2004 17:48
Messages: 5162
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.


Haut
 Profil  
Répondre en citant le message  
 Sujet du message: Re: Serveur et client securiser
MessagePosté: Sam 18/Mai/2013 7:26 
Hors ligne
Avatar de l’utilisateur

Inscription: Sam 23/Sep/2006 18:32
Messages: 6658
Localisation: Isere
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


Haut
 Profil  
Répondre en citant le message  
 Sujet du message: Re: Serveur et client securiser
MessagePosté: Sam 22/Fév/2014 17:17 
Hors ligne
Avatar de l’utilisateur

Inscription: Ven 13/Fév/2004 0:57
Messages: 3702
J'ai une erreur de syntaxe ligne 240


Haut
 Profil  
Répondre en citant le message  
 Sujet du message: Re: Serveur et client securiser
MessagePosté: Sam 22/Fév/2014 17:24 
Hors ligne
Avatar de l’utilisateur

Inscription: Ven 13/Fév/2004 0:57
Messages: 3702
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?


Haut
 Profil  
Répondre en citant le message  
 Sujet du message: Re: Serveur et client securiser
MessagePosté: Dim 23/Fév/2014 16:14 
Hors ligne

Inscription: Dim 01/Jan/2012 23:57
Messages: 1
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.


Haut
 Profil  
Répondre en citant le message  
Afficher les messages postés depuis:  Trier par  
Poster un nouveau sujet Répondre au sujet  [ 6 messages ] 

Heures au format UTC + 1 heure


Qui est en ligne

Utilisateurs parcourant ce forum: Aucun utilisateur enregistré et 0 invités


Vous ne pouvez pas poster de nouveaux sujets
Vous ne pouvez pas répondre aux sujets
Vous ne pouvez pas éditer vos messages
Vous ne pouvez pas supprimer vos messages

Rechercher:
Aller à:  

 


Powered by phpBB © 2008 phpBB Group | Traduction par: phpBB-fr.com
subSilver+ theme by Canver Software, sponsor Sanal Modifiye