
El tema de facturación electrónica es muy extenso y la cuestión principal es lo que no especifican a detalle en la página del SAT, "la generación del sello digital".
En primer lugar tenemos que se necesita decodificar la clave privada, para esto nuestros amigos de [URL="http://www.jensign.com/"]http://www.jensign.com/[/URL] nos proporcionan el código para decodificar la mentada clave privada en la siguiente liga: [URL="http://www.jensign.com/opensslkey/index.html"]http://www.jensign.com/opensslkey/index.html[/URL]
En la página de Microsoft nos explican un poco acerca de la seguridad que se recomienda tener con nuestras claves privadas utilizando Contenedores de Clave Privadas en la siguiente liga: [URL="http://msdn.microsoft.com/es-es/library/tswxhw92(VS.80).aspx"]http://msdn.microsoft.com/es-es/library/tswxhw92(VS.80).aspx[/URL]
Por mi parte, ya teniendo la clave privada a nuestro servicio lo que queda es tomar nuestro comprobante xml, generar la cadena original (que es lo más fácil utilizando la clase System.Xml.Xsl.XslCompiledTransform y nuestro archivo [URL="ftp://ftp2.sat.gob.mx/asistencia_servicio_ftp/publicaciones/solcedi/cadenaoriginal_3_0.xslt"]cadenaoriginal_3_0.xslt[/URL]).
Para efecto de pruebas generé el siguiente método que contiene los pasos importantes para la generación del sello digital. De acuerdo a la liga a la página de Microsoft que les mencioné, no es seguro mantener la clave privada en la PC como lo exige dicho método, pero repito, es sólo para pruebas y ya ustedes sabrán cómo lo aplican en sus sistemas.
/// <summary>
/// Sella digitalmente el comprobante fiscal digital.
/// </summary>
/// <param name="cadenaOriginalEnBytes">Arreglo de bytes que contiene a la Cadena Original del CFD.</param>
/// <param name="xmlClavePrivada">Clave Privada en formato XML (Sólo para efectos de prueba ya que es inseguro).</param>
/// <returns>Devuelve el sello digital en base64</returns>
private string SellarCFD(byte[] cadenaOriginalEnBytes, string xmlClavePrivada)
{
//Se especifica la ubicación de almacenamiento de nuestra clave privada.
//(Hay mejores formas de controlar esto).
CspParameters Parametros = new CspParameters();
Parametros.Flags = CspProviderFlags.UseMachineKeyStore;
//Se crea el objeto RSA y se carga la clave privada que se va a utilizar.
RSACryptoServiceProvider rsaClavePrivada;
rsaClavePrivada = new RSACryptoServiceProvider(1024, Parametros);
rsaClavePrivada.FromXmlString(xmlClavePrivada);
//Se crea el formateador de firma PKCS1 y se establece el algoritmo hash que se utiliza para crear la firma.
RSAPKCS1SignatureFormatter rsaPKCS1 = new RSAPKCS1SignatureFormatter(rsaClavePrivada);
rsaPKCS1.SetHashAlgorithm("MD5");
//Se genera el hash de la cadena original mediente el algoritmo MD5.
MD5CryptoServiceProvider md5CSP = new MD5CryptoServiceProvider();
byte[] cadenaHasMD5 = md5CSP.ComputeHash(cadenaOriginalEnBytes);
//Se sella el hash de la cadena original obteniendo el sello digital en un arreglo de bytes.
byte[] selloDigitalBytes = rsaPKCS1.CreateSignature(cadenaHasMD5);
//Se convierten los bytes en base64.
string selloDigitalB64 = Convert.ToBase64String(selloDigitalBytes);
//Sale nuestro sello digital como pan caliente!
return selloDigitalB64;
}

Espero cualquier duda o sugerencia al respecto.
Suerte con sus aplicaciones Web y de escritorio.
