quinta-feira, 26 de agosto de 2010

Criptografia utilizando JAVA e .NET

Um problema recorrente aqui no laboratório é a troca de dados sensíveis entre sistemas que utilizam tecnologias diferentes. Resumindo o problema:

  • Trata-se de informação sensível;

  • A informação, muitas vezes, trafega por redes inseguras e vulneráveis;

  • Os sistemas interessados utilizam tecnologias diferentes.


A ideia aqui é utilizar3DES, um algoritmo de chave simétrica ao mesmo tempo seguro e suportado pela maioria das tecnologias atuais. Antes de continuar com a solução, vamos dar uma olhada no exemplo de classes JAVA e .NET(C#) compatíveis entre si.

Java:

public class Cipher3DES {

SecretKeySpec chave;
IvParameterSpec iv;
Cipher cifrador;

public Cipher3DES(String key, String initializationVector) throws Exception {
cifrador = Cipher.getInstance("DESede/CBC/PKCS5Padding");
chave = new SecretKeySpec(key.getBytes("UTF8"), "DESede");
iv = new IvParameterSpec(initializationVector.getBytes());
}

public String encryptText(String original) throws Exception {
byte[] plaintext = original.getBytes("UTF8");
cifrador.init(Cipher.ENCRYPT_MODE, chave, iv);
byte[] cipherText = cifrador.doFinal(plaintext);
return new String(Base64Coder.encode(cipherText));
}

public String decryptText(String hidden) throws Exception {
byte[] hiddentext = Base64Coder.decode(hidden.toCharArray());
cifrador.init(Cipher.DECRYPT_MODE, chave, iv);
byte[] originalText = cifrador.doFinal(hiddentext);
return new String(originalText);
}
}

Exemplo de uso:

Cipher3DES c = new Cipher3DES("012345678901234567890123", "01234567");
String segredo = "Frase que não deve ser lida";
String escondido = c.encryptText(segredo);
String original = c.decryptText(escondido);

.NET(C#):

public class Cipher3DES{

TripleDESCryptoServiceProvider tdes;

public Cipher3DES(string chave, string iv){
if (chave.Length != 24)
throw new Exception("Chave de criptografia deve ter tamaho 24");
if (iv.Length != 8)
throw new Exception("Vetor de inicialização deve ter tamaho 8");

tdes = new TripleDESCryptoServiceProvider();
tdes.Key = Encoding.UTF8.GetBytes(chave);
tdes.IV = Encoding.UTF8.GetBytes(iv);
}

public string encryptText(string textToEncrypt){
byte[] buffer = Encoding.UTF8.GetBytes(textToEncrypt);
return Convert.ToBase64String(tdes.CreateEncryptor().TransformFinalBlock(buffer, 0, buffer.Length));
}

public string decryptText(string textToDecrypt){
byte[] buffer = Convert.FromBase64String(textToDecrypt);
return Encoding.UTF8.GetString(tdes.CreateDecryptor().TransformFinalBlock(buffer, 0, buffer.Length));
}
}

Exemplo de uso:

Cipher3DES c = new Cipher3DES("012345678901234567890123", "01234567");
String segredo = "Frase que não deve ser lida";
String escondido = c.encryptText(segredo);
String original = c.decryptText(escondido);

Considerações sobre a solução

  • Enquanto o .NET é bastante flexível quanto aos tamanhos da chave e do vetor de inicialização, o JAVA é bastante restritivo, de acordo com o padrão de chaves de 168 bits e ivs de 8 bytes.

  • Por questões de compatibilidade, os exemplo utilizam sempre UTF8 e os resultados das criptografias são representados em base64. Note que a base64 é suportada por padrão no .NET, enquanto em JAVA nós utilizamos a classe Base64Coder.

  • As implementações do algoritmo de criptografia utilizadas foram javax.crypto.Cipher do JAVA e System.Security.Cryptography do .NET.



Fontes:
http://en.wikipedia.org/wiki/Triple_DES
http://blog.bluesam.com/2009/07/triple-des-encryption-implementation.html
http://tripoverit.blogspot.com/2009/06/tripledes-encryption-compatibility.html
http://www.source-code.biz/base64coder/java/

Um comentário:

  1. Fico contente que estejamos utilizando um algoritmo de criptografia mais interessante que o DES. Ele é bem rápido, porém, já está mais que provado que sua quebra pode se dar em pouquíssimo tempo. Palácio, você sabe se existe algo para Ruby com Triple DES?

    ResponderExcluir