From 69a7f53b0226350d49aacf7886e3b518d231ccc3 Mon Sep 17 00:00:00 2001 From: Pascal Bach Date: Tue, 17 Dec 2019 12:09:41 +0100 Subject: [PATCH] Add support for utf-8 characters in subject This changes the format produced by OpenSSL from being separated by / to , --- Crypto/src/X509Certificate.cpp | 19 +++++--- Crypto/testsuite/src/CryptoTest.cpp | 72 ++++++++++++++++++++++++----- Crypto/testsuite/src/CryptoTest.h | 7 +-- 3 files changed, 78 insertions(+), 20 deletions(-) diff --git a/Crypto/src/X509Certificate.cpp b/Crypto/src/X509Certificate.cpp index 4af1aa9ac..19d99918c 100644 --- a/Crypto/src/X509Certificate.cpp +++ b/Crypto/src/X509Certificate.cpp @@ -38,7 +38,6 @@ namespace Poco { namespace Crypto { - X509Certificate::X509Certificate(std::istream& istr): _pCert(0) { @@ -200,13 +199,21 @@ void X509Certificate::save(const std::string& path) const } +std::string _X509_NAME_oneline_utf8(X509_NAME *name) +{ + BIO * bio_out = BIO_new(BIO_s_mem()); + X509_NAME_print_ex(bio_out, name, 0, (ASN1_STRFLGS_RFC2253 | XN_FLAG_SEP_COMMA_PLUS | XN_FLAG_FN_SN | XN_FLAG_DUMP_UNKNOWN_FIELDS) & ~ASN1_STRFLGS_ESC_MSB); + BUF_MEM *bio_buf; + BIO_get_mem_ptr(bio_out, &bio_buf); + std::string line = std::string(bio_buf->data, bio_buf->length); + BIO_free(bio_out); + return line; +} + void X509Certificate::init() { - char buffer[NAME_BUFFER_SIZE]; - X509_NAME_oneline(X509_get_issuer_name(_pCert), buffer, sizeof(buffer)); - _issuerName = buffer; - X509_NAME_oneline(X509_get_subject_name(_pCert), buffer, sizeof(buffer)); - _subjectName = buffer; + _issuerName = _X509_NAME_oneline_utf8(X509_get_issuer_name(_pCert)); + _subjectName = _X509_NAME_oneline_utf8(X509_get_subject_name(_pCert)); BIGNUM* pBN = ASN1_INTEGER_to_BN(X509_get_serialNumber(const_cast(_pCert)), 0); if (pBN) { diff --git a/Crypto/testsuite/src/CryptoTest.cpp b/Crypto/testsuite/src/CryptoTest.cpp index 830cdf8ef..d42af41e7 100644 --- a/Crypto/testsuite/src/CryptoTest.cpp +++ b/Crypto/testsuite/src/CryptoTest.cpp @@ -54,6 +54,27 @@ static const std::string APPINF_PEM( "-----END CERTIFICATE-----\n" ); +static const std::string UTF8_PEM( + "-----BEGIN CERTIFICATE-----\n" + "MIIDEzCCArigAwIBAgIQAKegojl/YLNUPqTyCnQ4LzAKBggqhkjOPQQDAjB0MQsw\n" + "CQYDVQQGEwJDSDEQMA4GA1UECgwHU2llbWVuczEUMBIGA1UECwwLQlQgRGl2aXNp\n" + "b24xPTA7BgNVBAMMNEt1cnpSUzFNUDIyc3ByaW50NTlwcmVWVlMgcHJvamVjdCBp\n" + "bnRlcm1lZGlhdGUgQ0EgRUMwHhcNMTkxMTI3MDAwMDAwWhcNMjQxMTI4MTkzMzQw\n" + "WjCCAQMxJDAiBgNVBAUTG1BJRDpQWEM1LkUwMDMgU046MTQwMDA0RDhFMjELMAkG\n" + "A1UEBhMCQ0gxEDAOBgNVBAoMB1NpZW1lbnMxFzAVBgNVBAsMDlNJIEJQIERpdmlz\n" + "aW9uMQwwCgYDVQQIDANadWcxHjAcBgNVBAcMFVrDpGhsZXJ3ZWcgNyBSb29tIDU0\n" + "NDEnMCUGCSqGSIb3DQEJARYYcmljaGFyZC5rdXJ6QHNpZW1lbnMuY29tMRgwFgYD\n" + "VQQLDA9TU0wgQ2VydGlmaWNhdGUxMjAwBgNVBAMMKUt1cnpSUzFNUDIyc3ByaW50\n" + "NTlwcmVWVlMuS3VyUFhDNUJOUjM3NjUyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcD\n" + "QgAEJjy+wx/mN9FbW3/IoOAOXdbfQvF1gF8wNasHUeLdn1UsCABnaAZTytqX7gMD\n" + "Y5HS32SIvdULYwsy6Dn3CO5tVKOBmjCBlzAOBgNVHQ8BAf8EBAMCA6gwIAYDVR0l\n" + "AQH/BBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAwHQYDVR0O\n" + "BBYEFIbtuXQJoVh7FlYiWZeWT2ooEQRNMB8GA1UdIwQYMBaAFOtUSuT1OYK7bNS4\n" + "Mqz0UGPoGavuMBUGA1UdEQQOMAyHBAqqt7SHBMCo/AEwCgYIKoZIzj0EAwIDSQAw\n" + "RgIhANBQnB1HFLHp7t8oZbLYsm8nWI0hshmVQupXV9oFwb4qAiEAg5UqSDnvAax3\n" + "LWWgnAZJkUS0AEQXu4Rx9ZiP7wBdFtA=\n" + "-----END CERTIFICATE-----\n" +); CryptoTest::CryptoTest(const std::string& name): CppUnit::TestCase(name) { @@ -99,7 +120,7 @@ void CryptoTest::testEncryptDecryptWithSalt() { Cipher::Ptr pCipher = CipherFactory::defaultFactory().createCipher(CipherKey("aes256", "simplepwd", "Too much salt")); Cipher::Ptr pCipher2 = CipherFactory::defaultFactory().createCipher(CipherKey("aes256", "simplepwd", "Too much salt")); - + for (std::size_t n = 1; n < MAX_DATA_SIZE; n++) { std::string in(n, 'x'); @@ -192,7 +213,7 @@ void CryptoTest::testEncryptDecryptDESECB() void CryptoTest::testEncryptDecryptGCM() { CipherKey key("aes-256-gcm"); - + CipherKey::ByteVec iv(20, 213); key.setIV(iv); @@ -224,7 +245,7 @@ void CryptoTest::testEncryptDecryptGCM() void CryptoTest::testPassword() { CipherKey key("aes256", "password", "salt"); - + std::ostringstream keyStream; Poco::Base64Encoder base64KeyEnc(keyStream); base64KeyEnc.write(reinterpret_cast(&key.getKey()[0]), key.keySize()); @@ -293,7 +314,7 @@ void CryptoTest::testStreams() EncryptingOutputStream encryptor(sstr, *pCipher); encryptor << SECRET_MESSAGE; encryptor.close(); - + DecryptingInputStream decryptor(sstr, *pCipher); std::string result; Poco::StreamCopier::copyToString(decryptor, result); @@ -317,7 +338,7 @@ void CryptoTest::testCertificate() { std::istringstream certStream(APPINF_PEM); X509Certificate cert(certStream); - + std::string subjectName(cert.subjectName()); std::string issuerName(cert.issuerName()); std::string commonName(cert.commonName()); @@ -326,8 +347,8 @@ void CryptoTest::testCertificate() std::string stateOrProvince(cert.subjectName(X509Certificate::NID_STATE_OR_PROVINCE)); std::string organizationName(cert.subjectName(X509Certificate::NID_ORGANIZATION_NAME)); std::string organizationUnitName(cert.subjectName(X509Certificate::NID_ORGANIZATION_UNIT_NAME)); - - assertTrue (subjectName == "/CN=appinf.com/O=Applied Informatics Software Engineering GmbH/OU=Development/ST=Carinthia/C=AT/L=St. Jakob im Rosental/emailAddress=guenter.obiltschnig@appinf.com"); + + assertTrue (subjectName == "CN=appinf.com,O=Applied Informatics Software Engineering GmbH,OU=Development,ST=Carinthia,C=AT,L=St. Jakob im Rosental,emailAddress=guenter.obiltschnig@appinf.com"); assertTrue (issuerName == subjectName); assertTrue (commonName == "appinf.com"); assertTrue (country == "AT"); @@ -335,13 +356,41 @@ void CryptoTest::testCertificate() assertTrue (stateOrProvince == "Carinthia"); assertTrue (organizationName == "Applied Informatics Software Engineering GmbH"); assertTrue (organizationUnitName == "Development"); - + // fails with recent OpenSSL versions: - // assertTrue (cert.issuedBy(cert)); - + // assert (cert.issuedBy(cert)); + std::istringstream otherCertStream(APPINF_PEM); X509Certificate otherCert(otherCertStream); - + + assertTrue (cert.equals(otherCert)); +} + +void CryptoTest::testCertificateUTF8() +{ + std::istringstream certStream(UTF8_PEM); + X509Certificate cert(certStream); + + std::string subjectName(cert.subjectName()); + std::string issuerName(cert.issuerName()); + std::string commonName(cert.commonName()); + std::string country(cert.subjectName(X509Certificate::NID_COUNTRY)); + std::string localityName(cert.subjectName(X509Certificate::NID_LOCALITY_NAME)); + std::string stateOrProvince(cert.subjectName(X509Certificate::NID_STATE_OR_PROVINCE)); + std::string organizationName(cert.subjectName(X509Certificate::NID_ORGANIZATION_NAME)); + std::string organizationUnitName(cert.subjectName(X509Certificate::NID_ORGANIZATION_UNIT_NAME)); + + assertTrue (subjectName == "serialNumber=PID:PXC5.E003 SN:140004D8E2,C=CH,O=Siemens,OU=SI BP Division,ST=Zug,L=Zählerweg 7 Room 544,emailAddress=richard.kurz@siemens.com,OU=SSL Certificate,CN=KurzRS1MP22sprint59preVVS.KurPXC5BNR37652"); + assertTrue (commonName == "KurzRS1MP22sprint59preVVS.KurPXC5BNR37652"); + assertTrue (country == "CH"); + assertTrue (localityName == "Zählerweg 7 Room 544"); + assertTrue (stateOrProvince == "Zug"); + assertTrue (organizationName == "Siemens"); + assertTrue (organizationUnitName == "SI BP Division"); + + std::istringstream otherCertStream(UTF8_PEM); + X509Certificate otherCert(otherCertStream); + assertTrue (cert.equals(otherCert)); } @@ -371,6 +420,7 @@ CppUnit::Test* CryptoTest::suite() CppUnit_addTest(pSuite, CryptoTest, testDecryptInterop); CppUnit_addTest(pSuite, CryptoTest, testStreams); CppUnit_addTest(pSuite, CryptoTest, testCertificate); + CppUnit_addTest(pSuite, CryptoTest, testCertificateUTF8); return pSuite; } diff --git a/Crypto/testsuite/src/CryptoTest.h b/Crypto/testsuite/src/CryptoTest.h index a4d6dd1cf..e4857a939 100644 --- a/Crypto/testsuite/src/CryptoTest.h +++ b/Crypto/testsuite/src/CryptoTest.h @@ -21,11 +21,11 @@ class CryptoTest: public CppUnit::TestCase { public: - enum + enum { MAX_DATA_SIZE = 10000 }; - + CryptoTest(const std::string& name); ~CryptoTest(); @@ -40,7 +40,8 @@ public: void testEncryptInterop(); void testDecryptInterop(); void testCertificate(); - + void testCertificateUTF8(); + void setUp(); void tearDown();