Implementación segura de compartir secretos de cifrado (nombre de usuario, contraseña) en la nube

7

Estoy creando un entorno multiusuario (nube) que necesita eliminar (o poner a disposición para su descarga) los archivos de configuración para los agentes (servicios en segundo plano) que reciben esta información. Una de las piezas de información en la configuración es un nombre de usuario y contraseña.

Suponiendo que el agente pueda identificarse de forma segura en la nube, ¿qué sistema de encriptación y seguridad usaría para cifrar, compartir, eliminar esta información confidencial?

¿Es suficiente un par de claves públicas privadas? Estoy pensando que los secretos se cifrarán en la clave pública de cada agente, y el valor sin cifrar se descartará.

¿Qué piensas de esta implementación? En general, usaré C # en esta aplicación, Windows Azure, ASP.NET MVC y Silverlight.

Código del lado del agente de muestra (RSACryptoProvider)

Esto generará el par público de claves privadas en C # y no guardará la clave en el disco

public static void AssignNewKey(){
    const int PROVIDER_RSA_FULL = 1;
    const string CONTAINER_NAME = "KeyContainer";
    CspParameters cspParams;
    cspParams = new CspParameters(PROVIDER_RSA_FULL);
    cspParams.KeyContainerName = CONTAINER_NAME;
// CspProviderFlags.UseNonExportableKey -- Prevent less-knowledgeable attacks against PK
// CspProviderFlags.UseUserProtectedKey -- Interactively prompt for password
    cspParams.Flags = CspProviderFlags.UseMachineKeyStore;
    cspParams.ProviderName = "Microsoft Strong Cryptographic Provider";
    rsa = new RSACryptoServiceProvider(cspParams);

    rsa.PersistKeyInCsp = false;

    string publicPrivateKeyXML = rsa.ToXmlString(true);
    string publicOnlyKeyXML = rsa.ToXmlString(false);
    // do stuff with keys...
}

Ejemplo de código del lado del agente Opción 2 (Bouncy Castle)

public void GenerateKey(string username, string password, string keyStoreUrl)
        {
            IAsymmetricCipherKeyPairGenerator kpg = new RsaKeyPairGenerator();
            kpg.Init(new RsaKeyGenerationParameters(BigInteger.ValueOf(0x13), new SecureRandom(), 1024, 8));
            AsymmetricCipherKeyPair kp = kpg.GenerateKeyPair();

            FileStream out1 = new FileInfo(string.Format("{0}secret.asc", keyStoreUrl)).OpenWrite();
            FileStream out2 = new FileInfo(string.Format("{0}pub.asc", keyStoreUrl)).OpenWrite();

            ExportKeyPair(out1, out2, kp.Public, kp.Private, username, password.ToCharArray(), true);

            out1.Close();
            out2.Close();

        }

private static void ExportKeyPair(
            Stream secretOut,
            Stream publicOut,
            AsymmetricKeyParameter publicKey,
            AsymmetricKeyParameter privateKey,
            string identity,
            char[] passPhrase,
            bool armor)
        {
            if (armor)
            {
                secretOut = new ArmoredOutputStream(secretOut);
            }

            PgpSecretKey secretKey = new PgpSecretKey(
                PgpSignature.DefaultCertification,
                PublicKeyAlgorithmTag.RsaGeneral,
                publicKey,
                privateKey,
                DateTime.Now,
                identity,
                SymmetricKeyAlgorithmTag.Cast5,
                passPhrase,
                null,
                null,
                new SecureRandom()
                //                ,"BC"
                );

            secretKey.Encode(secretOut);

            secretOut.Close();

            if (armor)
            {
                publicOut = new ArmoredOutputStream(publicOut);
            }

            PgpPublicKey key = secretKey.PublicKey;

            key.Encode(publicOut);

            publicOut.Close();
        }
    
pregunta random65537 19.01.2011 - 21:14
fuente

3 respuestas

9

Encriptar los datos con la clave pública de cada agente es una forma de autenticar implícitamente al agente. Realmente no sabe (en una configuración donde las comunicaciones pasan por una nube potencialmente maliciosa) si el agente realmente recibió los datos, pero sabe que solo el agente adecuado podría descifrarlos; por lo tanto, si los datos se han ido a algún lugar, entonces fueron al agente correcto. Esto parece la buena herramienta para su problema.

Tenga en cuenta que el cifrado de clave pública podría ser excesivo. Si puede organizar que el agente receptor y el remitente de los datos compartan una clave secreta común (solo un puñado de unas pocas docenas de bytes aleatorios), entonces podría usar un cifrado simétrico para cifrar los datos.

Hay algunos errores:

  • Si utiliza un esquema de cifrado de clave pública, entonces el remitente debe conocer las claves públicas de los agentes de antemano y de manera confiable. Dependiendo de cómo cree y despliegue los agentes, esto puede o no ser fácil.

  • El poder de un agente para recibir los datos proviene de su conocimiento de su clave privada (o de la clave secreta compartida común en el caso del cifrado simétrico). Debe cuidar el almacenamiento de esa clave privada, ya que adquirir una copia de la clave permitiría a un atacante descifrar sus datos cifrados.

  • El cifrado asimétrico funciona solo para mensajes limitados. Por ejemplo, con un RSA de 1024 bits y el relleno PKCS # 1 habitual, hay un límite rígido de 117 bytes en un mensaje. Además, el cifrado y descifrado RSA no es demasiado rápido (aunque lo suficientemente rápido para la mayoría de los propósitos). Por lo tanto, es habitual utilizar un esquema híbrido, en el que no se cifra el mensaje en sí, sino una clave secreta aleatoria (un grupo de bytes aleatorios) que luego se usa para cifrar los datos en sí, con un sistema de cifrado simétrico (AES ), que es rápido e ilimitado en la longitud del mensaje.

  • Cuando hay atacantes pasivos maliciosos, a menudo también hay atacantes activos. Los atacantes pasivos solo espían los datos; Los atacantes activos también pueden modificarlo. Hay muchos ataques inteligentes que pueden realizarse modificando sutilmente los datos cifrados y observando los resultados (las contraseñas enviadas en una conexión SSL se han recuperado de esa manera). Por lo tanto, no solo necesita cifrado, también necesita controles de integridad. Una posibilidad es que el remitente firme los paquetes cifrados y los agentes verifiquen la firma antes de intentar descifrarlos.

Miles de sistemas desplegados han tropezado con estos, y no pueden ser probados de manera eficiente de antemano. Realmente debería usar un formato estándar existente para todo eso, con una biblioteca de soporte que ya ha realizado el esfuerzo de implementarlo correctamente. Sugiero usar CMS o OpenPGP . No sé si C # ya los admite (lo dudo, especialmente en el caso de OpenPGP), pero Bouncy Castle es una fuente abierta biblioteca que hace (tiene una versión en C #).

Como nota final, si tiene muchos agentes que deberían recibir los mismos datos, puede ser más eficiente en la red cifrar los datos una vez con una clave secreta, que luego cifrará con la Clave pública de cada agente. Esto se denomina cifrado de difusión y esto es lo que hacen los proveedores de TV paga (envían el mismo contenido voluminoso a millones de clientes, lo que hace que la emisión no solo valga la pena, sino que también es absolutamente necesaria).

    
respondido por el Thomas Pornin 19.01.2011 - 23:13
fuente
2

Par de clave pública / clave privada: parece prestarse bien a este escenario, ya que debe asumir que los datos en la nube son accesibles para los actores malintencionados. Los datos que coloque en la nube para los agentes se pueden cifrar y autenticar a pesar de la poca seguridad en los entornos de nube.

La respuesta de Thomas Pornin cubre ese lado de las cosas mucho mejor que mi respuesta, así que el único bit adicional que agregaría es que es esencial para que la implementación sea probada , como una configuración débil o deficiente. El código en la implementación podría romper el modelo de seguridad.

    
respondido por el Rory Alsop 19.01.2011 - 21:38
fuente
0

Como entiendo por su pregunta, necesita usar el protocolo de autenticación de red de computadoras (" que permite a los nodos que se comunican a través de una red no segura para demostrar su identidad entre sí de manera segura ") para Su trabajo, propósito y especificaciones de los protocolos de comunicación es mantener:

  • Frescura:
  • Secreto hacia adelante
  • Resistencia clave conocida
  • autenticación de clave
  • confirmación de clave
  • Autenticación de clave explícita

Para lograr la especificación anterior, puede diseñar su propio protocolo de comunicación, el más sencillo es utilizar:

S es un tercero de confianza, A & B son los clientes que quieren tener una comunicación segura.

  
  • A → S: IDA ║IDB
  •   
  • S → A: Kab
  •   
  • A → B: Kab║IDA
  •   

Podemos mejorar el protocolo de esta manera:

  
  • A → S: IDA ║IDB
  •   
  • S → A: E (Kas, [Kab]) ║ E (Kbs, [Kab])
  •   
  • A → B: E (Kbs, [Kab]) ║IDA
  •   

Pero los dos protocolos anteriores tienen muchos problemas, si desea asegurarse de que el protocolo sea lo suficientemente sólido, es mejor usar uno de los protocolos enumerados:

respondido por el Am1rr3zA 20.01.2011 - 11:42
fuente