silverfighter
silverfighter

Reputation: 6882

How to encrypt a text message with multiple x509 certificates with dotnet core

I would like to encrypt a text message with multiple x509 certificates (public keys).

This is what I have right now:

X509Certificate2 cert = new X509Certificate2(rawBytes);

using(RSA rsa = cert.GetRSAPublicKey()){
   var txtBytes = Encoding.ASCII.GetBytes("hello world");
   var encryptedBytes = rsa.Encrypt(txtBytes, RSAEncryptionPadding.OaepSHA256);
   Console.Writline(Convert.ToBase64String(encryptedBytes);
}

This would let me encrypt the text with 1 public key. I Can not figure out how to do it with multiple certificates. Is this doable at all and does it makes sense?

Basically something like this... but without the XML and with dotnetcore 5 XML encryption and decryption for multiple recipients with X509 certificates

Upvotes: 0

Views: 1549

Answers (2)

bartonjs
bartonjs

Reputation: 33238

The answer that @Crypt32 gave for the algorithmic flow is spot-on. If you're OK with everyone receiving everyone's encrypted key blobs then that happens to describe precisely how EnvelopedCms (and encrypted e-mail) works.

private static byte[] EncryptMessage(
    string message,
    X509Certificate2Collection recipientCerts)
{
    byte[] data = Encoding.UTF8.GetBytes(message);

    EnvelopedCms cms = new EnvelopedCms(new ContentInfo(data));
    CmsRecipientCollection recipients = new CmsRecipientCollection();

    foreach (X509Certificate2 cert in recipientCerts)
    {
        recipients.Add(
            new CmsRecipient(SubjectIdentifierType.SubjectKeyIdentifier, cert));
    }

    cms.Encrypt(recipients);
    return cms.Encode();
}

/// <param name="extraCerts">
///   An optional collection of certificates which is used, in addition to the
///   appropriate certificate stores, to try to decrypt one of the encrypted keys.
/// </param>
private static string DecryptMessage(
    byte[] encodedMessage,
    X509Certificate2Collection extraCerts = null)
{
    EnvelopedCms cms = new EnvelopedCms();
    cms.Decode(encodedMessage);

    if (extraCerts == null)
    {
        cms.Decrypt();
    }
    else
    {
        cms.Decrypt(extraCerts);
    }

    return Encoding.UTF8.GetString(cms.ContentInfo.Content);
}

Upvotes: 2

Crypt32
Crypt32

Reputation: 13974

Actually, it is done in different way. First of all, do not use asymmetric encryption to encrypt large blocks of data, asymmetric encryption is pretty slow. Combine symmetric and asymmetric encryption instead:

  1. First, you generate symmetric key (AES 256, for example)
  2. Use this key to encrypt your message
  3. Take public keys from all recipients who need to access encrypted content and encrypt symmetric key with every public key
  4. In the end you get one ciphertext that contains message and several encrypted keys. The number of encrypted keys matches the number of public keys you used.
  5. Send encrypted message and corresponding encrypted symmetric key to recipients. Say, recipient A gets encrypted content and key encrypted by public key A and so on.

Upvotes: 1

Related Questions