The following Managed C++/CLI example codes demonstrate how to sign email to S/MIME format with digital signature (RSASSA-PSS + SHA256) and how to encrypt email with RSAES-OAEP + AES 128/192/256 + SHA256.
Sections:
Latest EDIFACT requires RSA-SHA256 Signature Algorithm + RSASSA-PSS with SHA256 padding for digital signature, and AES128/192/256 Encrypting Algorithm + RSAES-OAEP + SHA256 Hash for email encryption.
EASendMail uses Windows/.NET built-in function to implement S/MIME, it supports RSASSA-PSS signature + SHA1 padding and AES + RSAES-OAEP, however it has a compatible problem with RSASSA-PSS signature defined in latest EDIFACT (SHA256 padding).
To comply with EDIFACT rule, we implemented a special version with Bouncy Castle
library.
If you need to sign email with digital signature or encrypt email based on the rule of EDIFACT in EUROPE, you should use this version:
You can download it from: http://www.emailarchitect.net/webapp/download/easendmail.bc.exe
To use it in your project, the first step is Add reference
of EASendMail BC to your project
. Please create or open your project with Visual Studio,
then go to menu
-> Project
-> Add Reference
-> .NET
-> Browse...
, and select
Installation Path\Lib\net[version]\EASendMail.dll
from your disk, click Open
-> OK
.
The default Installation path is C:\Program Files (x86)\EASendMail.BC\
You can also install the run-time assembly by NuGet. Run the following command in the NuGet Package Manager Console:
Install-Package EASendMail.BC
The following example codes demonstrate signing email based on EDIFACT rule - S/MIME.
In order to run it correctly, please change SMTP server
, user
, password
, sender
, recipient
value to yours.
#include "stdafx.h"
using namespace System;
using namespace System::Security::Cryptography::X509Certificates;
using namespace EASendMail;
X509Certificate2^ _findCertificate(String ^storeName, String ^emailAddress)
{
X509Certificate2 ^cert = nullptr;
X509Store ^store = gcnew X509Store(storeName, StoreLocation::CurrentUser);
store->Open(OpenFlags::ReadOnly);
X509Certificate2Collection ^certfiicates = store->Certificates->Find(
X509FindType::FindBySubjectName, emailAddress, true);
if (certfiicates->Count > 0)
{
cert = certfiicates[0];
}
store->Close();
return cert;
}
int main(array<System::String ^> ^args)
{
try
{
SmtpMail ^oMail = gcnew SmtpMail("TryIt");
// Set sender email address, please change it to yours
oMail->From = "test@emailarchitect.net";
// Set recipient email address, please change it to yours
oMail->To = gcnew AddressCollection("support@emailarchitect.net");
// Set email subject
oMail->Subject = "test email from Managed C++/CLI with digital signature";
// Set email body
oMail->TextBody = "this is a test email sent from Managed C++ project with digital signature based on EDIFACT rule";
// Digital signature with sha256 hash algorithm + RSASSA-PSS signature + sha256 padding
oMail.SignatureHashAlgorithm = SignatureHashAlgorithmType::SHA256;
oMail.SignatureHashEncryption = SignatureHashEncryptionType::RSA_SSA_PSS_WITH_PARAMETER;
X509Certificate2 ^signerCertificate = _findCertificate("My", oMail->From->Address);
if (signerCertificate == nullptr)
throw gcnew Exception("No signer certificate found!");
oMail->From->Certificate2 = signerCertificate;
// You can also load the signer certificate from a pfx file.
/* String ^pfxPath = "D:\\TestCerts\\signer.pfx";
X509Certificate2 ^signerCertFromPfx = gcnew X509Certificate2(pfxPath,
"nosecret",
X509KeyStorageFlags::Exportable | X509KeyStorageFlags::UserKeySet);
oMail->From->Certificate2 = signerCertFromPfx;
*/
// If you use it in web application,
// please use X509KeyStorageFlags::Exportable | X509KeyStorageFlags::MachineKeySet
// If you use it in .NET core application
// please use X509KeyStorageFlags::Exportable | X509KeyStorageFlags::EphemeralKeySet
// Your SMTP server address
SmtpServer ^oServer = gcnew SmtpServer("smtp.emailarchitect.net");
// User and password for ESMTP authentication, if your server doesn't require
// User authentication, please remove the following codes.
oServer->User = "test@emailarchitect.net";
oServer->Password = "testpassword";
// Most mordern SMTP servers require SSL/TLS connection now.
// ConnectTryTLS means if server supports SSL/TLS, SSL/TLS will be used automatically.
oServer->ConnectType = SmtpConnectType::ConnectTryTLS;
// If your SMTP server uses 587 port
// oServer->Port = 587;
// If your SMTP server requires SSL/TLS connection on 25/587/465 port
// oServer->Port = 25; // 25 or 587 or 465
// oServer->ConnectType = SmtpConnectType::ConnectSSLAuto;
Console::WriteLine("start to send email with digital signature...");
SmtpClient ^oSmtp = gcnew SmtpClient();
oSmtp->SendMail(oServer, oMail);
Console::WriteLine("email was sent successfully!");
}
catch (Exception ^ep)
{
Console::WriteLine("failed to send email with the following error:");
Console::WriteLine(ep->Message);
}
return 0;
}
Note
RSASSA-PSS signature generated by Bouncy Castle is not verified by most email clients (outlook, firebird …), but it does meet the requirement in EDIFACT rule.
The following example codes demonstrate encrypting email message based on EDIFACT rule - S/MIME.
In order to run it correctly, please change SMTP server
, user
, password
, sender
, recipient
value to yours.
#include "stdafx.h"
using namespace System;
using namespace System::Security::Cryptography::X509Certificates;
using namespace EASendMail;
X509Certificate2^ _findCertificate(String ^storeName, String ^emailAddress)
{
X509Certificate2 ^cert = nullptr;
X509Store ^store = gcnew X509Store(storeName, StoreLocation::CurrentUser);
store->Open(OpenFlags::ReadOnly);
X509Certificate2Collection ^certfiicates = store->Certificates->Find(
X509FindType::FindBySubjectName, emailAddress, true);
if (certfiicates->Count > 0)
{
cert = certfiicates[0];
}
store->Close();
return cert;
}
int main(array<System::String ^> ^args)
{
try
{
SmtpMail ^oMail = gcnew SmtpMail("TryIt");
// Set sender email address, please change it to yours
oMail->From = "test@emailarchitect.net";
// Set recipient email address, please change it to yours
oMail->To = gcnew AddressCollection("support@emailarchitect.net");
// Set email subject
oMail->Subject = "test encrypted email from Managed C++/CLI";
// Set email body
oMail->TextBody = "this is a test encrypted email sent from Managed C++ based on EDIFACT rule";
// Email encryption with RAES-OAEP-128 + sha-256 oaep hash algorithm
oMail.EncryptionAlgorithm = EncryptionAlgorithmType::RAES_OAEP_128;
// RAES_OAEP_128 uses AES128, you can also use RAES_OAEP_192 (AES192) and RAES_OAEP_256 (AES256)
oMail.OaepHashAlgorithm = OaepHashAlgorithmType::SHA256;
int count = oMail->To->Count;
for (int i = 0; i < count; i++)
{
MailAddress ^oAddress = dynamic_cast<MailAddress^>(oMail->To[i]);
X509Certificate2 ^encryptCert = _findCertificate("AddressBook", oAddress->Address);
if (encryptCert == nullptr)
encryptCert = _findCertificate("My", oAddress->Address);
if (encryptCert == nullptr)
throw gcnew Exception("No encryption certificate found!");
oAddress->Certificate2 = encryptCert;
// You can also load the encryptor certificate from a cer file like this
/*
String ^cerPath = "D:\\TestCerts\\encryptor.cer";
X509Certificate2 ^encryptCertFromFile = gcnew X509Certificate2(cerPath);
oAddress->Certificate2 = encryptCertFromFile;
*/
}
// Your SMTP server address
SmtpServer ^oServer = gcnew SmtpServer("smtp.emailarchitect.net");
// User and password for ESMTP authentication, if your server doesn't require
// User authentication, please remove the following codes.
oServer->User = "test@emailarchitect.net";
oServer->Password = "testpassword";
// Most mordern SMTP servers require SSL/TLS connection now.
// ConnectTryTLS means if server supports SSL/TLS, SSL/TLS will be used automatically.
oServer->ConnectType = SmtpConnectType::ConnectTryTLS;
// If your SMTP server uses 587 port
// oServer->Port = 587;
// If your SMTP server requires SSL/TLS connection on 25/587/465 port
// oServer->Port = 25; // 25 or 587 or 465
// oServer->ConnectType = SmtpConnectType::ConnectSSLAuto;
Console::WriteLine("start to send encrypted email ...");
SmtpClient ^oSmtp = gcnew SmtpClient();
oSmtp->SendMail(oServer, oMail);
Console::WriteLine("email was sent successfully!");
}
catch (Exception ^ep)
{
Console::WriteLine("failed to send email with the following error:");
Console::WriteLine(ep->Message);
}
return 0;
}
The following example codes demonstrate signing and encrypting email message based on EDIFACT rule - S/MIME.
In order to run it correctly, please change SMTP server
, user
, password
, sender
, recipient
value to yours.
#include "stdafx.h"
using namespace System;
using namespace System::Security::Cryptography::X509Certificates;
using namespace EASendMail;
X509Certificate2^ _findCertificate(String ^storeName, String ^emailAddress)
{
X509Certificate2 ^cert = nullptr;
X509Store ^store = gcnew X509Store(storeName, StoreLocation::CurrentUser);
store->Open(OpenFlags::ReadOnly);
X509Certificate2Collection ^certfiicates = store->Certificates->Find(
X509FindType::FindBySubjectName, emailAddress, true);
if (certfiicates->Count > 0)
{
cert = certfiicates[0];
}
store->Close();
return cert;
}
int main(array<System::String ^> ^args)
{
try
{
SmtpMail ^oMail = gcnew SmtpMail("TryIt");
// Set sender email address, please change it to yours
oMail->From = "test@emailarchitect.net";
// Set recipient email address, please change it to yours
oMail->To = gcnew AddressCollection("support@emailarchitect.net");
// Set email subject
oMail->Subject = "test signed and encrypted email from Managed C++/CLI";
// Set email body
oMail->TextBody = "this is a test signed and encrypted email sent from Managed C++ based on EDIFACT rule";
// Digital signature with sha256 hash algorithm + RSASSA-PSS signature + sha256 padding
oMail.SignatureHashAlgorithm = SignatureHashAlgorithmType::SHA256;
oMail.SignatureHashEncryption = SignatureHashEncryptionType::RSA_SSA_PSS_WITH_PARAMETER;
X509Certificate2 ^signerCertificate = _findCertificate("My", oMail->From->Address);
if (signerCertificate == nullptr)
throw gcnew Exception("No signer certificate found!");
oMail->From->Certificate2 = signerCertificate;
// You can also load the signer certificate from a pfx file.
/* String ^pfxPath = "D:\\TestCerts\\signer.pfx";
X509Certificate2 ^signerCertFromPfx = gcnew X509Certificate2(pfxPath,
"nosecret",
X509KeyStorageFlags::Exportable | X509KeyStorageFlags::UserKeySet);
oMail->From->Certificate2 = signerCertFromPfx;
*/
// If you use it in web application,
// please use X509KeyStorageFlags::Exportable | X509KeyStorageFlags::MachineKeySet
// If you use it in .NET core application
// please use X509KeyStorageFlags::Exportable | X509KeyStorageFlags::EphemeralKeySet
// Email encryption with RAES-OAEP-128 + sha-256 oaep hash algorithm
oMail.EncryptionAlgorithm = EncryptionAlgorithmType::RAES_OAEP_128;
// RAES_OAEP_128 uses AES128, you can also use RAES_OAEP_192 (AES192) and RAES_OAEP_256 (AES256)
oMail.OaepHashAlgorithm = OaepHashAlgorithmType::SHA256;
int count = oMail->To->Count;
for (int i = 0; i < count; i++)
{
MailAddress ^oAddress = dynamic_cast<MailAddress^>(oMail->To[i]);
X509Certificate2 ^encryptCert = _findCertificate("AddressBook", oAddress->Address);
if (encryptCert == nullptr)
encryptCert = _findCertificate("My", oAddress->Address);
if (encryptCert == nullptr)
throw gcnew Exception("No encryption certificate found!");
oAddress->Certificate2 = encryptCert;
// You can also load the encryptor certificate from a cer file like this
/*
String ^cerPath = "D:\\TestCerts\\encryptor.cer";
X509Certificate2 ^encryptCertFromFile = gcnew X509Certificate2(cerPath);
oAddress->Certificate2 = encryptCertFromFile;
*/
}
// Your SMTP server address
SmtpServer ^oServer = gcnew SmtpServer("smtp.emailarchitect.net");
// User and password for ESMTP authentication, if your server doesn't require
// User authentication, please remove the following codes.
oServer->User = "test@emailarchitect.net";
oServer->Password = "testpassword";
// Most mordern SMTP servers require SSL/TLS connection now.
// ConnectTryTLS means if server supports SSL/TLS, SSL/TLS will be used automatically.
oServer->ConnectType = SmtpConnectType::ConnectTryTLS;
// If your SMTP server uses 587 port
// oServer->Port = 587;
// If your SMTP server requires SSL/TLS connection on 25/587/465 port
// oServer->Port = 25; // 25 or 587 or 465
// oServer->ConnectType = SmtpConnectType::ConnectSSLAuto;
Console::WriteLine("start to send encrypted email ...");
SmtpClient ^oSmtp = gcnew SmtpClient();
oSmtp->SendMail(oServer, oMail);
Console::WriteLine("email was sent successfully!");
}
catch (Exception ^ep)
{
Console::WriteLine("failed to send email with the following error:");
Console::WriteLine(ep->Message);
}
return 0;
}
TLS is the successor of SSL, more and more SMTP servers require TLS 1.2
encryption now.
If your operating system is Windows XP/Vista/Windows 7/Windows 2003/2008/2008 R2/2012/2012 R2
, you need to
enable TLS 1.2 protocol in your operating system like this:
Enable TLS 1.2 on Windows XP/Vista/7/10/Windows 2008/2008 R2/2012
Appendix
Comments
If you have any comments or questions about above example codes, please click here to add your comments.