Encrypt the content using AES and mimekit - c#

I looked at several questions on stackoverflow and I'm not able to find answer pertaining to my requirement. So I'm posting this question:
My requirement says:
The content must be encrypted using AES in FIPS Publication 197 (incorporated by reference in provision 6 of this Standard), and RFC 3565 (incorporated by reference in provision 6 of this Standard).
And it should be signed with RSA algorithm specified in RFC 4056.
I saw this post: MimeKit encrypt Message with AES
CmsRecipient CmsRecipient = new CmsRecipient("mail.cer");
CmsRecipient.EncryptionAlgorithms = new EncryptionAlgorithm[] { EncryptionAlgorithm.AES256 };
to1.Add(CmsRecipient);
var signed = MultipartSigned.Create(ctx, signer, multipart);
var encrypted = ApplicationPkcs7Mime.Encrypt(ctx, to1, signed);
message.Body = MultipartSigned.Create(ctx, signer, encrypted);
It seems like in the above code, we expect the AES key to be part of the "mail.cer" certificate?
How do we encrypt the mail content using AES key and mimekit libraries, provided I've a secret key in the form of a string?

Related

Verifying a RSA signature made by Crypto Node.JS in C#

I'm trying to build a web service using Express/NodeJS which signs a piece of information. The signed data is received and verified by a client written in C#. You'll have to forgive my inexperience in cryptography and its associated technologies.
First off, I generate a certificate for the C# client and a private key for the NodeJS application using OpenSSL;
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days
365
In the NodeJS application, I have the following code;
const crypto = require('crypto')
const fs = require('fs')
var pem = fs.readFileSync('./keys/key.pem');
var key = pem.toString('ascii');
var privateKey = crypto.createPrivateKey({
'key': key,
'format': 'pem',
'passphrase': '<PASSPHRASE>',
});
function sign(identifier){
var sign = crypto.createSign('RSA-SHA256');
sign.update(identifier);
var sig = sign.sign(privateKey, 'base64');
return sig;
}
exports.sign = sign;
In this case, the parameter identifier is the data to be signed. The client will receive this, and the signature generated, sig.
In the C# client I have the following snippet;
X509Certificate2 cert = new X509Certificate2(Convert.FromBase64String(pub));
using (var sha256 = SHA256.Create())
{
using (var rsa = cert.GetRSAPublicKey())
{
bool results = rsa.VerifyData(data, signature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
Console.WriteLine(results.ToString());
}
}
The pub is the generated certificate in Base64, it is stored in a const string. The data contains the same information as identifier in the NodeJS application, but it's converted to bytes using Convert.FromBase64String(...), and likewise the signature is the data returned from sig in the NodeJS application, only converted from Base64 to byte data.
When all information is inserted, VerifyData() returns false, this leads me to believe that there's some kind of missmatch between the cryptographic configurations of the web service and the client.
Any ideas?
As pointed out in the comments, the problem was that data in the C# client was converted to from Base64 when the data in the NodeJS application read from UTF-8.
The solution was to convert the string using Encoding.UTF8.GetBytes()
Thanks for the quick response!

How to sign using new keyvault client from azure.security.keyvault

I recently started to replace the old Azure KeyVault client from the Microsoft.Azure.KeyVaultnamespace with the newer one in Azure.Security.KeyVault.
This works without any issues when getting secrets and certificates, but I am not sure how to sign anymore
How do I sign using the new keyvault client?
Did you check Azure SDK Azure.Security.KeyVault.Keys package on github?
Example code from that source:
SignResult rsaSignDataResult = rsaCryptoClient.SignData(SignatureAlgorithm.RS256, data);
Debug.WriteLine($"Signed data using the algorithm {rsaSignDataResult.Algorithm}, with key {rsaSignDataResult.KeyId}. The resulting signature is {Convert.ToBase64String(rsaSignDataResult.Signature)}");
For azure key vault, we need to create a signature from a digest using the specified key.
So, you could refer to the below code to sign some arbitrary data and verify the signatures using the CryptographyClient with both the EC and RSA keys we created.
byte[] digest = null;
using (HashAlgorithm hashAlgo = SHA256.Create())
{
digest = hashAlgo.ComputeHash(data);
}
SignResult rsaSignResult = rsaCryptoClient.Sign(SignatureAlgorithm.RS256, digest);
If you want to sign certificate you could refer to this article.

Encrypting the X509Certificate public Key

All, I am working on IDP initiated web sso for a project and the Service Provider has this requirement to RSA encrypt the AES-128 symmetric key(ECB with PKCS1 padding) and Base64 encode that before adding this to the AttributeStatement section of SAML 2.0 response .My understanding is RSA encryption is asymmetric and the key we have to encrypt is the Service Providers public key.But we dont have SP's public certificate ,so I decided to RSA encrypt our X509Certicate's public key
This is the code I have and it throws a Bad Length Cryptographic exception on calling the Encrypt method on RSACryptoServiceProvider class.Does anyone know what the issue?
using(var rsa = cert.PublicKey.Key as RSACryptoServiceProvider)
{
rsa.KeySize = 1024;
byte[] encryptedKey = rsa.Encrypt(cert.GetPublicKey(),false);
encodedPublicKey = Convert.ToBase64String(encryptedKey);
}
The amount of data that you are able to encrypt using RSA public key must be (I don't know the exact equation) less than the length of the public key.
In case of encrypting AES-128 you will be encrypting 128 bits.

Hash X509 certificate with SHA 256 in c#

I work on an EBICS implementation in C# and I need to send to my bank the hash of my three certificates in SHA256 format in order to enable EBICS link with it.
I generated them in C# with BouncyCastle and now I have a X509Certificate2 object.
So to hash my certificate I used the following code :
String HashCertificate = Certificat.GetCertHashString();
And he return me the following result :
21952A5F79CA3232A656794EE4532BECF5AE3960
But the length don't match with the lenght of the hash of the bank certificate :
57436AD3D09989ED74F4FCCDBF7668C43F8BF87C933F90B065ED442A22E5B0BF
So I think the GetCertHashString() function return the hash of the certificate in SHA1 format and I have no idea how I can hash it in SHA256.
Can you help me please ?
Thank you in advance
As MSDN says GetCertHashString method always
Returns the SHA1 hash value for the X.509v3 certificate as a hexadecimal string.
regardless of signature algorithm since it is Windows specific thumbprint used internally in certifcates store.
You can calculate any other hash by accessing certificate content from its RawData property, e.g. for SHA256:
using (var hasher = SHA256.Create())
{
var hash = hasher.ComputeHash(cert.RawData);
Console.WriteLine(BitConverter.ToString(hash));
}

Is it possible to create a signed email with an opaque signature using MimeKit?

Basically as the questions states.
I have written a program to sign an email using an X509Certificate2 installed on a users machine. This is done with MimeKit, which makes it very easy (as shown).
var signer = new CmsSigner(certificate, key);
signer.DigestAlgorithm = DigestAlgorithm.Sha1;
message.Body = MultipartSigned.Create(ctx, signer, messageContent);
I've just been asked if it is possible to create this signed email using an 'opaque' signature instead of a detached signature. I believe there is an option in OpenSSL that can do this(??).
Anyway, I've been unable to find any mention of an 'opaque' option in relation to MimeKit.
Is this possible, and if so, how?
Yes, this is also possible. With regards to S/MIME, when people refer to an opaque signature, what they mean is that they want a signature in the application/pkcs7-mime format. Here's how you would go about creating that:
var signer = new CmsSigner(certificate, key);
signer.DigestAlgorithm = DigestAlgorithm.Sha1;
message.Body = ApplicationPkcs7Mime.Sign(ctx, signer, messageContent);
Hope that helps!
Note:
In late 2013, Microsoft announced that they would be retiring their
use of SHA-1 in their products by 2016 with the assumption that its
days as an unbroken digest algorithm were numbered. It is speculated
that the SHA-1 digest algorithm will be vulnerable to collisions, and
thus no longer considered secure, by 2018.
Microsoft and other vendors plan to move to the SHA-2 suite of digest
algorithms which includes the following 4 variants: SHA-224, SHA-256,
SHA-384, and SHA-512.
public void SignEmail( MimeMessage m, Org.BouncyCastle.X509.X509Certificate certificate, Org.BouncyCastle.Crypto.AsymmetricKeyParameter key, MailboxAddress sender, MimeEntity content)
{
var signer = new MimeKit.Cryptography.CmsSigner( certificate, key );
signer.DigestAlgorithm = DigestAlgorithm.Sha1;
m.Body = ApplicationPkcs7Mime.Sign( sender, signer.DigestAlgorithm, content );
}

Categories