DelphiFan Magazine

Top Menu

Main Menu

  • DELPHI
  • CODE SAMPLES
  • FIREMONKEY
  • DATABASE
  • RELEASES
  • VIDEOS
  • REVIEW
  • TECH NEWS

logo

DelphiFan Magazine

  • DELPHI
  • CODE SAMPLES
  • FIREMONKEY
  • DATABASE
  • RELEASES
  • VIDEOS
  • REVIEW
  • TECH NEWS
  • How to add a server application written in UNIGUI to startup?

  • UniGUI Expiry Link Anonymizer

  • UniGUI Add CAPTCHA to the WEB project

  • UniGui. Unique hybrid of Delphi and JS

  • How to transform a blob field into string lines (varchar) in SQL Firebird?

CODE SAMPLESDELPHI
Home›CODE SAMPLES›Talk about the application of SSL protocol in Delphi [transfer]

Talk about the application of SSL protocol in Delphi [transfer]

By admin
October 19, 2020
820
0
Share:

Abstract: This article mainly introduces how to use the SSL protocol in Delphi. It is divided into seven parts: (1) What is the SSL protocol? (2) How to use the SSL protocol in Delphi? (3) SSL client programming examples. (4) SSL server programming examples. (5) SSL certificate programming examples. (6) Man-in-the-middle spoofing examples. (7) Others. The author of this article also has a work written in SSL protocol called SSLPROXY.

1.What is the SSL protocol?
SSL is an encrypted transmission protocol. To quote an online passage: SSL is the English abbreviation of Secure socket Layer, and its Chinese means Secure Socket Layer Protocol, which refers to a secure network communication protocol that uses a combination of public and private key technologies. The SSL protocol is a web application-based security protocol launched by Netscape. The SSL protocol specifies a way to provide data security between application protocols (such as Http, Telenet, NMTP and FTP, etc.) and TCP/IP protocols. A layered mechanism, which provides data encryption, server authentication, message integrity, and optional client authentication for TCP/IP connections. It is mainly used to improve the security of data between applications and encrypt and hide transmitted data To ensure that the data is not changed during transmission, that is, to ensure the integrity of the data.

2. How to use SSL protocol in Delphi?
To use the SSL protocol, there are several methods, one is to implement it yourself according to the SSL protocol document, and the other is to call a third-party development library. Now general developers (whether Delphi or VC) use the open source OpenSSL library The introduction in this article is based on OpenSSL.
The Indy component in Delphi itself supports OpenSSL. For example, for IdTCPClient, you only need to drag an IdSSLIOHandlerSocket control to the window, and then point the IOHandler of IdTCPClient to it. However, the statement of IdSSLOpenSSLHeaders.pas is older and is based on OpenSSL 0.9.4 Yes, and 0.9.4 DLL files are now relatively rare. Now OpenSSL 0.9.7i is generally used. (You can open IdSSLOpenSSLHeaders.pas, search for the version, the old version is like this:

OPENSSL_OPENSSL_VERSION_NUMBER = $00904100;
OPENSSL_OPENSSL_VERSION_TEXT = ‘OpenSSL 0.9.4 09 Aug 1999’;  {Do not localize}

The difference between 0.9.4 and 0.9.7i is that some functions of 0.9.4 are located in ssleay32.dll, while 0.9.7i discards this DLL. There are many modified versions of IdSSLOpenSSLHeaders.pas based on 0.9.7i on the Internet. The demo code is mainly based on 0.9.7i.

3. SSL client programming example

Before using OpenSSL, you must first load the SSL library. Call the Load function directly to complete:

if not uIdSSLOpenSSLHeaders.Load then //Load ssl library
begin
Application.MessageBox(‘Failed to load ssl dynamic library!’,’error’, MB_ICONEXCLAMATION + MB_TOPMOST);
Halt;
end;

Then load the wrong character library and encryption algorithm:

IdSslLoadErrorStrings;
IdSslAddSslAlgorithms; //load all SSL algorithms

Then, initialize the protocol version and SSL context used by SSL:

methClient := IdSslMethodClientV23;//There are multiple versions of the SSL protocol, including SSLv2, SSLv23, SSLv3 and TLSv1. We use v23 here.
if methClient = nil then
begin
Application.MessageBox(‘The method used to establish SSL Client failed!’,’Error’, MB_ICONEXCLAMATION + MB_TOPMOST);
Halt;
end;

ctxClient := IdSslCtxNew(methClient); //Initialize the context scenario.
if ctxClient = nil then
begin
Application.MessageBox(‘Failed to create client SSL_CTX!’,’Error’, MB_ICONEXCLAMATION + MB_TOPMOST);
Halt;
end;

After the context scenario is initialized, socket communication can be carried out. First, create a normal socket, connect to the destination address, and then apply for an SSL session environment:

sslClient := IdSslNew(ctxClient);
if sslClient = nil then
begin
closesocket(ClientSocket);
Application.MessageBox(‘Application for SSL session environment failed!’,’error’, MB_ICONEXCLAMATION + MB_TOPMOST);
Halt;
end;

Then bind the socket:

IdSslSetFd(sslClient, ClientSocket);
IdSslConnect(sslClient);

After success, you can call IdSslRead and IdSslWrite to read and write data.
Below we give a complete example for connecting the security focus of the forum homepage. This program uses a Memo control and a button control. Note: This code does not do too much error handling, readers can add it by themselves:

procedure TForm1.Button1Click(Sender: TObject);
const
  //Url: string = ‘https://www.delphifan.online/index.php?lang=en’;
  Host: string = ‘www.delphifan.online’;
  Port: Word = 443;
var
  Wsa: TWSAData;
  ctxClient: PSSL_CTX; //SSL context
  methClient: PSSL_METHOD;
  sRemoteIP: string;

  ClientSocket: TSocket;
  sAddr: TSockAddr;
  sslClient: PSSL;
  pServer_Cert: PX509;
  pStr: Pchar;
  buf: array[0..4095] of Char;
  nRet: integer;
  strSend: string;
begin
  Button1.Enabled := False;

if WSAStartup($101, Wsa) <> 0 then //Initialize Wsock32.dll, MakeWord(2,2),
begin
Application.MessageBox(‘Failed to initialize Winsock dynamic library!’,’error’, MB_ICONEXCLAMATION + MB_TOPMOST);
Halt;
end;

if not uIdSSLOpenSSLHeaders.Load then //Load ssl library
begin
Application.MessageBox(‘Failed to load ssl dynamic library!’,’error’, MB_ICONEXCLAMATION + MB_TOPMOST);
Halt;
end;
IdSslLoadErrorStrings;
IdSslAddSslAlgorithms; //load all SSL algorithms

methClient := IdSslMethodClientV23;
if methClient = nil then
begin
Application.MessageBox(‘The method used to establish SSL Client failed!’,’Error’, MB_ICONEXCLAMATION + MB_TOPMOST);
Halt;
end;

ctxClient := IdSslCtxNew(methClient); //Initialize context
if ctxClient = nil then
begin
Application.MessageBox(‘Failed to create client SSL_CTX!’,’Error’, MB_ICONEXCLAMATION + MB_TOPMOST);
Halt;
end;

sRemoteIP := GetIPAddressByHost(Host);
if sRemoteIP =” then
begin
Application.MessageBox(‘Failed to obtain remote IP address!’,’Error’, MB_ICONEXCLAMATION + MB_TOPMOST);
Halt;
end;

ClientSocket := Socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if ClientSocket = INVALID_SOCKET then
begin
Application.MessageBox(‘Failed to create socket!’,’Error’, MB_ICONEXCLAMATION + MB_TOPMOST);
Halt;
end;

FillChar(sAddr, Sizeof(TSockAddr), #0);
sAddr.sin_family := AF_INET;
sAddr.sin_addr.S_addr := inet_addr(Pchar(sRemoteIP));
sAddr.sin_port := htons(Port);

if connect(ClientSocket, sAddr, sizeof(TSockAddr)) = SOCKET_ERROR then
begin
Application.MessageBox(‘Failed to connect to remote server!’,’Error’, MB_ICONEXCLAMATION + MB_TOPMOST);
Halt;
end;

sslClient := IdSslNew(ctxClient); //The environment for applying for an SSL session, the parameter is the SSL communication method we applied for. Returns a pointer to the current SSL connection environment.
if sslClient = nil then
begin
closesocket(ClientSocket);
Application.MessageBox(‘Application for SSL session environment failed!’,’error’, MB_ICONEXCLAMATION + MB_TOPMOST);
Halt;
end;

IdSslSetFd(sslClient, ClientSocket); //Binding read and write sockets
if IdSslConnect(sslClient) = -1 then
begin
IdSslFree(sslClient);
closesocket(ClientSocket);
Application.MessageBox(‘Failed to bind read and write socket!’,’error’, MB_ICONEXCLAMATION + MB_TOPMOST);
Halt;
end;

Memo1.Lines.Add(Format(‘The algorithm used by the SSL connection is: %s’, [IdSSLCipherGetName(IdSSLGetCurrentCipher(sslClient))]));

pServer_Cert := IdSslGetPeerCertificate(sslClient);
if (pServer_Cert <> nil) then
begin
Memo1.Lines.Add(‘Server certificate:’);
pStr := IdSslX509NameOneline(IdSslX509GetSubjectName(pServer_Cert), nil, 0);
if pStr <> nil then Memo1.Lines.Add(Format(‘Subject: %s’, [pStr]));
pStr := IdSslX509NameOneline(IdSslX509GetIssuerName(pServer_Cert), nil, 0);
if pStr <> nil then Memo1.Lines.Add(Format(‘Issuer: %s’, [pStr]));
end
else
begin
Memo1.Lines.Add(‘The client does not have a certificate.’);
end;
Memo1.Lines.Add(”);

  strSend := ‘GET //index.php?lang=en HTTP/1.1’#$D#$A +
    ‘Accept: */*’#$D#$A +
    ‘Accept-Language: en-en’#$D#$A +
    ‘User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)’#$D#$A +
    ‘Host: ‘ + Host + #$D#$A +
    ‘Connection: Keep-Alive’#$D#$A#$D#$A;

if IdSslWrite(sslClient, @strSend[1], Length(strSend)) <= 0 then
begin
IdSslFree(sslClient);
closesocket(ClientSocket);
Application.MessageBox(‘Send failed!’,’Error’, MB_ICONEXCLAMATION + MB_TOPMOST);
Halt;
end;

  FillChar(buf, sizeof(buf), #0);
  nRet := IdSslRead(sslClient, buf, sizeof(buf));
  while nRet > 0 do
  begin
    Memo1.Lines.Add(StrPas(Buf));
    FillChar(buf, sizeof(buf), #0);
    Application.ProcessMessages;
    nRet := IdSslRead(sslClient, buf, sizeof(buf));
  end;

IdSslFree(sslClient);
closesocket(ClientSocket);
if ctxClient <> nil then IdSslCtxFree(ctxClient);
WSACleanup; //End the call to WSocket32.dll
Button1.Enabled := True;
end;

4.SSL server programming examples

The server side has nothing to talk about. The difference from the client side is that the certificate needs to be loaded during initialization, and then IdSslAccept needs to be associated after Accept. For details on how to generate a certificate file with Delphi, see the next lecture. The code is posted below:

var
Form1: TForm1;
g_Wsa: TWSAData;
g_ServerSocketMain: TSocket = INVALID_SOCKET;
g_ctxServer: PSSL_CTX = nil; //SSL context
g_methServer: PSSL_METHOD = nil;
g_DebugCritSec: TRTLCriticalSection;
g_hAcceptThread: THandle = 0;
g_Start: BOOL = False;

Implementation

{$R *.dfm}

function AcceptThread(lp: Pointer): DWORD; stdcall;
var
  nAddrLen: integer;
  sdClient: TSocket;
  sAddrs: TSockAddr;
  nErrorCode: integer;
  sslServer: PSSL;
  pClient_Cert: PX509;
  pStr: Pchar;
  nRet: integer;
  buf: array[0..4095] of Char;
  strBody, strSend: string;
begin
  Result := 0;

  while g_Start do
  begin

nAddrLen := sizeof(TSockAddr);
sdClient := accept(g_ServerSocketMain, @sAddrs, @nAddrLen);
if (sdClient = INVALID_SOCKET) then
begin
nErrorCode := WSAGetLastError;
EnterCriticalSection(g_DebugCritSec);
if g_Start then Form1.Memo1.Lines.Add(Format(‘An error occurred. Error code: %d’, [nErrorCode]));
LeaveCriticalSection(g_DebugCritSec);
end
else
begin
EnterCriticalSection(g_DebugCritSec);
Form1.Memo1.Lines.Add(Format(‘New connection. Client IP:%s’, [inet_ntoa(sAddrs.sin_addr)]));
LeaveCriticalSection(g_DebugCritSec);


   sslServer := IdSslNew(g_ctxServer); //Apply for the SSL session environment, the parameter is the SSL communication method we applied for earlier, and returns the pointer of the current SSL connection environment.
      if sslServer = nil then
      begin
        closesocket(sdClient);
        Continue;
      end;

     IdSslSetFd(sslServer, sdClient); //Binding read and write sockets

      nRet := IdSslAccept(sslServer);
   &nb”7p0�B  if (nRet = -1) then<br “2=””      =”” begin<br=””>        closesocket(sdClient);
        IdSslShutdown(sslServer);
        IdSslFree(sslServer);
        Continue;
      end;

      EnterCriticalSection(g_DebugCritSec);
      Form1.Memo1.Lines.Add(Format(‘The algorithm used for the SSL connection is: %s’, [IdSSLCipherGetName(IdSSLGetCurrentCipher(sslServer))]));
      LeaveCriticalSection(g_DebugCritSec);

      pClient_Cert := IdSslGetPeerCertificate(sslServer);
      if (pClient_Cert <> nil) then
      begin
        EnterCriticalSection(g_DebugCritSec);
       Form1.Memo1.Lines.Add(‘Client certificate:’);
        LeaveCriticalSection(g_DebugCritSec);
        pStr := IdSslX509NameOneline(IdSslX509GetSubjectName(pClient_Cert), nil, 0);
        if pStr = nil then Exit;
        EnterCriticalSection(g_DebugCritSec);
        Form1.Memo1.Lines.Add(Format(‘Subject: %s’, [pStr]));
        LeaveCriticalSection(g_DebugCritSec);
        IdSslFree(pStr);
        pStr := IdSslX509NameOneline(IdSslX509GetIssuerName(pClient_Cert), nil, 0);
        if pStr = nil then Exit;
        IdSslFree(pStr);
        EnterCriticalSection(g_DebugCritSec);
        Form1.Memo1.Lines.Add(Format(‘Issuer: %s’, [pStr]));
        LeaveCriticalSection(g_DebugCritSec);
        IdSslFree(pStr);
        IdSslFree(pClient_Cert);
      end
      else
      begin
        EnterCriticalSection(g_DebugCritSec);
        Form1.Memo1.Lines.Add(‘The client does not have a certificate.’);
        LeaveCriticalSection(g_DebugCritSec);
      end;


      FillChar(buf, sizeof(buf), #0);
      nRet := IdSslRead(sslServer, buf, sizeof(buf));
      if nRet <= 0 then
      begin
        closesocket(sdClient);
        sdClient := INVALID_SOCKET;
        IdSslShutdown(sslServer);
        IdSslFree(sslServer);
        sslServer := nil;
      end
      else
      begin
        EnterCriticalSection(g_DebugCritSec);
        orm1.Memo1.Lines.Add(‘Client sends request:’#$D#$A + StrPas(buf));
        LeaveCriticalSection(g_DebugCritSec);
      end;

      strBody := ‘Your IP is:’ + inet_ntoa(sAddrs.sin_addr);

      strSend := ‘HTTP/1.1 200 OK’#$D#$A +
        ‘Content-Length: ‘ + IntToStr(Length(strBody)) + #$D#$A +
        ‘Content-Type: text/html’#$D#$A#$D#$A + strBody;

      IdSslWrite(sslServer, @strSend[1], Length(strSend));

      closesocket(sdClient);
      IdSslShutdown(sslServer);
      IdSslFree(sslServer);
    end;
  end;
  g_hAcceptThread := 0;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  sAddr: TSockAddr;
  dwThreadID: DWORD;
begin
  Button1.Enabled := False;

  //Create a socket
  g_ServerSocketMain := Socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  if g_ServerSocketMain = INVALID_SOCKET then
  begin
    MessageBox(0,’Failed to create Socket!’,’Error’, MB_ICONEXCLAMATION + MB_TOPMOST);
    Application.Terminate;
    Exit;
  end;

  //Bind Port
  FillChar(sAddr, Sizeof(TSockAddr), #0);
  sAddr.sin_family := AF_INET;
  sAddr.sin_port := htons(StrToIntDef(Trim(Edit1.Text), 443));
  sAddr.sin_addr.S_addr := INADDR_ANY;

  if Bind(g_ServerSocketMain, sAddr, Sizeof(TSockAddr)) = SOCKET_ERROR then
  begin
    MessageBox(0,’Failed to bind port!’,’Error’, MB_ICONEXCLAMATION + MB_TOPMOST);
    Application.Terminate;
    Exit;
  end;

  //listen
  if listen(g_ServerSocketMain, SOMAXCONN) = SOCKET_ERROR then
  begin
    MessageBox(0,’Listening port failed!’,’Error’, MB_ICONEXCLAMATION + MB_TOPMOST);
    Application.Terminate;
    Exit;
  end;
  g_Start := TRUE;
  g_hAcceptThread := CreateThread(nil, 0, @AcceptThread, nil, 0, dwThreadId);
end;


procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  g_Start := FALSE;
  if g_ServerSocketMain <> INVALID_SOCKET then
  begin
    closesocket(g_ServerSocketMain);
    g_ServerSocketMain := INVALID_SOCKET;
  end;

  if (g_hAcceptThread <> 0) then
  begin
    WaitForSingleObject(g_hAcceptThread, INFINITE);
    CloseHandle(g_hAcceptThread);
    g_hAcceptThread := 0;
  end;
end;

initialization

if WSAStartup($101, g_Wsa) <> 0 then //Initialize Wsock32.dll, version 2.2 can use MakeWord(2,2),
begin
MessageBox(0,’Failed to initialize Winsock dynamic library!’,’Error’, MB_ICONEXCLAMATION + MB_TOPMOST);
Halt;
end;

if not Load then //Failed to load the ssl library
begin
MessageBox(0,’Failed to load the ssl dynamic library!’,’Error’, MB_ICONEXCLAMATION + MB_TOPMOST);
Halt;
end;
IdSslLoadErrorStrings;
IdSslAddSslAlgorithms; //load all SSL algorithms.

//========================= Initialize SSL Server =================== =============
g_methServer := IdSslMethodV23; //The method used to establish SSL.
if g_methServer = nil then
begin
MessageBox(0,’The method used to establish the SSL Server failed!’,’Error’, MB_ICONEXCLAMATION + MB_TOPMOST);
Halt;
end;
g_ctxServer := IdSslCtxNew(g_methServer); //Initialize the context scenario.
if g_ctxServer = nil then //Failed to create SSL_CTX
begin
MessageBox(0,’Failed to create server SSL_CTX!’,’Error’, MB_ICONEXCLAMATION + MB_TOPMOST);
Halt;
end;

 

if IdSslCtxUseCertificateFile(g_ctxServer, Pchar(ExtractFilePath(GetModuleName(HInstance)) +’UserCert.pem’), OPENSSL_SSL_FILETYPE_PEM) <= 0 then //Failed to load the certificate
begin
MessageBox(0,’Failed to load certificate!’,’Error’, MB_ICONEXCLAMATION + MB_TOPMOST);
Halt;
end;
if IdSslCtxUsePrivateKeyFile(g_ctxServer, Pchar(ExtractFilePath(GetModuleName(HInstance)) +’UserKey.pem’), OPENSSL_SSL_FILETYPE_PEM) <= 0 then //Failed to load the private key


 

begin
MessageBox(0,’Failed to load the private key!’,’Error’, MB_ICONEXCLAMATION + MB_TOPMOST);
Halt;
end;
if not IdSslCtxCheckPrivateKeyFile(g_ctxServer) = 0 then //Key certificate does not match
begin
MessageBox(0,’Key and certificate do not match!’,’Error’, MB_ICONEXCLAMATION + MB_TOPMOST);
Halt;
end;
InitializeCriticalSection(g_DebugCritSec);
finalization
if g_ctxServer <> nil then IdSslCtxFree(g_ctxServer);
DeleteCriticalSection(g_DebugCritSec);
WSACleanup; //End the call to WSocket32.dll
end.

Tagsdelphidelphi ssl protocoldelpih sslexamplessslssl protocol
Previous Article

Good code samples for cxGrid

Next Article

Build ssl website with Delphi Unigui

0
Shares
  • 0
  • +
  • 0
  • 0
  • 0
  • 0

admin

Related articles More from author

  • CODE SAMPLESDELPHI

    Customize the height of uniGUI Grid header

    October 1, 2020
    By admin
  • CODE SAMPLESDELPHI

    How to automatically adjust the size of DBGrid columns?

    January 4, 2021
    By admin
  • CODE SAMPLESDELPHI

    Connect And Manage A SQLite Database For Delphi

    October 8, 2020
    By admin
  • CODE SAMPLESDELPHI

    Build ssl website with Delphi Unigui

    October 23, 2020
    By admin
  • CODE SAMPLESDELPHIFIREMONKEY

    Delphi changes Android brightness

    December 10, 2020
    By admin
  • DELPHIRELEASES

    Bold for Delphi is Open Source

    September 21, 2020
    By admin

Leave a reply Cancel reply

You may interested

  • CODE SAMPLESDELPHI

    How to Remove Blank Lines from Memo?

  • CODE SAMPLESDELPHI

    Build ssl website with Delphi Unigui

  • CODE SAMPLESDELPHI

    How to select multiple files with OpenDialog?

  • LATEST REVIEWS

  • TOP REVIEWS

Timeline

  • January 27, 2021

    How to add a server application written in UNIGUI to startup?

  • January 27, 2021

    UniGUI Expiry Link Anonymizer

  • January 26, 2021

    UniGUI Add CAPTCHA to the WEB project

  • January 26, 2021

    UniGui. Unique hybrid of Delphi and JS

  • January 13, 2021

    How to transform a blob field into string lines (varchar) in SQL Firebird?

Latest Comments

Find us on Facebook

Follow Us on Instagram

logo

Our website, law, laws, copyright and aims to be respectful of individual rights. Our site, as defined in the law of 5651 serves as a provider of space. According to the law, contrary to the law of site management has no obligation to monitor content. Therefore, our site has adopted the principle of fit and remove. Works are subject to copyright laws and is shared in a manner that violated their legal rights, or professional associations, rights holders who, adsdelphi@gmail.com I can reach us at e-mail address. Complaints considered to be infringing on the examination of the content will be removed from our site.

About us

  • 660 Pennsylvania Avenue Southeast #100 Washington, DC 20003
  • 0123456789
  • adsdelphi@gmail.com
  • Recent

  • Popular

  • Comments

  • How to add a server application written in UNIGUI to startup?

    By admin
    January 27, 2021
  • UniGUI Expiry Link Anonymizer

    By admin
    January 27, 2021
  • UniGUI Add CAPTCHA to the WEB project

    By admin
    January 26, 2021
  • UniGui. Unique hybrid of Delphi and JS

    By admin
    January 26, 2021
  • How to add a server application written in UNIGUI to startup?

    By admin
    January 27, 2021
  • Amazing Cross Platform Email App Sample In Delphi 10.4.1 FireMonkey For Android And IOS

    By admin
    August 13, 2020
  • Critical Update Available For Delphi FireMonkey 10.4.1 On Android, IOS, OSX, Windows, And Linux

    By admin
    September 4, 2020
  • Setting up the IDE for your first Android Application in Delphi

    By admin
    September 7, 2020

Follow us

Find us on Facebook

© Copyright Delphifan Forum. All rights reserved.