Quiero usar un cifrado híbrido en mi aplicación, así que después de leer muchas líneas terminé con esta implementación, por favor critícalo;) (quiero seguir con .Net)
byte[] aesKey = GetRandomBytes(256); // 256 Bits with RNGCryptoServiceProvider
byte[] aesIV = GetRandomBytes(128); // 128 Bits with RNGCryptoServiceProvider
Pregunta: Si encripto la IV, en mi entender esto sería solo por seguridad en la oscuridad y no agregaría nada a mi seguridad.
Ahora cifro aesKey y aesIV con cada PublicKey (Destinatario).
foreach (RSACryptoServiceProvider key in keys)
{
var data = new EncryptedData();
data.Data = key.Encrypt(bytes, true); // with OAEP padding
data.Fingerprint = CreateFingerprint(key); // SHA1 from the public key
list.Add(data);
}
Pregunta: Si no almacena la huella digital, ¿es denegable?
Pregunta: He leído que el relleno incorrecto podría ser un problema de seguridad, pero ¿qué sucede si cifro una clave aleatoria?
Si un 'signo == verdadero' pasado, firmo los datos con cada clave privada (Remitente), en el caso normal, una clave.
if (sign)
{
foreach (RSACryptoServiceProvider key in privateKeys)
{
var hash = new SHA512Managed();
byte[] hashBytes = hash.ComputeHash(data);
byte[] signHash = key.SignHash(hashBytes, CryptoConfig.MapNameToOID("SHA512"));
var item = new EncryptedData
{
Data = signHash,
Fingerprint = CreateFingerprint(key)
};
encryptedData.Signatures.Add(item);
}
}
Pregunta: ¿Es RSACryptoServiceProvider.SignHash el método correcto? (O SignData?)
Pregunta: Encuentro diferentes enfoques, algunos quieren firmar los datos simples y otros los cifrados. ¿Qué piensas?
Ahora cifro los datos reales
using (var rijAlg = new RijndaelManaged())
{
rijAlg.KeySize = 256;
rijAlg.Key = aesKey;
rijAlg.IV = aesIV;
rijAlg.Mode = CipherModeTextMode; // CipherMode.CBC
rijAlg.Padding = PaddingModeTextMode; // PaddingMode.ISO10126, pad with random data
using (var stream = new MemoryStream())
using (ICryptoTransform encryptor = rijAlg.CreateEncryptor(rijAlg.Key, rijAlg.IV))
using (var encrypt = new CryptoStream(stream, encryptor, CryptoStreamMode.Write))
{
encrypt.Write(data, 0, data.Length);
encrypt.FlushFinalBlock();
return stream.ToArray();
}
}
Al final, muestro este objeto y lo envío a Bob.
public class EncryptedDataHolder
{
public IEnumerable<EncryptedData> EncryptedAesKeys { get; set; }
public IEnumerable<EncryptedData> EncryptedAesIVs { get; set; }
public IEnumerable<EncryptedData> Signatures { get; set; }
public byte[] EncryptedContent { get; set; }
}
public class EncryptedData
{
public byte[] Data { get; set; }
public byte[] Fingerprint { get; set; }
}
Pregunta: ¿Agregaría o eliminaría información?
Vi este gráfico en enlace
enlace
Así que creo que debería usar una clave RSA de 16384 bits para cumplir con el nivel de seguridad de aes 256. Esto funciona con csp = new RSACryptoServiceProvider(16384);
pero toma unos minutos.
Pregunta: ¿Es este enfoque razonable?
¡Muchas gracias!