Protegendo seu sistema utilizando Criptgrafia no arquivo de Configuração

Nesse artigo mostraremos como proteger nossos arquivos com criptografia.

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.

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.

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.

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.

Artigos relacionados