desencriptar - Encriptación compatible entre Android y C#
encriptar y desencriptar en c++ (5)
Sí, debería estar bien, siempre que el tamaño de la clave sea el mismo: AES de 128 bits y el modo de cifrado de bloque correcto (CBC). Es posible que tenga problemas con el relleno, pero eso debería ser bastante fácil de resolver. Me encontré con estos problemas con Java y Python recientemente, pero al final todo funcionó. Base64 para la codificación debería estar bien sobre HTTP. ¡Buena suerte!
He encontrado muchos ejemplos de cómo hacer el cifrado en C #, y un par para Android, pero estoy buscando una forma de manejar el cifrado (usando algo como AES, TripleDES, etc.) desde Android, y finalmente terminaré siendo descifrado en C #. Encontré un ejemplo para codificar AES en Android y codificar / decodificar AES en C #, pero no estoy seguro si estos son compatibles (C # requiere una IV, no se especifica nada para esto en el ejemplo de Android). Además, una recomendación sobre una buena forma de codificar la cadena encriptada para la transmisión a través de HTTP (Base64?) Sería útil. Gracias.
Si implementa correctamente el mismo cifrado (como AES) y el modo (como CTR, CFB, CCM, etc.) en ambos extremos, el texto cifrado de un extremo se puede descifrar por el otro extremo independientemente de la plataforma.
El ejemplo de Android al que vinculó parece usar el modo ECB y, por lo tanto, no es seguro para sus propósitos. Es sumamente importante que comprenda las implicaciones del modo de bloque que selecciona. Es muy fácil equivocarse en crypto en este nivel, lo que da como resultado un sistema que no es tan seguro como crees.
EDIT: retiro eso, no está usando ECB, pero la forma en que genera el IV no es práctica. En cualquier caso, mi punto de entender las implicaciones de los modos de bloque se mantiene.
Puedes comenzar con este artículo de wikipedia . El libro de Bruce Schneier '' Practical Cryptography'' también es muy valioso para cualquiera que implemente seguridad criptográfica.
En cuanto a la codificación de la cadena, si debe convertir la cadena en texto ASCII, Base64 es tan buena como cualquier otra, pero le sugiero que investigue el uso de HTTP PUT o POST para evitarle este paso adicional.
Obtuve ayuda de http://oogifu.blogspot.com/2009/01/aes-in-java-and-c.html .
Aquí está mi clase de Java:
package com.neocodenetworks.smsfwd;
import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import android.util.Log;
public class Crypto {
public static final String TAG = "smsfwd";
private static Cipher aesCipher;
private static SecretKey secretKey;
private static IvParameterSpec ivParameterSpec;
private static String CIPHER_TRANSFORMATION = "AES/CBC/PKCS5Padding";
private static String CIPHER_ALGORITHM = "AES";
// Replace me with a 16-byte key, share between Java and C#
private static byte[] rawSecretKey = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
private static String MESSAGEDIGEST_ALGORITHM = "MD5";
public Crypto(String passphrase) {
byte[] passwordKey = encodeDigest(passphrase);
try {
aesCipher = Cipher.getInstance(CIPHER_TRANSFORMATION);
} catch (NoSuchAlgorithmException e) {
Log.e(TAG, "No such algorithm " + CIPHER_ALGORITHM, e);
} catch (NoSuchPaddingException e) {
Log.e(TAG, "No such padding PKCS5", e);
}
secretKey = new SecretKeySpec(passwordKey, CIPHER_ALGORITHM);
ivParameterSpec = new IvParameterSpec(rawSecretKey);
}
public String encryptAsBase64(byte[] clearData) {
byte[] encryptedData = encrypt(clearData);
return net.iharder.base64.Base64.encodeBytes(encryptedData);
}
public byte[] encrypt(byte[] clearData) {
try {
aesCipher.init(Cipher.ENCRYPT_MODE, secretKey, ivParameterSpec);
} catch (InvalidKeyException e) {
Log.e(TAG, "Invalid key", e);
return null;
} catch (InvalidAlgorithmParameterException e) {
Log.e(TAG, "Invalid algorithm " + CIPHER_ALGORITHM, e);
return null;
}
byte[] encryptedData;
try {
encryptedData = aesCipher.doFinal(clearData);
} catch (IllegalBlockSizeException e) {
Log.e(TAG, "Illegal block size", e);
return null;
} catch (BadPaddingException e) {
Log.e(TAG, "Bad padding", e);
return null;
}
return encryptedData;
}
private byte[] encodeDigest(String text) {
MessageDigest digest;
try {
digest = MessageDigest.getInstance(MESSAGEDIGEST_ALGORITHM);
return digest.digest(text.getBytes());
} catch (NoSuchAlgorithmException e) {
Log.e(TAG, "No such algorithm " + MESSAGEDIGEST_ALGORITHM, e);
}
return null;
}
}
Usé http://iharder.sourceforge.net/current/java/base64/ para la codificación base64.
Aquí está mi clase de C #:
using System;
using System.Text;
using System.Security.Cryptography;
namespace smsfwdClient
{
public class Crypto
{
private ICryptoTransform rijndaelDecryptor;
// Replace me with a 16-byte key, share between Java and C#
private static byte[] rawSecretKey = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
public Crypto(string passphrase)
{
byte[] passwordKey = encodeDigest(passphrase);
RijndaelManaged rijndael = new RijndaelManaged();
rijndaelDecryptor = rijndael.CreateDecryptor(passwordKey, rawSecretKey);
}
public string Decrypt(byte[] encryptedData)
{
byte[] newClearData = rijndaelDecryptor.TransformFinalBlock(encryptedData, 0, encryptedData.Length);
return Encoding.ASCII.GetString(newClearData);
}
public string DecryptFromBase64(string encryptedBase64)
{
return Decrypt(Convert.FromBase64String(encryptedBase64));
}
private byte[] encodeDigest(string text)
{
MD5CryptoServiceProvider x = new System.Security.Cryptography.MD5CryptoServiceProvider();
byte[] data = Encoding.ASCII.GetBytes(text);
return x.ComputeHash(data);
}
}
}
¡Realmente espero que esto ayude a alguien más!
En el ejemplo del código fuente c # proporcionado, tenga cuidado con esta línea:
Encoding.ASCII.GetString(newClearData);
UTF-8 es la codificación predeterminada para Android, por lo que la cadena encriptada (especialmente caracteres no ASCII como el chino) se pasará a C # asumiendo UTF-8. El texto se convierte codificado si se decodifica de nuevo en cadena usando codificación ASCII. Aquí hay una mejor,
Encoding.UTF8.GetString(newClearData);
¡Gracias!
La mayoría de los ejemplos en Internet son una implementación débil de AES. Para que una implementación sea fuerte, se debe usar IV aleatoria todo el tiempo y la clave debe ser hash.
Para una implementación más segura (aleatorio IV + clave hash) multiplataforma (android, ios, c #) de AES, consulte mi respuesta aquí - https://.com/a/24561148/2480840