00001 /* 00002 Copyright (C) 2003 Justin Karneges <justin@affinix.com> 00003 Copyright (C) 2005 Brad Hards <bradh@frogmouth.net> 00004 00005 Permission is hereby granted, free of charge, to any person obtaining a copy 00006 of this software and associated documentation files (the "Software"), to deal 00007 in the Software without restriction, including without limitation the rights 00008 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00009 copies of the Software, and to permit persons to whom the Software is 00010 furnished to do so, subject to the following conditions: 00011 00012 The above copyright notice and this permission notice shall be included in 00013 all copies or substantial portions of the Software. 00014 00015 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00016 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00017 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00018 AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 00019 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 00020 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00021 */ 00022 00023 00024 #include <QtCrypto> 00025 00026 #include <QCoreApplication> 00027 00028 #include <iostream> 00029 00030 // dump out information about some part of the certificate 00031 // we use this same approach for information about the subject 00032 // of the certificate, and also about the issuer of the certificate 00033 static void dumpCertificateInfo( QCA::CertificateInfo info) 00034 { 00035 std::cout << " Organization: " << std::endl; 00036 00037 // Note that a single certificate can apply to more than one 00038 // organisation. QCA::Certificate is a multimap, so when you 00039 // ask for the values associated with a parameter, it returns 00040 // a list. 00041 QList<QString> orgInfoList = info.values(QCA::Organization); 00042 00043 // foreach() interates over each value in the list, and we dump 00044 // out each value. Note that is uncommon for a certificate to 00045 // actually contain multiple values for a single parameter. 00046 QString organization; 00047 foreach( organization, orgInfoList ) { 00048 std::cout << " " << qPrintable(organization) << std::endl; 00049 } 00050 00051 std::cout << " Country: " << std::endl; 00052 // As above, however this shows a more compact way to represent 00053 // the iteration and output. 00054 foreach( QString country, info.values(QCA::Country) ) { 00055 std::cout << " " << qPrintable(country) << std::endl; 00056 } 00057 } 00058 00059 // This is just a convenience routine 00060 static void dumpSubjectInfo( QCA::CertificateInfo subject) 00061 { 00062 std::cout << "Subject: " << std::endl; 00063 00064 dumpCertificateInfo( subject ); 00065 } 00066 00067 00068 // This is just a convenience routine 00069 static void dumpIssuerInfo( QCA::CertificateInfo issuer) 00070 { 00071 std::cout << "Issuer: " << std::endl; 00072 00073 dumpCertificateInfo( issuer ); 00074 } 00075 00076 00077 int main(int argc, char** argv) 00078 { 00079 // the Initializer object sets things up, and 00080 // also does cleanup when it goes out of scope 00081 QCA::Initializer init; 00082 00083 QCoreApplication app(argc, argv); 00084 00085 // We need to ensure that we have certificate handling support 00086 if ( !QCA::isSupported( "cert" ) ) { 00087 std::cout << "Sorry, no PKI certificate support" << std::endl; 00088 return 1; 00089 } 00090 00091 // We are going to work with a number of certificates, and a 00092 // QList is a great template class for that 00093 QList<QCA::Certificate> certlist; 00094 00095 // We do two different cases - if we provide an argument, it is taken 00096 // as a filename to read the keys from. If there is no argument, we just 00097 // read from the system store certificates. 00098 if (argc >= 2) { 00099 // we are going to read the certificates in using a single call 00100 // which requires a CertificateCollection. 00101 QCA::CertificateCollection filecerts; 00102 // The conversion can be tested (although you don't have to) to find out if it 00103 // worked. 00104 QCA::ConvertResult importResult; 00105 // This imports all the PEM encoded certificates from the file specified as the argument 00106 // Note that you pass in a pointer to the result argument. 00107 filecerts = QCA::CertificateCollection::fromFlatTextFile( argv[1], &importResult ); 00108 if ( QCA::ConvertGood == importResult) { 00109 std::cout << "Import succeeded" << std::endl; 00110 // this turns the CertificateCollection into a QList of Certificate objects 00111 certlist = filecerts.certificates(); 00112 } 00113 } else { 00114 // we have no arguments, so just use the system certificates 00115 if ( !QCA::haveSystemStore() ) { 00116 std::cout << "System certificates not available" << std::endl; 00117 return 2; 00118 } 00119 00120 // Similar to above, except we just want the system certificates 00121 QCA::CertificateCollection systemcerts = QCA::systemStore(); 00122 00123 // this turns the CertificateCollection into a QList of Certificate objects 00124 certlist = systemcerts.certificates(); 00125 } 00126 00127 std::cout << "Number of certificates: " << certlist.count() << std::endl; 00128 00129 QCA::Certificate cert; 00130 foreach (cert, certlist) { 00131 std::cout << "Serial Number:"; 00132 // the serial number of the certificate is a QCA::BigInteger, but we can 00133 // just convert it to a string, and then output it. 00134 std::cout << qPrintable(cert.serialNumber().toString()) << std::endl; 00135 00136 // The subject information shows properties of who the certificate 00137 // applies to. See the convenience routines above. 00138 dumpSubjectInfo( cert.subjectInfo() ); 00139 00140 // The issuer information shows properties of who the certificate 00141 // was signed by. See the convenience routines above. 00142 dumpIssuerInfo( cert.issuerInfo() ); 00143 00144 // Test if the certificate can be used as a certificate authority 00145 if ( cert.isCA() ) { 00146 std::cout << "Is certificate authority" << std::endl; 00147 } else { 00148 std::cout << "Is not a certificate authority" << std::endl; 00149 } 00150 00151 // Test if the certificate is self-signed. 00152 if (cert.isSelfSigned() ) { 00153 std::cout << "Self signed" << std::endl; 00154 } else { 00155 std::cout << "Is not self-signed!!!" << std::endl; 00156 } 00157 00158 // Certificate are only valid between specific dates. We can get the dates 00159 // (as a QDateTime) using a couple of calls 00160 std::cout << "Valid from " << qPrintable(cert.notValidBefore().toString()); 00161 std::cout << ", until " << qPrintable(cert.notValidAfter().toString()); 00162 std::cout << std::endl; 00163 00164 // You can get the certificate in PEM encoding with a simple toPEM() call 00165 std::cout << "PEM:" << std::endl; 00166 std::cout << qPrintable(cert.toPEM()); 00167 std::cout << std::endl << std::endl; 00168 } 00169 00170 return 0; 00171 } 00172