Ir para o conteúdo
nunopicado

Encriptar ou Desencriptar... Eis a questão!

Mensagens Recomendadas

nunopicado

Cá fica mais uma pequena unit para ser usada por quem dela precise.

Está preparada para usar em delphi, mas facilmente poderá ser adaptada para usar em FreePascal

unit Cryptic;

// UNIT Cryptic
// - Permite Encriptar e Desencriptar um texto
// - Permite o uso de uma chave fixa ou aleatória (chave Integer)
// - A chave é passada junto com o código (e também ela codificada) para
//   posterior desencriptação
// - Pode ser usada de forma encadeada para maior segurança
// - O número de encadeamentos não é passado junto com a chave, pelo que, quando
//   se usa codificação encadeada, é necessário saber o número de encadeamentos
//   para se proceder à desencriptação
// - Permite definir os limites inferior e superior da chave aleatória (por
//   defeito a chave é escolhida aleatoriamente entre 1 e 255)
//   Para isso, basta definir o valor das variável LowLimit e HighLimit(1-65535)
//
// Encriptação (uso):
//   Encrypt (Texto:String);  - Encripta o texto com chave variável
//   Encrypt (Texto:String; Chave:Integer);  - Encripta o texto com a chave
//                                             inserida
//
// Desencriptação (uso):
//   Decrypt (Texto:String);  - Desencripta o texto
//   Decrypt (Texto:String; var Chave:Integer);  - Desencripta o texto e guarda
//                                             na segunda variável a chave usada
//                                             para encriptar
//
// por:  Nuno Picado (Portugal@Programar)


interface

uses
    Classes,SysUtils;

const
     DefaultLowLimit  =   1;
     DefaultHighLimit = 255;

var
   LowLimit  : Word = DefaultLowLimit;
   HighLimit : Word = DefaultHighLimit;

Function Encrypt(Text:String;Key:Integer):String;Overload;
Function Encrypt(Text:String):String;Overload;
Function Decrypt(Text:String;var Key:Integer):String;Overload;
Function Decrypt(Text:String):String;Overload;

implementation

Function Encrypt(Text:String;Key:integer):String;Overload;
var
   i:integer;
   Cript:String;
   lst:TStringList;
begin
     // Termina se o Texto a encriptar for nulo
     if Text='' then exit;

     // Prepara uma lista de apoio aos cálculos
     lst:=TStringList.Create;
     try
        lst.Clear;

        // Converte os caracteres em códigos ASCII e aplica-lhes a chave
        for i:=1 to length(Text) do
            lst.Add(IntToStr(Ord(Text[i])+Key));

        // Codifica a chave usando os códigos do primeiro e último caracter do texto, e insere o caracter resultante na segunda posição da lista
        Key:=StrToInt(lst[0])+StrToInt(lst[lst.Count-1])-Key;
        lst.Insert(1,IntToStr(Key));

        // Converte os códigos ASCII com a chave aplicada numa string codificada
        Result:='';
        for i:=0 to lst.count-1 do
            Result:=Result+Chr(StrToInt(lst[i]));
     finally
        lst.Free;  // Elimina a lista temporaria
     end;
end;

Function Encrypt(Text:String):String;Overload;
var
   Tmp:integer;
begin
     // Termina se o Texto a encriptar for nulo
     if Text='' then exit;

     // Valida os valores limite da chave, e ajusta-os se necessário
     if LowLimit<DefaultLowLimit
        then LowLimit:=DefaultLowLimit;
     if LowLimit=HighLimit
        then if LowLimit>1
                then LowLimit:=DefaultLowLimit
                else HighLimit:=DefaultHighLimit;
     if LowLimit>HighLimit
        then begin
                  Tmp:=LowLimit;
                  LowLimit:=HighLimit;
                  HighLimit:=Tmp;
             end;

     // Chama a função de encriptação com uma chave aleatória
     Randomize;
     Result:=Encrypt(Text,Random(HighLimit+LowLimit)+LowLimit);
end;

Function Decrypt(Text:String;var Key:Integer):String;
var
   lst:TStringList;
   i:integer;
begin
     // Termina se o Texto a encriptar for nulo
     if Text='' then exit;

     // Prepara uma lista de apoio aos cálculos
     lst:=TStringList.Create;
     try
        lst.Clear;

        // Adiciona à lista os códigos ASCII dos caracteres codificados
        for i:=1 to length(Text) do
            lst.Add(IntToStr(Ord(Text[i])));

        // Extrai a chave codificada da segunda posição da lista.
        Key:=StrToInt(lst[1]);
        // Descodifica a chave usando os códigos da primeira e ultimas posições
        Key:=StrToInt(lst[0])+StrToInt(lst[lst.Count-1])-Key;
        // Elimina a chave da lista
        lst.Delete(1);

        // Remove a chave de cada código, e converte o resultado em caracter, armazenando cada um no resultado
        Result:='';
        for i:=0 to lst.Count-1 do
            Result:=Result+Chr(StrToInt(lst[i])-Key);
     finally
        lst.Free;  // Elimina a lista temporaria
     end;
end;

Function Decrypt(Text:String):String;Overload;
var
   Key:integer;
begin
     // Termina se o Texto a encriptar for nulo
     if Text='' then exit;

     // Chama a função de desencriptação com uma variável para receber a chave usada que será ignorada
     Result:=Decrypt(Text,Key);
end;

end.

A explicação de funcionamento está nos comments iniciais da unit, mas alguma dúvida, é só dizer...

;)


"A humanidade está a perder os seus génios... Aristóteles morreu, Newton já lá está, Einstein finou-se, e eu hoje não me estou a sentir bem!"

> Não esclareço dúvidas por PM: Indica a tua dúvida no quadro correcto do forum.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
nunopicado

Só é pena é que tenhas acabado de fazer o trabalho do outro agora mesmo com isto... :hmm:

Pensei nisso, mas lembrei-me de duas coisas:

1. Não me pareceu que aquilo fosse trabalho escolar. E assim sendo, é uma questão de força de vontade de ele fazer antes de tentar copiar

2. Está noutro quadro... :) Pode ser que não veja!

3. Precisava de mudar um pouco a cabeça do que estava a fazer, senão dava tilt!  :smoke: ;)

Aqui fica um mini programa para testar a unit:

program Project1;

{$APPTYPE CONSOLE}

uses
  SysUtils, Cryptic;

var
   Texto,
   TextoEncriptado:String;
   Chave:Integer;

begin
  try
    // Encriptar com chave Aleatória
    Write('Texto a encriptar com chave aleatoria: ');
    Readln(Texto);
    TextoEncriptado:=Encrypt(Texto);
    Writeln(#13,'Texto encriptado:');
    Writeln(TextoEncriptado,#13#10);

    // Desencriptar (e verificando a chave)
    Writeln('Texto desencriptado:');
    Writeln(Decrypt(TextoEncriptado,Chave));
    Writeln('Chave aleatória gerada: ',Chave);

    // Encriptar com chave fixa
    Write('Texto a encriptar com chave fixa: ');
    Readln(Texto);
    Write('Chave fixa a usar: ');
    Readln(Chave);
    TextoEncriptado:=Encrypt(Texto,Chave);
    Writeln(#13,'Texto encriptado:');
    Writeln(TextoEncriptado,#13#10);

    // Desencriptar (sem verificar a chave)
    Writeln('Texto desencriptado:');
    Writeln(Decrypt(TextoEncriptado));
    Writeln('Chave aleatória gerada: ',Chave);

    // Mudar os valores de limite baixo e alto
    Write('Insira um novo limite baixo para a chave (1 a 65534): ');
    Readln(LowLimit);
    Write('Insira um novo limite alto para a chave (',LowLimit,' a 65535): ');
    Readln(HighLimit);

    // Encriptar com chave Aleatória
    Write('Texto a encriptar com chave aleatoria: ');
    Readln(Texto);
    TextoEncriptado:=Encrypt(Texto);
    Writeln(#13,'Texto encriptado:');
    Writeln(TextoEncriptado,#13#10);

    // Desencriptar (e verificando a chave)
    Writeln('Texto desencriptado:');
    Writeln(Decrypt(TextoEncriptado,Chave));
    Writeln('Chave aleatória gerada: ',Chave);


    Writeln(#13#13#13#10,'Enter para terminar. . .');
    Readln;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.


"A humanidade está a perder os seus génios... Aristóteles morreu, Newton já lá está, Einstein finou-se, e eu hoje não me estou a sentir bem!"

> Não esclareço dúvidas por PM: Indica a tua dúvida no quadro correcto do forum.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
nunopicado

Adicionada Implementação na Wiki. :)

Ah! E título corrigido no que toca ao Português... É "eis" e não "héis" ;)

Opps, tens razão!  :-[ :P


"A humanidade está a perder os seus génios... Aristóteles morreu, Newton já lá está, Einstein finou-se, e eu hoje não me estou a sentir bem!"

> Não esclareço dúvidas por PM: Indica a tua dúvida no quadro correcto do forum.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
Rui Carlos

Seria útil indicar o algoritmo usado (parece a Cifra de César com ligeiras adaptações).

Alguns comentários:

- Qual a razão para colocar a chave no resultado? Significa que qualquer pessoa passa a poder decifrar a mensagem original. (A cifra de César já é muito insegura, mas com a chave lá, a coisa ainda fica pior...)

- "Pode ser usada de forma encadeada para maior segurança".

Parece-me que isto adiciona pouca ou nenhuma segurança, na medida é que o resultado final deverá ser semelhante ao de somar as chaves (pelo menos pelo que percebi do código). Encadear "transformações" só tem interesse se elas não poderem ser facilmente compostas.

(Não percebi muito bem se isto era um exemplo didáctico, ou se é para ser usado.)

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
nunopicado

Seria útil indicar o algoritmo usado (parece a Cifra de César com ligeiras adaptações).

Err... bem, não faço ideia! B)

Um membro noutro tópico perguntou por uma maneira de se codificar um determinado texto, e esta foi uma maneira de que me lembrei de o fazer, de forma simples, mas não excepcionalmente segura (como já pudeste reparar :))

- Qual a razão para colocar a chave no resultado? Significa que qualquer pessoa passa a poder decifrar a mensagem original. (A cifra de César já é muito insegura, mas com a chave lá, a coisa ainda fica pior...)

A ideia da chave ir incorporada é por causa do uso de uma chave aleatória, e porque com isto não é necessário saber a chave para poder descodificar, logo que se tenha a unit (e se saiba é claro que foi com esta unit que foi codificado).

É completamente opcional (eu podia era ter posto uma flag a activar ou não o envio), mas falando exclusivamente da óptica do utilizador comum, ao ver um código gerado assim, não tem como saber nem que a chave lá está, nem onde, e nem quais as posições do código que lhe dão origem. De qualquer maneira, nada que alguém mais entendido não pudesse lá chegar! :)

- "Pode ser usada de forma encadeada para maior segurança".

Parece-me que isto adiciona pouca ou nenhuma segurança, na medida é que o resultado final deverá ser semelhante ao de somar as chaves (pelo menos pelo que percebi do código). Encadear "transformações" só tem interesse se elas não poderem ser facilmente compostas.

O encadeado aqui é nada mais do que codificar o proprio resultado do código, quantas vezes for desejado. Aumenta a segurança no sentido em que quando alguém tenta crackar o código, ao terminar fica outra vez com caracteres inintelegíveis. Pode ser que desista e não tente outra vez :D.

A sério, assim como está só aumenta o trabalho, até porque com o uso da chave aleatória, de cada vez que concluir tem de voltar a encontrar a chave, visto que é sempre diferente, mas é um principio, caso a unit seja expandida por exemplo para mudar os caracteres de posição, mantendo é claro uma forma de os reordenar ao descodificar, ou mudar a forma como a chave é guardada.

(Não percebi muito bem se isto era um exemplo didáctico, ou se é para ser usado.)

Esta é facil... ;) É meramente didáctico, apenas para mostrar uma maneira (provavelmente a mais básica) de codificar um texto.

Ainda admito o uso "as is" em coisas básicas, mas nem de perto nem de longe recomendo o seu uso a nivel "profissional".

Basicamente a ideia era criar um "esqueleto", que possa agora ser expandido com outras ideias, tipo o uso de formulas matemáticas aplicadas ao código, outros métodos de verificação da chave (sem ir incorporada).

Isto é mais didáctico que outra coisa (pareceu-me). Sempre é um excelente exemplo de manipulação de strings, e da utilização de TStringList que eu não conhecia. :)

Não conhecias a TStringList? É uma boa altura para conheceres! :) Muito utils esta classe! Só por curiosidade, podes até ler e gravar ficheiros de texto directamente para a TStringList, e manipular o conteudo directamente da classe, sem teres de passar por Assign's ou AssignFile's...


"A humanidade está a perder os seus génios... Aristóteles morreu, Newton já lá está, Einstein finou-se, e eu hoje não me estou a sentir bem!"

> Não esclareço dúvidas por PM: Indica a tua dúvida no quadro correcto do forum.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
Rui Carlos

Tirando a parte da chave, isso é a cifra de César.

A questão da chave é que isso permite que qualquer pessoa decifre o texto sem saber a chave. Normalmente, quando cifras uma mensagem o objectivo é impedir que outros a decifrem a menos que saibam a chave.

O encadeado aqui é nada mais do que codificar o proprio resultado do código, quantas vezes for desejado. Aumenta a segurança no sentido em que quando alguém tenta crackar o código, ao terminar fica outra vez com caracteres inintelegíveis. Pode ser que desista e não tente outra vez :).

A sério, assim como está só aumenta o trabalho, até porque com o uso da chave aleatória, de cada vez que concluir tem de voltar a encontrar a chave, visto que é sempre diferente, mas é um principio, caso a unit seja expandida por exemplo para mudar os caracteres de posição, mantendo é claro uma forma de os reordenar ao descodificar, ou mudar a forma como a chave é guardada.

Imagina que cifras uma mensagem 3 vezes, com as chaves c1, c2 e c3. Se bem percebi o código, decifrar consiste basicamente em subtrair primeiro c3, depois c2, e depois c1 aos caracteres do texto cifrado. Mas repara que podias logo à partida subtrair c3+c2+c1 (i.e., usar como chave para decifrar o texto c3+c2+c1), e obtinhas logo o mensagem original.

Assim, cifrar um texto com a chave c1, depois com c2, ..., depois com cn, é equivalente a cifrá-lo logo com c1+c2+...+cn. Como tal, o nível de segurança é igual. A única diferença no caso do programa que apresentaste é que em cada passo adicionavas uma chave, que para alguém que esteja a tentar decifrar a mensagem é lixo, e logo a cada passo acrescentavas mais lixo à mensagem. Este lixo pode complicar um pouco a aplicação de técnicas como a análise de frequências para decifrar o texto, mas apenas em casos extremos, em que a mensagem é muito curta.

Moral da história: aplicar várias vezes uma cifra só é benéfico se a transformação que a cifra opera não for fácil de "compor" (como neste caso, em que basta somar as chaves). Normalmente a composição é dificultada usando diferentes tipos de transformações intercaladas.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
nunopicado

Sim, concordo... :)

O facto de ser sempre a somar facilita a questão.

Por isso é que eu dizia usar outras operações, tipo numa instancia usar a soma, noutra a divisão, noutra o a média, etc, etc... :D

Mas sem duvida, existem algoritmos bem mais seguros do que este... É mesmo só para mostrar um primeiro passo!  :)


"A humanidade está a perder os seus génios... Aristóteles morreu, Newton já lá está, Einstein finou-se, e eu hoje não me estou a sentir bem!"

> Não esclareço dúvidas por PM: Indica a tua dúvida no quadro correcto do forum.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!

Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.

Entrar Agora

×

Aviso Sobre Cookies

Ao usar este site você aceita os nossos Termos de Uso e Política de Privacidade. Este site usa cookies para disponibilizar funcionalidades personalizadas. Para mais informações visite esta página.