it-swarm-es.com

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

Estoy creando un entorno de múltiples inquilinos (nube) que necesita enviar (o hacer disponibles para descargar) archivos de configuración para 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 cifrado y seguridad utilizaría para cifrar, compartir y enviar esta información confidencial?

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

¿Cuáles son sus pensamientos sobre esta implementación? En esta aplicación, usaré principalmente C #, Windows Azure, ASP.NET MVC y Silverlight.

Ejemplo de código del lado del agente (RSACryptoProvider)

Esto generará el par de claves públicas 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 (castillo hinchable)

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();
        }
7
goodguys_activate

Cifrar los datos con la clave pública de cada agente es una forma de autenticar implícitamente al agente. No sabe realmente (en una configuración en la que 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 alguna parte, entonces fueron al agente correcto. Esta parece la buena herramienta para su problema.

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

Hay algunas trampas:

  • 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 e implemente los agentes, esto puede ser fácil o no.

  • 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 de cifrado simétrico). Debe cuidar el almacenamiento de esa clave privada, porque la adquisición de 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 RSA de 1024 bits y el relleno PKCS # 1 habitual, existe un límite estricto 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 montón de bytes aleatorios) que luego se utiliza 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 malintencionados, a menudo también hay atacantes activos. Los atacantes pasivos simplemente espían los datos; los atacantes activos también pueden modificarlo. Hay muchos ataques inteligentes que se pueden realizar 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 verificaciones 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 implementados han tropezado con estos y no pueden probarse 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 pasado por 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 biblioteca de código abierto que sí (tiene una versión C #).

Como nota final, si tiene muchos agentes que deberían recibir los mismos datos, puede ser más eficiente para la red cifrar los datos una vez con un secreto key, que luego encripta con la clave pública de cada agente. Esto se llama cifrado de transmisió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 transmisión no solo valga la pena, sino que también sea absolutamente necesaria).

9
Thomas Pornin

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

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

2
Rory Alsop

Según tengo entendido por su pregunta, debe utilizar el protocolo de autenticación de red informática (" que permite a los nodos que se comunican a través de una red no segura para probar su identidad entre sí de una manera segura ") para su trabajo, el propósito y las especificaciones de los protocolos de comunicación es mantener:

  • Frescura:
  • Secreto directo
  • Resiliencia clave conocida
  • Autenticación de clave
  • Confirmación 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 simple es usar:

S es un tercero de confianza, A & B son el cliente que desea 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 ambos protocolos anteriores tienen muchos problemas, si desea estar seguro de que el protocolo es lo suficientemente fuerte, es mejor usar uno de los protocolos enumerados:

0
Am1rr3zA