Quando desenvolvemos sistemas hoje, não importa a linguagem de programação utilizada, devemos nos preocupar com os dados da empresa, principalmente com a segurança do banco de dados. Muitos ainda utilizam arquivos .ini como string de conexão com o banco de dados, então nesse artigo abordaremos um assunto simples, porém de muita eficácia.

Não abordaremos princípios sobre a conexão a banco de dados por arquivos, pois já existe um artigo sobre isso.

Existem muitas outras forma de criptografia no mercado com chaves de 128 bits, e soluções muito mais eficientes para banco de dados. Porém a função aqui é mostrar uma solução simples apenas para esclarecimento e conhecimento dos iniciantes

A primeira coisa é iniciar uma nova aplicação no Delphi usando o banco de dados Firebird porém, o método pode ser aplicado a qualquer banco. Para isso use os seguintes dados: usuário SYSDBA e senha masterkey.

Em seguida crie um DataModule da aplicação chamado DM, conforme mostra a Figura 1.

Configuração do DataModule
Figura 1. Configuração do DataModule

Em seguida implemente o Código 1.


  unit Udm;
interface
uses
  SysUtils, Classes, DBXpress, DB, SqlExpr,
IniFiles; //Classe que trabalha com arquivos .INI
type
  TDm = class(TDataModule)
    Conexao: TSQLConnection;
    procedure ConexaoBeforeConnect(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    UserBD,             { Usuário do Banco de Dados }
    PassDB,             { Senha do Banco de Dados }
    PathBD,             { Path do Banco de Dados }
    Fundo2,             {Imagem do Fundo}
    Path,                {Path do Banco de Dados}
    PathImage,        {Path das Imagens}
    PathSkin,           {Path dos Skins}
    Usuario: String;  {Armazena o Usuario}
 
   { Funções de Encriptação e Decriptação de Dados esta na sessão Public pois se trata de procedimento publico} 
    function Encrypt(const S: String; Key: Word): String;
    function Decrypt(const S: ShortString; Key: Word): String;
  end;
var
  Dm: TDm;
implementation
{$R *.dfm}
const
 
 { Constantes que irão ser utilizadas nos cálculos das rotinas de criptografia e podendo ser alteradas conforme o gosto do leitor.} 
 
  C1 = 52845;
  C2 = 22719;
 

 {Procedimento do Evento BeforeConnect do Objeto sqlConnection onde irá ler todas as informações do arquivo .ini criptografado} 
 
procedure TDm.ConexaoBeforeConnect(Sender: TObject);
var
ConfigIni : TIniFile;
Path : String;
begin
//Seta as propriedades da conexão em tempo de execução pegando os dados do arquivo config.ini
 ConfigIni := TIniFile.Create(ExtractFilePath(ParamStr(0)) + 'Config.ini');
 Conexao.Params.Values['Database']:= ConfigIni.ReadString('CONFIG', 'DATABASE', '');
 ConfigIni.Free;
end;
 
 {Função declarada acima encarregada de encriptar os dados, como podemos ver as constantes C1 e C2
estão sendo utilizadas para a execução desse bloco de comando}
function TDm.Encrypt(const S: String; Key: Word): String;
var
  I: byte;
begin
  Result := '';
  for I := 1 to Length(S) do
  begin
    Result := Result + IntToHex(byte(char(byte(S[I]) xor (Key shr 8))), 2);
    Key := (byte(char(byte(S[I]) xor (Key shr 8))) + Key) * C1 + C2;
  end;
end;
 
 {Função declarada acima encarregada de descriptar os dados}
 
function TDm.Decrypt(const S: ShortString; Key: Word): String;
var
  I: byte;
  x: char;
begin
  result := '';
  i := 1;
  while (i < Length(S)) do
  begin
    x := char(strToInt('$' + Copy(s, i, 2)));
    Result := result + char(byte(x) xor (Key shr 8));
    Key := (byte(x) + Key) * C1 + C2;
    Inc(i, 2);
  end;
end;
end.
Código 1. Código completo

O próximo passo é implementar isso nos Forms. Assim, criaremos outro Form com o nome de Principal, como mostra a Figura 2.

Implementação do form principal
Figura 2. Implementação do form principal

Em seguida implemente o Código 2 que apenas lê os diretórios do arquivo .ini e os coloca em memória nas variáveis do DataModule.


procedure TFrmLogin.FormCreate(Sender: TObject);
var
  Arq: TIniFile;
begin
  DecimalSeparator := ',';    
  ThousandSeparator := '.'; 
  ShortDateFormat := 'dd/mm/yyyy';
 
  Arq := TIniFile.Create(ExtractFilePath(Application.ExeName) + 'Config.ini');
  with DM do
  begin
     Path   := Arq.ReadString('CONFIG', 'DATABASE', ExtractFilePath(Application.ExeName) + 'CONFIG');
  PathImage := Arq.ReadString('IMAGEM_FUNDO','IMAGEN',PathImage);
   PathSkin := Arq.ReadString('SKIN','SKIN',PathSkin);
     UserBD := Decrypt(Arq.ReadString('DATABASE', 'Username', Encrypt('SYSDBA', 7834)), 7834);
     PassDB := Decrypt(Arq.ReadString('DATABASE', 'Password', Encrypt('masterkey', 7834)), 7834);
    
end;
end;
Código 2. Implementação do form principal

Com o Código 3 chamaremos o próximo form.


Application.CreateForm(TFrmConfig,FrmConfig);
    FrmConfig.ShowModal;
    FrmConfig.Free;
Código 3. Chamando o form

Esse form que chamaremos é o das configurações, chamado de FrmConfig, como mostra a Figura 3.

Form de configurações
Figura 3. Form de configurações

Com o Código 4 implementamos o procedimento de leitura.


{ Abertura de Diretórios }
procedure TFrmConfig.BitBtn3Click(Sender: TObject);
begin
 If OpenDialog1.Execute Then
   edtPatch.Text:= OpenDialog1.FileName;
end;
procedure TFrmConfig.BitBtn2Click(Sender: TObject);
begin
  If OpenDialog1.Execute Then
    EdtImagen.Text:= OpenDialog1.FileName;
end;
procedure TFrmConfig.BitBtn4Click(Sender: TObject);
begin
 If OpenDialog1.Execute Then
    EdtSkin.Text:= OpenDialog1.FileName;
end;
 
 { Aqui vem os comandos de Gravação e Leitura através dos procedimentos e das variáveis declaradas no DataModule anteriormente}
procedure TFrmConfig.btOkClick(Sender: TObject);
 Var
  Cfg,Arq: TIniFile;
 begin
 With DM do
  begin
  
 {Observe que aquelas variáveis no DataModule declaradas são recuperadas com Dados em Memória a partir da inicialização do Form}  

   PathBD := EdtPatch.Text;      { Path do Banco de Dados }
   UserBD := edtUserDB.Text;     { Usuario do Banco de Dados }
   PassDB := edtPassDB.Text;    { Senha do Banco de Dados }
   Path:=EdtPatch.Text;           {a variável recebe o conteúdo puxado pelo edit ao solicitar o acesso a outro banco e dados}
   PathImage:=EdtImagen.Text;  { Path das imagens }
   PathSkin:=EdtSkin.Text;        { Path das Skins }
 
  {Se a conexao for Local}
   if (RadioLocal.Checked = True ) Then
            PathBD := EdtPatch.Text    { Path do Banco de Dados }
    {Senão a conexão Vai receber o IP do Servidor, a porta de Comunicação e o Patch do banco}
    else
     PathBD := EdtIp.Text+':'+ EdtPorta.Text+':'+EdtPatch.Text  ;
                  {Ip, Porta e Path do Banco de Dados }
 
   Arq:= TIniFile.Create(ExtractFilePath(Application.ExeName) + 'Config.ini');
   Arq.WriteString('CONFIG','DATABASE',Path);          //Grava o conteúdo escrito no Edit no arquivo .ini
   Arq.WriteString('IMAGEM_FUNDO','IMAGEN',PathImage);
   Arq.WriteString('SKIN','SKIN',PathSkin);
   Arq.WriteString('DATABASE', 'Username', Encrypt(UserBD, 7834));
   Arq.WriteString('DATABASE', 'Password', Encrypt(PassDB, 7834));
   Arq.Free;
    end;
    Close;
end;
end.
Código 4. Procedimento de leitura

Observe que quando as configurações são alteradas novamente no arquivo Config.ini essas já estão criptografadas.

Isso pode ser implementado de várias maneiras a depender de cada desenvolvedor. No nosso caso criptografamos apenas o usuário e a senha, porém os demais diretórios e arquivos também podem ser criptografados e lidos na inicialização do sistema.