From f5e983f5b95a9c9142d459e86a7c573d46f5138f Mon Sep 17 00:00:00 2001 From: "carsten.pluntke" Date: Thu, 2 Sep 2010 15:58:09 +0000 Subject: [PATCH] References #2 --- Test_Qt_Frontend/QtSslTest.pro | 16 +++ Test_Qt_Frontend/pindialog.cpp | 37 +++++++ Test_Qt_Frontend/pindialog.h | 22 ++++ Test_Qt_Frontend/qtssltest.cpp | 48 +++++++++ Test_Qt_Frontend/smartcardauth.cpp | 162 +++++++++++++++++++++++++++++ Test_Qt_Frontend/smartcardauth.h | 27 +++++ Test_Qt_Frontend/swsign_cert.pem | 39 +++++++ Test_Qt_Frontend/swsign_interm.pem | 41 ++++++++ Test_Qt_Frontend/swsign_root.pem | 37 +++++++ 9 files changed, 429 insertions(+) create mode 100644 Test_Qt_Frontend/QtSslTest.pro create mode 100644 Test_Qt_Frontend/pindialog.cpp create mode 100644 Test_Qt_Frontend/pindialog.h create mode 100644 Test_Qt_Frontend/qtssltest.cpp create mode 100644 Test_Qt_Frontend/smartcardauth.cpp create mode 100644 Test_Qt_Frontend/smartcardauth.h create mode 100644 Test_Qt_Frontend/swsign_cert.pem create mode 100644 Test_Qt_Frontend/swsign_interm.pem create mode 100644 Test_Qt_Frontend/swsign_root.pem diff --git a/Test_Qt_Frontend/QtSslTest.pro b/Test_Qt_Frontend/QtSslTest.pro new file mode 100644 index 0000000..ba6cd6c --- /dev/null +++ b/Test_Qt_Frontend/QtSslTest.pro @@ -0,0 +1,16 @@ +# ##################################################################### +# Automatically generated by qmake (2.01a) Fr 18. Jun 11:12:34 2010 +# ##################################################################### +TEMPLATE = app +TARGET = +DEPENDPATH += . +INCLUDEPATH += ../engine_securetoken . + +# Input +SOURCES += qtssltest.cpp \ + smartcardauth.cpp \ + pindialog.cpp +QT += webkit +QT += network +HEADERS += smartcardauth.h \ + pindialog.h diff --git a/Test_Qt_Frontend/pindialog.cpp b/Test_Qt_Frontend/pindialog.cpp new file mode 100644 index 0000000..ed094e2 --- /dev/null +++ b/Test_Qt_Frontend/pindialog.cpp @@ -0,0 +1,37 @@ +#include +#include "pindialog.h" + + +PinDialog::PinDialog(QWidget *parent) + : QDialog(parent) +{ + label=new QLabel(tr("Enter &PIN:")); + lineEdit=new QLineEdit; + lineEdit->setEchoMode(QLineEdit::Password); + label->setBuddy(lineEdit); + + okButton=new QPushButton(tr("&OK")); + okButton->setDefault(true); + + cancelButton=new QPushButton(tr("&Cancel")); + + connect(okButton, SIGNAL(clicked()), this, SLOT(accept())); + connect(cancelButton, SIGNAL(clicked()), this, SLOT(reject())); + + QHBoxLayout* tl= new QHBoxLayout; + tl->addWidget(label); + tl->addWidget(lineEdit); + QHBoxLayout* bl= new QHBoxLayout; + bl->addStretch(); + bl->addWidget(okButton); + bl->addWidget(cancelButton); + QVBoxLayout* ml= new QVBoxLayout; + ml->addLayout(tl); + ml->addLayout(bl); + setLayout(ml); +} + +QString PinDialog::pin() const { + // TODO: Cleanup of internal strings as soon as the PIN is retrieved + return lineEdit ? lineEdit->text() : ""; +} diff --git a/Test_Qt_Frontend/pindialog.h b/Test_Qt_Frontend/pindialog.h new file mode 100644 index 0000000..7b54c75 --- /dev/null +++ b/Test_Qt_Frontend/pindialog.h @@ -0,0 +1,22 @@ +#ifndef PINDIALOG_H +#define PINDIALOG_H + +#include +class QLabel; +class QLineEdit; +class QPushButton; + +class PinDialog : public QDialog +{ + Q_OBJECT +public: + PinDialog(QWidget *parent = 0); + QString pin() const; +private: + QLabel* label; + QLineEdit* lineEdit; + QPushButton* okButton; + QPushButton* cancelButton; +}; + +#endif // PINDIALOG_H diff --git a/Test_Qt_Frontend/qtssltest.cpp b/Test_Qt_Frontend/qtssltest.cpp new file mode 100644 index 0000000..d3f2e02 --- /dev/null +++ b/Test_Qt_Frontend/qtssltest.cpp @@ -0,0 +1,48 @@ +#include +#include +#include +#include +#include +#include +#include "smartcardauth.h" + +SmartCardAuth g_scard_auth; + +int main(int argc, char *argv[]) +{ + + SmartCardAuth::initialize(); + + QApplication app(argc, argv); + + QSslConfiguration sslConf(QSslConfiguration::defaultConfiguration()); + + // Works even without specifying the root certificate, we just need to add the intermediates, + // and that's done in SmartCardAuth.cpp +#if 0 + QFile caCertsFile("D:\\QtSmartCardAuth_TMI\\QtSslTest\\swsign_root.pem"); + caCertsFile.open(QIODevice::ReadOnly); + QList chain( QSslCertificate::fromDevice(&caCertsFile) ); + + sslConf.setCaCertificates(chain); +#endif + + sslConf.setPeerVerifyMode(QSslSocket::QueryPeer); + sslConf.setOpenSslHook(&g_scard_auth); + QSslConfiguration::setDefaultConfiguration(sslConf); + + // TODO - IMPORTANT: Error reporting! + // If there is ANY failure (no network, no host resolution, no SSL connection, timeout) we just see a + // blank page! + QWebView web; + + // Works - NEEDS AN INTERMEDIATE CERTIFICATE, either loaded from card or from file, see SmartCardAuth + web.load(QUrl("https://dev.swisssign.com/test/")); + + // web.load(QUrl("https://e2k7.demo8.cryptovision.com/ssl/")); + web.show(); + + int rv=app.exec(); + SmartCardAuth::deinitialize(); + return rv; +} diff --git a/Test_Qt_Frontend/smartcardauth.cpp b/Test_Qt_Frontend/smartcardauth.cpp new file mode 100644 index 0000000..a475068 --- /dev/null +++ b/Test_Qt_Frontend/smartcardauth.cpp @@ -0,0 +1,162 @@ +#include "smartcardauth.h" +#include "pindialog.h" +#include + +#include "engine_sct.h" + +#include + +ENGINE* SmartCardAuth::e=NULL; +enum_certs_s* SmartCardAuth::certs_found=NULL; +QWidget* SmartCardAuth::parent=0; +bool SmartCardAuth::pin_configured=false; +bool SmartCardAuth::pin_rejected=false; + +void SmartCardAuth::initialize() { + QSslSocketPrivate::ensureInitialized(); + + q_ENGINE_load_dynamic(); + e = q_ENGINE_by_id("dynamic"); + + int r=q_ENGINE_ctrl_cmd_string(e, "SO_PATH", "C:\\Windows\\System32\\engine_act.dll", 0); + r=q_ENGINE_ctrl_cmd_string(e, "ID", "act", 0); + r=q_ENGINE_ctrl_cmd_string(e, "LIST_ADD", "1", 0); + r=q_ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0); + + if(!r) + { + unsigned int err = 0; + while((err = q_ERR_get_error())) + { + char *str = q_ERR_error_string(err, NULL); + fprintf(stderr,"%s\n", str); + } + } + + r=q_ENGINE_init(e); + +} + +void SmartCardAuth::deinitialize() { + q_ENGINE_finish(e); + q_ENGINE_cleanup(); +} + +void SmartCardAuth::setPinDlgParent(QWidget* p) { + parent=p; +} + +int SmartCardAuth::client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey) +{ + // NB: Keep in mind that this function is called for EVERY SSL connection to be opened. + + for(size_t i=certs_found->num_certs;i--;) + { + const char *id_p = certs_found->certificate[i].id; + + if(id_p == NULL) continue; + + // Name has the format "slot-x-name-SwissSign_digSig" for the certificate/key we're looking for + std::string name(certs_found->certificate[i].name); + std::string compare("-name-SwissSign_digSig"); + + // Compare the rightmost part of the retrieved name to locate the certificate/keypair + size_t pos = name.length() - compare.length(); + if(name.substr(pos) != compare) + continue; + +// // Filter out the correct certificate depending on well-known sorting criteria +// // Given example searches for a keyword in the certificate's subject, but since we've got +// // the decoded certificate as an X509* structure we can check all the fields. +// X509_NAME* subj_name = q_X509_get_subject_name(certs_found->certificate[i].cert); +// int maxlen = 2048; +// char buf[maxlen+1]; +// buf[maxlen]=0; +// q_X509_NAME_oneline(subj_name, buf, maxlen); +// std::string subject(buf); + +// const char *compare="CN=Carsten Pluntke"; +// if(subject.find(compare) == std::string::npos) +// continue; + + // Here we found a suitable certificate. + + // Now prepare the reference to the SmartCard's private key and a copy of the certificate + // to pass back to the caller. + *x509 = q_X509_dup(certs_found->certificate[i].cert); + *pkey = NULL; + + // If we don't have a PIN yet, pop up a dialog, ask for a PIN and pass it along to the engine + // for usage. + if(!pin_configured) + { + PinDialog dlg(parent); + int ok=dlg.exec(); + if(ok!=1) return 0; // User cancelled + QByteArray pinByteArray=dlg.pin().toAscii(); + char *pin_str = pinByteArray.data(); + + // The engine control command takes a copy and overwrites the source array + if(q_ENGINE_ctrl_cmd_string(e, "PIN", pin_str, 0)) + pin_configured = true; + else + return 0; // Engine refuses to take the PIN + + *pkey = q_ENGINE_load_private_key(e, id_p, NULL, NULL); + + // We do a test authorization on loading of the private key. If the operation fails at all, + // DON'T try again (see below) or we would instantly lock the card in a single session because + // of the retries! + if(!*pkey) + pin_rejected = true; + } + + // Second to nth iteration: We skipped the PIN dialog here, now load the key if we don't have the + // explicit information not to do it (because the PIN is wrong) + if(!*pkey && !pin_rejected) + *pkey = q_ENGINE_load_private_key(e, id_p, NULL, NULL); + + break; + } + + if(!*x509) { + qWarning("Unable to load certificate"); + return 0; + } + + if(!*pkey) { + qWarning("Unable to load key"); + return 0; + } + + return 1; +} + +bool SmartCardAuth::hookInitSslContext(SSL_CTX *ctx) +{ + bool result = false; + + if(!certs_found) + result = (q_ENGINE_ctrl_cmd(e, "ENUM_CERTS", 0, &certs_found, NULL, 0) != 0); + else + result = true; + +#ifdef USE_CERTIFICATE_FILE + // Load a specific intermediate certificate from a file + BIO* cert_file= q_BIO_new_file("D:\\QtSmartCardAuth_TMI\\QtSslTest\\swsign_interm.pem", "r"); + X509* interm=q_PEM_read_bio_X509(cert_file,NULL,NULL, NULL); + q_BIO_free(cert_file); + + q_SSL_CTX_add_extra_chain_cert(ctx,interm); +#else + // Add all of the card's certificates without a private key as intermediate certs + for(size_t i=certs_found->num_certs;i--;) + { + if(certs_found->certificate[i].id == NULL) + q_SSL_CTX_add_extra_chain_cert(ctx, q_X509_dup(certs_found->certificate[i].cert)); + } +#endif + + q_SSL_CTX_set_client_cert_cb(ctx,client_cert_cb); + return true; +} diff --git a/Test_Qt_Frontend/smartcardauth.h b/Test_Qt_Frontend/smartcardauth.h new file mode 100644 index 0000000..0edfb46 --- /dev/null +++ b/Test_Qt_Frontend/smartcardauth.h @@ -0,0 +1,27 @@ +#ifndef SMARTCARDAUTH_H +#define SMARTCARDAUTH_H + +#include +class QWidget; + +struct enum_certs_s; + +class SmartCardAuth : public QOpenSslHook { + +public: + static void initialize(); + static void deinitialize(); + static void setPinDlgParent(QWidget* parent); + + virtual bool hookInitSslContext(SSL_CTX* ctx); + +private: + static int client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey); + static ENGINE* e; + static enum_certs_s* certs_found; + static QWidget* parent; + static bool pin_configured; + static bool pin_rejected; +}; + +#endif // SMARTCARDAUTH_H diff --git a/Test_Qt_Frontend/swsign_cert.pem b/Test_Qt_Frontend/swsign_cert.pem new file mode 100644 index 0000000..90b82ab --- /dev/null +++ b/Test_Qt_Frontend/swsign_cert.pem @@ -0,0 +1,39 @@ +Bag Attributes + localKeyID: 01 00 00 00 + 1.3.6.1.4.1.311.17.3.20: AB FC 95 89 38 6A 06 C3 21 78 B7 AE 9E 87 06 8A C8 79 33 02 + friendlyName: My SwissSign ID +subject=/CN=Markus Tesche/emailAddress=markus.tesche@cryptovision.com +issuer=/C=CH/O=SwissSign AG/CN=SwissSign Personal Silver CA 2008 - G2 +-----BEGIN CERTIFICATE----- +MIIFzDCCBLSgAwIBAgIPCfGkMO74CroouYxQ+mKcMA0GCSqGSIb3DQEBBQUAMFUx +CzAJBgNVBAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxLzAtBgNVBAMTJlN3 +aXNzU2lnbiBQZXJzb25hbCBTaWx2ZXIgQ0EgMjAwOCAtIEcyMB4XDTEwMDQxNjEw +MDI0N1oXDTExMDQxNjEwMDI0N1owRzEWMBQGA1UEAxMNTWFya3VzIFRlc2NoZTEt +MCsGCSqGSIb3DQEJARYebWFya3VzLnRlc2NoZUBjcnlwdG92aXNpb24uY29tMIIB +IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu0DvJNEgXJefs4pdCnGzn6zS +8jTO20XS0Gzu16exDDXZ1aqIUdfj/dV5ya25YiJmOqwkOIvi3ruaXTYEGhGAMXUb +5/AqzjSwJ5Jn5KG2s8zD8GchJf72hUPTF4Pke0aS1tQ+0r3L5uVCDLzMZ839GF1/ +bbp1bb8vgXa7UL0qbeLH4nITT0QgEVoXhx/xGDnvOBfvmy7OQ3/GuOqnFHz6REIe +daYfEMYyxIziYa1aYlyUw1xGIkOcNahznkN6wK+enrJPzLORFcF9soZOGO3cMH7k +tKPxB1P8LeZtgoIXLmrns5aJ11omB+zCRXieZTyj6OAFPR6Z700ozZG4PWAdxwID +AQABo4ICpTCCAqEwWQYDVR0RBFIwUIEebWFya3VzLnRlc2NoZUBjcnlwdG92aXNp +b24uY29toC4GCisGAQQBgjcUAgOgIAwebWFya3VzLnRlc2NoZUBjcnlwdG92aXNp +b24uY29tMA4GA1UdDwEB/wQEAwID+DA1BgNVHSUELjAsBggrBgEFBQcDAgYIKwYB +BQUHAwQGCisGAQQBgjcKAwQGCisGAQQBgjcUAgIwHwYDVR0jBBgwFoAU6zWxVm0V +YFj04SLNHEYcrtAEAGUwgf8GA1UdHwSB9zCB9DBHoEWgQ4ZBaHR0cDovL2NybC5z +d2lzc3NpZ24ubmV0L0VCMzVCMTU2NkQxNTYwNThGNEUxMjJDRDFDNDYxQ0FFRDAw +NDAwNjUwgaiggaWggaKGgZ9sZGFwOi8vZGlyZWN0b3J5LnN3aXNzc2lnbi5uZXQv +Q049RUIzNUIxNTY2RDE1NjA1OEY0RTEyMkNEMUM0NjFDQUVEMDA0MDA2NSUyQ089 +U3dpc3NTaWduJTJDQz1DSD9jZXJ0aWZpY2F0ZVJldm9jYXRpb25MaXN0P2Jhc2U/ +b2JqZWN0Q2xhc3M9Y1JMRGlzdHJpYnV0aW9uUG9pbnQwZAYDVR0gBF0wWzBZBglg +hXQBWQEDAQQwTDBKBggrBgEFBQcCARY+aHR0cDovL3JlcG9zaXRvcnkuc3dpc3Nz +aWduLmNvbS9Td2lzc1NpZ24tU2lsdmVyLUNQLUNQUy1SNC5wZGYwdAYIKwYBBQUH +AQEEaDBmMGQGCCsGAQUFBzAChlhodHRwOi8vc3dpc3NzaWduLm5ldC9jZ2ktYmlu +L2F1dGhvcml0eS9kb3dubG9hZC9FQjM1QjE1NjZEMTU2MDU4RjRFMTIyQ0QxQzQ2 +MUNBRUQwMDQwMDY1MA0GCSqGSIb3DQEBBQUAA4IBAQA6L3y3A9mZ+xziOo71CcWq +WjFl8sqtk0ul6oh0uA7qDT8DP2BjP+uVUZr3fdnzWenL1qLbnh9M90yWLst0vGZ1 +dOBO5Ex+6VgHb95jcK4BztfCYGhGvdtBbWbdJELmPBF+87OL/C/PYRrLvYqDo0XX +P5R1DZeJu732qaFB30Z28Fino7RzuSmngwwWujRQGJs2sVmxjkHqD0Lrxkp9eOQl +XwLo9uhMlEgDhah/dPA+S/+zApB8mNjhILw+3WkPgEsNLob15u5wvJEZ4GD/vK7E +kbMxGDlvSkM6+tWVizxeqhFJgYA2kLeY/pKJ9ZRT2d+k+DJufdWeWMCbWPVEiILc +-----END CERTIFICATE----- diff --git a/Test_Qt_Frontend/swsign_interm.pem b/Test_Qt_Frontend/swsign_interm.pem new file mode 100644 index 0000000..fe6c37b --- /dev/null +++ b/Test_Qt_Frontend/swsign_interm.pem @@ -0,0 +1,41 @@ +Bag Attributes + 1.3.6.1.4.1.311.17.3.20: EB 35 B1 56 6D 15 60 58 F4 E1 22 CD 1C 46 1C AE D0 04 00 65 +subject=/C=CH/O=SwissSign AG/CN=SwissSign Personal Silver CA 2008 - G2 +issuer=/C=CH/O=SwissSign AG/CN=SwissSign Silver CA - G2 +-----BEGIN CERTIFICATE----- +MIIGZzCCBE+gAwIBAgIJAOJWt1OXa3ZYMA0GCSqGSIb3DQEBBQUAMEcxCzAJBgNV +BAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxITAfBgNVBAMTGFN3aXNzU2ln +biBTaWx2ZXIgQ0EgLSBHMjAeFw0wODA3MDkxMTExMDlaFw0yMzA3MDkxMTExMDla +MFUxCzAJBgNVBAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxLzAtBgNVBAMT +JlN3aXNzU2lnbiBQZXJzb25hbCBTaWx2ZXIgQ0EgMjAwOCAtIEcyMIIBIjANBgkq +hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA9/NTXkltjAPlJxchGGCldpQ/FRC4IUDP +NjOsKnKaj2HDa956SQhYPYDYO/CdHUEQAb9rB1YajbM9v2O6MX7ickYYaIfXhU+g +yXsTqdA50YnWNWdodsFflgnNzzoF0T8GBQraFvJD8qQHHaKsgHUBnaDo9zSnv7bm +OWhmUkc5KU20negqrRVhtKIx4BCR2x7kQ/Er3hDBNMtshO5iFCdE2DHx3zwhzMCs +kGjTdGjJF0qOOwmnsQVljQekkK4uet56RG+wAv50/xqH9VjppiXxzIgiJ9jLMcEv +KAxxch73+whObnoFrCF/PwpaZvi/5RYU+RubxJ+6Mw2GlxVdrqEGjwIDAQABo4IC +RjCCAkIwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0O +BBYEFOs1sVZtFWBY9OEizRxGHK7QBABlMB8GA1UdIwQYMBaAFBegzcHkQbY6WzvL +RZ29HMKY+oZYMIH/BgNVHR8EgfcwgfQwR6BFoEOGQWh0dHA6Ly9jcmwuc3dpc3Nz +aWduLm5ldC8xN0EwQ0RDMUU0NDFCNjNBNUIzQkNCNDU5REJEMUNDMjk4RkE4NjU4 +MIGooIGloIGihoGfbGRhcDovL2RpcmVjdG9yeS5zd2lzc3NpZ24ubmV0L0NOPTE3 +QTBDREMxRTQ0MUI2M0E1QjNCQ0I0NTlEQkQxQ0MyOThGQTg2NTglMkNPPVN3aXNz +U2lnbiUyQ0M9Q0g/Y2VydGlmaWNhdGVSZXZvY2F0aW9uTGlzdD9iYXNlP29iamVj +dENsYXNzPWNSTERpc3RyaWJ1dGlvblBvaW50MGQGA1UdIARdMFswWQYJYIV0AVkB +AwEDMEwwSgYIKwYBBQUHAgEWPmh0dHA6Ly9yZXBvc2l0b3J5LnN3aXNzc2lnbi5j +b20vU3dpc3NTaWduLVNpbHZlci1DUC1DUFMtUjMucGRmMHQGCCsGAQUFBwEBBGgw +ZjBkBggrBgEFBQcwAoZYaHR0cDovL3N3aXNzc2lnbi5uZXQvY2dpLWJpbi9hdXRo +b3JpdHkvZG93bmxvYWQvMTdBMENEQzFFNDQxQjYzQTVCM0JDQjQ1OURCRDFDQzI5 +OEZBODY1ODANBgkqhkiG9w0BAQUFAAOCAgEALip22pfzTN9kJ+FbLZXvuVUu27gJ +ZTFAsEu9fJCx2dhxGFPO6DUsmxS6H3SC1FeSwFeTm1AFJXvgldRduER46TOQQf7h +v0abeX1yvDhQGcBoWgay0xveXWfPaZL49awJhdTdWi5qOSPv9O9zWjYew+mNIEdk +Nx85eRPXDlCyrLoZnuqD5EVGBL7NLzkQCJsNifBVsiYkUbNr0XxpPVjVgTU8aEdX +jcYSs88qahVFL4SpTj3BOcrr+95KnK0buGGWBiC4gCMZtHZDHJ+umjheENI49R6e +2QwR1S74yYqHpwyz0ihdI2xOZgXxmGOg3GKBxEficqLgbRl+PV2FRZdogAOl8PXt +25iCzummltrfbjXaGQNg9rBHmAM05bxgtMCQwCj0BG48ufpJhzplOLS1YYIehiHv +mojFdSg1q15SYC867zGLpnv3SAxwPLXXYsu0QsP0jbhEcYwk/NfunyHoqmOWw88H +W/KB0ppwJ1QYzO6h0Qwijl7QmUM5qlJOZxuP2jK8WoOS2jarU3r0EXfq/Nfo3uqX +xm5QDg9E4M8wyouaoaCn/LnoxS3zc/VU/p0o15AjIylPSTN/kHmDSl4eYZFmBBhd +0YhvjC4hW2UBRM12SQAAEPIaEqUdxrYFfogWojYCoymheKskXfAKdA1k2gp5mhVh +SFXeRgS5uQTbqpY= +-----END CERTIFICATE----- diff --git a/Test_Qt_Frontend/swsign_root.pem b/Test_Qt_Frontend/swsign_root.pem new file mode 100644 index 0000000..fc135a0 --- /dev/null +++ b/Test_Qt_Frontend/swsign_root.pem @@ -0,0 +1,37 @@ +Bag Attributes + 1.3.6.1.4.1.311.17.3.20: 17 A0 CD C1 E4 41 B6 3A 5B 3B CB 45 9D BD 1C C2 98 FA 86 58 +subject=/C=CH/O=SwissSign AG/CN=SwissSign Silver CA - G2 +issuer=/C=CH/O=SwissSign AG/CN=SwissSign Silver CA - G2 +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE-----