C++ にて VMime を使って TLS 接続してサーバ明書を検証する

C++ にて VMime を使って メールを送信する
の続きです。

TLS

TLS (Transport Layer Security) は、インターネットにて 通信路を暗号化するためのプロトコルです。

参考 : wikipedia TLS

Gmail では必須です。

Gmail 送受信時のメールの暗号化

VMime の TLS

VMime Book に記載されている

TLS / SSLを使用した安全な接続

TLSを有効にするには、 connection.tlsプロパティをtrue に設定する。

theService−>setProperty(”connection. tls”, true);

VMime の証明書の検証

VMime のデフォルトでは、 certificateException が発生する。 これは、認証局の証明書が設定されていないためです。
認証局の証明書を設定した独自の証明書ベリファイアを作成する必要がある。

下記は、VMime Book に掲載されている例

VMime Book 証明書の検証

ファイルからX.509証明書を読み込む

vmime: : shared ptr <vmime: : security : : cert : : X509Certificate> loadX509CertificateFromFile(const std::string& path)
{
vmime:: utility ::inputStreamAdapter is(certFile);
vmime: : shared ptr <vmime: : security::cert ::X509Certificate> cert ;
cert = vmime::security::cert::X509Certificate::import(is); return cert;
}

デフォルトの証明書ベリファイアにて、認証局の証明書を設定する

vmime::shared ptr <vmime::security::cert ::defaultCertificateVerifier> vrf = vmime::make shared <vmime::security::cert::defaultCertificateVerifier>();

// Load root CAs (such as Verisign or Thawte)
std::vector <vmime::shared ptr <vmime::security::cert::X509Certificate>> rootCAs;
rootCAs.push back(loadX509CertificateFromFile("/path/to/root−ca1.cer"); rootCAs.push back(loadX509CertificateFromFile("/path/to/root−ca2.cer"); rootCAs.push back(loadX509CertificateFromFile("/path/to/root−ca3.cer");
vrf->setX509RootCAs(rootCAs);

// Then, load certificates that the user explicitely chose to trust
std ::vector <vmime::shared ptr <vmime::security::cert::X509Certificate> > trusted;
 trusted.push_back(loadX509CertificateFromFile("/path/to/trusted−site1.cer");
trusted.push_back(loadX509CertificateFromFile("/path/to/trusted−site2.cer);
vrf−>setX509TrustedCerts(trusted);

独自の証明書ベリファイアを作成する

class myCertVerifier : public vmime::security::cert::certificateVerifier {
public :
void verify(vmime::shared ptr <certificateChain> certs) {
// Obtain the subject’s certificate
vmime::shared ptr <vmime::security::cert::certificate> cert = chain−>getAt(0);
std::cout << std::endl;
std::couts << "Server sent a ' " << c e r t −>getType() <<  " ' "
<< "certificate." << std::endl;
std::cout <<  "Do you want to accept this certificate? (Y/n) " ;
std::cout.flush();
std::string answer;
std::getline(std::cin, answer);
if (answer.length() != 0 && (answer[0] == 'Y'  || answer[0] == 'y' ) ) return;
// OK, we trust the certificate

// Don’t trust this certificate
throw vmime::security::cert::certificateException(); 
} };

同封されている証明書ベリファイアのサンプルコード: example6_certificateVerifier.hpp

認証局の証明書を入手する

Gmail サーバーの場合は、 下記から ルート局証明書(Root CA)と下位局証明書 (Subordinate CA) をダウンロードする

Google Trust Services

全体のコードは、githubに公開した。
https://github.com/ohwada/MAC_cpp_Samples/tree/master/vmime/smtp