7

I'm building a multi-tenant (cloud) environment that needs to push out (or make available for download) configuration files for agents (background services) that receive this information. One of the pieces of information in the config is a username and password.

Assuming that the agent can be identified securely to the cloud, what encryption and security system would you use to encrypt, share, push out this sensitive information?

Is a Public Private key pair sufficient? I am thinking the secrets will be encrypted to the public key of each agent, and the unencrypted value will be discarded.

What are your thoughts on this implementation? I'll mostly be using C# in this application, Windows Azure, ASP.NET MVC, and Silverlight.

Sample Agent-side code (RSACryptoProvider)

This will generate the Public Private Key Pair in C#, and not save the key to disk

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...
}

Sample Agent-side code Option 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();
        }
3
  • 2
    Is it just me, or does this whole architecture seem a bit, well, off? "Assuming ... can be identified securely to the cloud" - why would you assume that? How can you ensure it? And, assuming you can (e.g. via private/public keys) - why do you then need to (potentially) expose passwords in client-side config files? You can can already authenticate them "somehow" - so why bother with an additional datum that needs to be kept secret? Of course, that's assuming the password is intended to identify individual agents - otherwise, why ever bother? ... Then again, maybe I'm missing something...
    – AviD
    Commented Jan 20, 2011 at 0:36
  • I appreciate the critique AviD, it's logical. Each agent will be sent a list of servers to connect to, and the username/pass in which to make the RPC/WMI/SNMP connection. These credentials would be encrypted using a public key and available for download. The decrypted password data will only reside in memory, not on disk, unless configured to do so. I don't intend to use the same secret that identifies the agent to encrypt the data in the cloud. Commented Jan 20, 2011 at 1:32
  • As far as how the Agents identify themselves to the cloud and customer account, thats a function of the Agent-installation routine that incorporates a key pair for the site, the customer account user/pass (to the cloud), and a secret I embed within the .NET app itself. I'm protecting that secret with what was known as Microsoft's SLP server, now Inishtech SLP. The part you quoted where I said "assuming... can be identified securely to the cloud" may have been too brief on my part. I wanted to focus on one piece of this equation, but feel free to ask about the rest if you want more detail. Commented Jan 20, 2011 at 1:42

3 Answers 3

9

Encrypting the data with the public key of each agent is a way to implicitly authenticate the agent. You do not really know (in a setup where communications go through a potentially malicious cloud) if the agent really received the data, but you know that only the proper agent could decrypt it; hence, if the data has gone somewhere at all, then it went to the right agent. This looks like the good tool for your problem.

Note that public key encryption could be overkill. If you can arrange for the receiving agent and the data sender to share a common secret key (just a bunch of a few dozen random bytes), then you could use symmetric encryption to encrypt the data.

There are a few gotchas:

  • If you use a public key encryption scheme, then the sender must know the public keys of the agents beforehand, and in a reliable way. Depending on how you create and deploy the agents, this may or may not be easy.

  • The power of an agent to receive the data comes from its knowledge of his private key (or of the common shared secret key in the symmetric encryption case). You must take care of the storage of that private key, because acquiring a copy of the key would allow an attacker to decrypt your encrypted data.

  • Asymmetric encryption works only for limited messages. E.g., with 1024-bit RSA and the usual PKCS#1 padding, there is a hard limit at 117 bytes in a message. Also, RSA encryption and decryption is not too fast (although fast enough for most purposes). Hence, it is customary to use an hybrid scheme, in which you do not encrypt the message itself, but a random secret key (a bunch of random bytes) which you then use to encrypt the data itself, with a symmetric encryption system (AES), which is fast and unlimited in message length.

  • When there are malicious passive attackers, there often are active attackers as well. Passive attackers just spy on data; active attackers can also modify it. There are many smart attacks which can be made by subtly modifying encrypted data and observing the results (passwords sent in a SSL connection have been recovered that way). So you do not need only encryption, you also need integrity checks. One possibility is that the sender signs the encrypted packets, and the agents verify the signature before trying to decrypt them.

Myriads of deployed systems have stumbled on these, and they cannot be efficiently tested beforehand. You really should use an existing standard format for all that, with a support library which has already gone through the effort of implementing it properly. I suggest using CMS or OpenPGP. I do not know if C# already support those (I doubt it, especially in the case of OpenPGP), but Bouncy Castle is an open source library which does (it has a C# version).

As a final note, if you have many agents which should receive the same data, it may be more network-efficient to encrypt the data once with a secret key, which you then encrypt with the public key of each agent. This is called broadcast encryption and this is what pay TV vendors do (they send the very same voluminous content to millions of customers, which makes the broadcast thing not only worthwhile, but also downright necessary).

1
2

Public Key / Private Key pair - would seem to lend itself well to this scenario, as you should assume data in the cloud is accessible to malicious actors. The data you place in the cloud for the agents can be encrypted and authenticated despite the weak security around cloud environments.

Thomas Pornin's answer covers off that side off things way better than my answer, so the only additional bit I would add it that it is essential to get the implementation tested, as a weak configuration or poor code in the implementation could break the security model.

0

As I understand from your question you need to use computer network authentication protocol ("which allows nodes communicating over a non-secure network to prove their identity to one another in a secure manner") for your job, purpose and specifications of communication protocols is to keep:

  • Freshness:
  • Forward Secrecy
  • Known Key Resilience
  • Key Authentication
  • Key Confirmation
  • Explicit Key Authentication

For achieving specification above you can design your own communication protocol, the simplest one is to use :

S is a trusted third party, A & B are the client want to have a secure communication.

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

We can improve the protocol like this:

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

But both protocols above have many problems, if you want to be sure that the protocol is strong enough, it's better using one of the listed protocol:

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .