• Skip to content
  • Skip to link menu
KDE 4.4 API Reference
  • KDE API Reference
  • KDE Support
  • Sitemap
  • Contact Us
 

qca

qca_publickey.cpp

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2003-2007  Justin Karneges <justin@affinix.com>
00003  * Copyright (C) 2004,2005  Brad Hards <bradh@frogmouth.net>
00004  *
00005  * This library is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU Lesser General Public
00007  * License as published by the Free Software Foundation; either
00008  * version 2.1 of the License, or (at your option) any later version.
00009  *
00010  * This library is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  * Lesser General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU Lesser General Public
00016  * License along with this library; if not, write to the Free Software
00017  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00018  * 02110-1301  USA
00019  *
00020  */
00021 
00022 #include "qca_publickey.h"
00023 
00024 #include "qcaprovider.h"
00025 
00026 #include <QFile>
00027 #include <QTextStream>
00028 
00029 namespace QCA {
00030 
00031 Provider::Context *getContext(const QString &type, const QString &provider);
00032 Provider::Context *getContext(const QString &type, Provider *p);
00033 
00034 bool stringToFile(const QString &fileName, const QString &content)
00035 {
00036     QFile f(fileName);
00037     if(!f.open(QFile::WriteOnly))
00038         return false;
00039     QTextStream ts(&f);
00040     ts << content;
00041     return true;
00042 }
00043 
00044 bool stringFromFile(const QString &fileName, QString *s)
00045 {
00046     QFile f(fileName);
00047     if(!f.open(QFile::ReadOnly))
00048         return false;
00049     QTextStream ts(&f);
00050     *s = ts.readAll();
00051     return true;
00052 }
00053 
00054 bool arrayToFile(const QString &fileName, const QByteArray &content)
00055 {
00056     QFile f(fileName);
00057     if(!f.open(QFile::WriteOnly))
00058         return false;
00059     f.write(content.data(), content.size());
00060     return true;
00061 }
00062 
00063 bool arrayFromFile(const QString &fileName, QByteArray *a)
00064 {
00065     QFile f(fileName);
00066     if(!f.open(QFile::ReadOnly))
00067         return false;
00068     *a = f.readAll();
00069     return true;
00070 }
00071 
00072 bool ask_passphrase(const QString &fname, void *ptr, SecureArray *answer)
00073 {
00074     PasswordAsker asker;
00075     asker.ask(Event::StylePassphrase, fname, ptr);
00076     asker.waitForResponse();
00077     if(!asker.accepted())
00078         return false;
00079     *answer = asker.password();
00080     return true;
00081 }
00082 
00083 ProviderList allProviders()
00084 {
00085     ProviderList pl = providers();
00086     pl += defaultProvider();
00087     return pl;
00088 }
00089 
00090 Provider *providerForName(const QString &name)
00091 {
00092     ProviderList pl = allProviders();
00093     for(int n = 0; n < pl.count(); ++n)
00094     {
00095         if(pl[n]->name() == name)
00096             return pl[n];
00097     }
00098     return 0;
00099 }
00100 
00101 bool use_asker_fallback(ConvertResult r)
00102 {
00103     // FIXME: we should only do this if we get ErrorPassphrase?
00104     //if(r == ErrorPassphrase)
00105     if(r != ConvertGood)
00106         return true;
00107     return false;
00108 }
00109 
00110 class Getter_GroupSet
00111 {
00112 public:
00113     static QList<DLGroupSet> getList(Provider *p)
00114     {
00115         QList<DLGroupSet> list;
00116         const DLGroupContext *c = static_cast<const DLGroupContext *>(getContext("dlgroup", p));
00117         if(!c)
00118             return list;
00119         list = c->supportedGroupSets();
00120         delete c;
00121         return list;
00122     }
00123 };
00124 
00125 class Getter_PBE
00126 {
00127 public:
00128     static QList<PBEAlgorithm> getList(Provider *p)
00129     {
00130         QList<PBEAlgorithm> list;
00131         const PKeyContext *c = static_cast<const PKeyContext *>(getContext("pkey", p));
00132         if(!c)
00133             return list;
00134         list = c->supportedPBEAlgorithms();
00135         delete c;
00136         return list;
00137     }
00138 };
00139 
00140 class Getter_Type
00141 {
00142 public:
00143     static QList<PKey::Type> getList(Provider *p)
00144     {
00145         QList<PKey::Type> list;
00146         const PKeyContext *c = static_cast<const PKeyContext *>(getContext("pkey", p));
00147         if(!c)
00148             return list;
00149         list = c->supportedTypes();
00150         delete c;
00151         return list;
00152     }
00153 };
00154 
00155 class Getter_IOType
00156 {
00157 public:
00158     static QList<PKey::Type> getList(Provider *p)
00159     {
00160         QList<PKey::Type> list;
00161         const PKeyContext *c = static_cast<const PKeyContext *>(getContext("pkey", p));
00162         if(!c)
00163             return list;
00164         list = c->supportedIOTypes();
00165         delete c;
00166         return list;
00167     }
00168 };
00169 
00170 template <typename I>
00171 class Getter_PublicKey
00172 {
00173 public:
00174     // DER
00175     static ConvertResult fromData(PKeyContext *c, const QByteArray &in)
00176     {
00177         return c->publicFromDER(in);
00178     }
00179 
00180     // PEM
00181     static ConvertResult fromData(PKeyContext *c, const QString &in)
00182     {
00183         return c->publicFromPEM(in);
00184     }
00185 
00186     static PublicKey getKey(Provider *p, const I &in, const SecureArray &, ConvertResult *result)
00187     {
00188         PublicKey k;
00189         PKeyContext *c = static_cast<PKeyContext *>(getContext("pkey", p));
00190         if(!c)
00191         {
00192             if(result)
00193                 *result = ErrorDecode;
00194             return k;
00195         }
00196         ConvertResult r = fromData(c, in);
00197         if(result)
00198             *result = r;
00199         if(r == ConvertGood)
00200             k.change(c);
00201         else
00202             delete c;
00203         return k;
00204     }
00205 };
00206 
00207 template <typename I>
00208 class Getter_PrivateKey
00209 {
00210 public:
00211     // DER
00212     static ConvertResult fromData(PKeyContext *c, const SecureArray &in, const SecureArray &passphrase)
00213     {
00214         return c->privateFromDER(in, passphrase);
00215     }
00216 
00217     // PEM
00218     static ConvertResult fromData(PKeyContext *c, const QString &in, const SecureArray &passphrase)
00219     {
00220         return c->privateFromPEM(in, passphrase);
00221     }
00222 
00223     static PrivateKey getKey(Provider *p, const I &in, const SecureArray &passphrase, ConvertResult *result)
00224     {
00225         PrivateKey k;
00226         PKeyContext *c = static_cast<PKeyContext *>(getContext("pkey", p));
00227         if(!c)
00228         {
00229             if(result)
00230                 *result = ErrorDecode;
00231             return k;
00232         }
00233         ConvertResult r = fromData(c, in, passphrase);
00234         if(result)
00235             *result = r;
00236         if(r == ConvertGood)
00237             k.change(c);
00238         else
00239             delete c;
00240         return k;
00241     }
00242 };
00243 
00244 Provider *providerForGroupSet(DLGroupSet set)
00245 {
00246     ProviderList pl = allProviders();
00247     for(int n = 0; n < pl.count(); ++n)
00248     {
00249         if(Getter_GroupSet::getList(pl[n]).contains(set))
00250             return pl[n];
00251     }
00252     return 0;
00253 }
00254 
00255 Provider *providerForPBE(PBEAlgorithm alg, PKey::Type ioType, const PKeyContext *prefer = 0)
00256 {
00257     Provider *preferProvider = 0;
00258     if(prefer)
00259     {
00260         preferProvider = prefer->provider();
00261         if(prefer->supportedPBEAlgorithms().contains(alg) && prefer->supportedIOTypes().contains(ioType))
00262             return preferProvider;
00263     }
00264 
00265     ProviderList pl = allProviders();
00266     for(int n = 0; n < pl.count(); ++n)
00267     {
00268         if(preferProvider && pl[n] == preferProvider)
00269             continue;
00270 
00271         if(Getter_PBE::getList(pl[n]).contains(alg) && Getter_IOType::getList(pl[n]).contains(ioType))
00272             return pl[n];
00273     }
00274     return 0;
00275 }
00276 
00277 Provider *providerForIOType(PKey::Type type, const PKeyContext *prefer = 0)
00278 {
00279     Provider *preferProvider = 0;
00280     if(prefer)
00281     {
00282         preferProvider = prefer->provider();
00283         if(prefer && prefer->supportedIOTypes().contains(type))
00284             return preferProvider;
00285     }
00286 
00287     ProviderList pl = allProviders();
00288     for(int n = 0; n < pl.count(); ++n)
00289     {
00290         if(preferProvider && pl[n] == preferProvider)
00291             continue;
00292 
00293         if(Getter_IOType::getList(pl[n]).contains(type))
00294             return pl[n];
00295     }
00296     return 0;
00297 }
00298 
00299 template <typename T, typename G>
00300 QList<T> getList(const QString &provider)
00301 {
00302     QList<T> list;
00303 
00304     // single
00305     if(!provider.isEmpty())
00306     {
00307         Provider *p = providerForName(provider);
00308         if(p)
00309             list = G::getList(p);
00310     }
00311     // all
00312     else
00313     {
00314         ProviderList pl = allProviders();
00315         for(int n = 0; n < pl.count(); ++n)
00316         {
00317             QList<T> other = G::getList(pl[n]);
00318             for(int k = 0; k < other.count(); ++k)
00319             {
00320                 // only add what we don't have in the list
00321                 if(!list.contains(other[k]))
00322                     list += other[k];
00323             }
00324         }
00325     }
00326 
00327     return list;
00328 }
00329 
00330 template <typename T, typename G, typename I>
00331 T getKey(const QString &provider, const I &in, const SecureArray &passphrase, ConvertResult *result)
00332 {
00333     T k;
00334 
00335     // single
00336     if(!provider.isEmpty())
00337     {
00338         Provider *p = providerForName(provider);
00339         if(!p)
00340             return k;
00341         k = G::getKey(p, in, passphrase, result);
00342     }
00343     // all
00344     else
00345     {
00346         ProviderList pl = allProviders();
00347         for(int n = 0; n < pl.count(); ++n)
00348         {
00349             ConvertResult r;
00350             k = G::getKey(pl[n], in, passphrase, &r);
00351             if(result)
00352                 *result = r;
00353             if(!k.isNull())
00354                 break;
00355             if(r == ErrorPassphrase) // don't loop if we get this
00356                 break;
00357         }
00358     }
00359 
00360     return k;
00361 }
00362 
00363 PBEAlgorithm get_pbe_default()
00364 {
00365     return PBES2_TripleDES_SHA1;
00366 }
00367 
00368 static PrivateKey get_privatekey_der(const SecureArray &der, const QString &fileName, void *ptr, const SecureArray &passphrase, ConvertResult *result, const QString &provider)
00369 {
00370     PrivateKey out;
00371     ConvertResult r;
00372     out = getKey<PrivateKey, Getter_PrivateKey<SecureArray>, SecureArray>(provider, der, passphrase, &r);
00373 
00374     // error converting without passphrase?  maybe a passphrase is needed
00375     if(use_asker_fallback(r) && passphrase.isEmpty())
00376     {
00377         SecureArray pass;
00378         if(ask_passphrase(fileName, ptr, &pass))
00379             out = getKey<PrivateKey, Getter_PrivateKey<SecureArray>, SecureArray>(provider, der, pass, &r);
00380     }
00381     if(result)
00382         *result = r;
00383     return out;
00384 }
00385 
00386 static PrivateKey get_privatekey_pem(const QString &pem, const QString &fileName, void *ptr, const SecureArray &passphrase, ConvertResult *result, const QString &provider)
00387 {
00388     PrivateKey out;
00389     ConvertResult r;
00390     out = getKey<PrivateKey, Getter_PrivateKey<QString>, QString>(provider, pem, passphrase, &r);
00391 
00392     // error converting without passphrase?  maybe a passphrase is needed
00393     if(use_asker_fallback(r) && passphrase.isEmpty())
00394     {
00395         SecureArray pass;
00396         if(ask_passphrase(fileName, ptr, &pass))
00397             out = getKey<PrivateKey, Getter_PrivateKey<QString>, QString>(provider, pem, pass, &r);
00398     }
00399     if(result)
00400         *result = r;
00401     return out;
00402 }
00403 
00404 //----------------------------------------------------------------------------
00405 // Global
00406 //----------------------------------------------------------------------------
00407 
00408 // adapted from Botan
00409 static const unsigned char pkcs_sha1[] =
00410 {
00411     0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02,
00412     0x1A, 0x05, 0x00, 0x04, 0x14
00413 };
00414 
00415 static const unsigned char pkcs_md5[] =
00416 {
00417     0x30, 0x20, 0x30, 0x0C, 0x06, 0x08, 0x2A, 0x86, 0x48, 0x86,
00418     0xF7, 0x0D, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10
00419 };
00420 
00421 static const unsigned char pkcs_md2[] =
00422 {
00423     0x30, 0x20, 0x30, 0x0C, 0x06, 0x08, 0x2A, 0x86, 0x48, 0x86,
00424     0xF7, 0x0D, 0x02, 0x02, 0x05, 0x00, 0x04, 0x10
00425 };
00426 
00427 static const unsigned char pkcs_ripemd160[] =
00428 {
00429     0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x24, 0x03, 0x02,
00430     0x01, 0x05, 0x00, 0x04, 0x14
00431 };
00432 
00433 QByteArray get_hash_id(const QString &name)
00434 {
00435     if(name == "sha1")
00436         return QByteArray::fromRawData((const char *)pkcs_sha1, sizeof(pkcs_sha1));
00437     else if(name == "md5")
00438         return QByteArray::fromRawData((const char *)pkcs_md5, sizeof(pkcs_md5));
00439     else if(name == "md2")
00440         return QByteArray::fromRawData((const char *)pkcs_md2, sizeof(pkcs_md2));
00441     else if(name == "ripemd160")
00442         return QByteArray::fromRawData((const char *)pkcs_ripemd160, sizeof(pkcs_ripemd160));
00443     else
00444         return QByteArray();
00445 }
00446 
00447 QByteArray emsa3Encode(const QString &hashName, const QByteArray &digest, int size)
00448 {
00449     QByteArray hash_id = get_hash_id(hashName);
00450     if(hash_id.isEmpty())
00451         return QByteArray();
00452 
00453     // logic adapted from Botan
00454     int basesize = hash_id.size() + digest.size() + 2;
00455     if(size == -1)
00456         size = basesize + 1; // default to 1-byte pad
00457     int padlen = size - basesize;
00458     if(padlen < 1)
00459         return QByteArray();
00460 
00461     QByteArray out(size, (char)0xff); // pad with 0xff
00462     out[0] = 0x01;
00463     out[padlen + 1] = 0x00;
00464     int at = padlen + 2;
00465     memcpy(out.data() + at, hash_id.data(), hash_id.size());
00466     at += hash_id.size();
00467     memcpy(out.data() + at, digest.data(), digest.size());
00468     return out;
00469 }
00470 
00471 //----------------------------------------------------------------------------
00472 // DLGroup
00473 //----------------------------------------------------------------------------
00474 class DLGroup::Private
00475 {
00476 public:
00477     BigInteger p, q, g;
00478 
00479     Private(const BigInteger &p1, const BigInteger &q1, const BigInteger &g1)
00480     :p(p1), q(q1), g(g1)
00481     {
00482     }
00483 };
00484 
00485 DLGroup::DLGroup()
00486 {
00487     d = 0;
00488 }
00489 
00490 DLGroup::DLGroup(const BigInteger &p, const BigInteger &q, const BigInteger &g)
00491 {
00492     d = new Private(p, q, g);
00493 }
00494 
00495 DLGroup::DLGroup(const BigInteger &p, const BigInteger &g)
00496 {
00497     d = new Private(p, 0, g);
00498 }
00499 
00500 DLGroup::DLGroup(const DLGroup &from)
00501 {
00502     d = 0;
00503     *this = from;
00504 }
00505 
00506 DLGroup::~DLGroup()
00507 {
00508     delete d;
00509 }
00510 
00511 DLGroup & DLGroup::operator=(const DLGroup &from)
00512 {
00513     delete d;
00514     d = 0;
00515 
00516     if(from.d)
00517         d = new Private(*from.d);
00518 
00519     return *this;
00520 }
00521 
00522 QList<DLGroupSet> DLGroup::supportedGroupSets(const QString &provider)
00523 {
00524     return getList<DLGroupSet, Getter_GroupSet>(provider);
00525 }
00526 
00527 bool DLGroup::isNull() const
00528 {
00529     return (d ? false: true);
00530 }
00531 
00532 BigInteger DLGroup::p() const
00533 {
00534     return d->p;
00535 }
00536 
00537 BigInteger DLGroup::q() const
00538 {
00539     return d->q;
00540 }
00541 
00542 BigInteger DLGroup::g() const
00543 {
00544     return d->g;
00545 }
00546 
00547 //----------------------------------------------------------------------------
00548 // PKey
00549 //----------------------------------------------------------------------------
00550 class PKey::Private
00551 {
00552 public:
00553 };
00554 
00555 PKey::PKey()
00556 {
00557     d = new Private;
00558 }
00559 
00560 PKey::PKey(const QString &type, const QString &provider)
00561 :Algorithm(type, provider)
00562 {
00563     d = new Private;
00564 }
00565 
00566 PKey::PKey(const PKey &from)
00567 :Algorithm(from)
00568 {
00569     d = new Private;
00570     *this = from;
00571 }
00572 
00573 PKey::~PKey()
00574 {
00575     delete d;
00576 }
00577 
00578 PKey & PKey::operator=(const PKey &from)
00579 {
00580     Algorithm::operator=(from);
00581     *d = *from.d;
00582     return *this;
00583 }
00584 
00585 void PKey::set(const PKey &k)
00586 {
00587     *this = k;
00588 }
00589 
00590 void PKey::assignToPublic(PKey *dest) const
00591 {
00592     dest->set(*this);
00593 
00594     // converting private to public
00595     if(dest->isPrivate())
00596         static_cast<PKeyContext *>(dest->context())->key()->convertToPublic();
00597 }
00598 
00599 void PKey::assignToPrivate(PKey *dest) const
00600 {
00601     dest->set(*this);
00602 }
00603 
00604 QList<PKey::Type> PKey::supportedTypes(const QString &provider)
00605 {
00606     return getList<Type, Getter_Type>(provider);
00607 }
00608 
00609 QList<PKey::Type> PKey::supportedIOTypes(const QString &provider)
00610 {
00611     return getList<Type, Getter_IOType>(provider);
00612 }
00613 
00614 bool PKey::isNull() const
00615 {
00616     return (!context() ? true : false);
00617 }
00618 
00619 PKey::Type PKey::type() const
00620 {
00621     if(isNull())
00622         return RSA; // some default so we don't explode
00623     return static_cast<const PKeyContext *>(context())->key()->type();
00624 }
00625 
00626 int PKey::bitSize() const
00627 {
00628     return static_cast<const PKeyContext *>(context())->key()->bits();
00629 }
00630 
00631 bool PKey::isRSA() const
00632 {
00633     return (type() == RSA);
00634 }
00635 
00636 bool PKey::isDSA() const
00637 {
00638     return (type() == DSA);
00639 }
00640 
00641 bool PKey::isDH() const
00642 {
00643     return (type() == DH);
00644 }
00645 
00646 bool PKey::isPublic() const
00647 {
00648     if(isNull())
00649         return false;
00650     return !isPrivate();
00651 }
00652 
00653 bool PKey::isPrivate() const
00654 {
00655     if(isNull())
00656         return false;
00657     return static_cast<const PKeyContext *>(context())->key()->isPrivate();
00658 }
00659 
00660 bool PKey::canExport() const
00661 {
00662     return static_cast<const PKeyContext *>(context())->key()->canExport();
00663 }
00664 
00665 bool PKey::canKeyAgree() const
00666 {
00667     return isDH();
00668 }
00669 
00670 PublicKey PKey::toPublicKey() const
00671 {
00672     PublicKey k;
00673     if(!isNull())
00674         assignToPublic(&k);
00675     return k;
00676 }
00677 
00678 PrivateKey PKey::toPrivateKey() const
00679 {
00680     PrivateKey k;
00681     if(!isNull() && isPrivate())
00682         assignToPrivate(&k);
00683     return k;
00684 }
00685 
00686 RSAPublicKey PKey::toRSAPublicKey() const
00687 {
00688     RSAPublicKey k;
00689     if(!isNull() && isRSA())
00690         assignToPublic(&k);
00691     return k;
00692 }
00693 
00694 RSAPrivateKey PKey::toRSAPrivateKey() const
00695 {
00696     RSAPrivateKey k;
00697     if(!isNull() && isRSA() && isPrivate())
00698         assignToPrivate(&k);
00699     return k;
00700 }
00701 
00702 DSAPublicKey PKey::toDSAPublicKey() const
00703 {
00704     DSAPublicKey k;
00705     if(!isNull() && isDSA())
00706         assignToPublic(&k);
00707     return k;
00708 }
00709 
00710 DSAPrivateKey PKey::toDSAPrivateKey() const
00711 {
00712     DSAPrivateKey k;
00713     if(!isNull() && isDSA() && isPrivate())
00714         assignToPrivate(&k);
00715     return k;
00716 }
00717 
00718 DHPublicKey PKey::toDHPublicKey() const
00719 {
00720     DHPublicKey k;
00721     if(!isNull() && isDH())
00722         assignToPublic(&k);
00723     return k;
00724 }
00725 
00726 DHPrivateKey PKey::toDHPrivateKey() const
00727 {
00728     DHPrivateKey k;
00729     if(!isNull() && isDH() && isPrivate())
00730         assignToPrivate(&k);
00731     return k;
00732 }
00733 
00734 bool PKey::operator==(const PKey &a) const
00735 {
00736     if(isNull() || a.isNull() || type() != a.type())
00737         return false;
00738 
00739     if(a.isPrivate())
00740         return (toPrivateKey().toDER() == a.toPrivateKey().toDER());
00741     else
00742         return (toPublicKey().toDER() == a.toPublicKey().toDER());
00743 }
00744 
00745 bool PKey::operator!=(const PKey &a) const
00746 {
00747     return !(*this == a);
00748 }
00749 
00750 //----------------------------------------------------------------------------
00751 // PublicKey
00752 //----------------------------------------------------------------------------
00753 PublicKey::PublicKey()
00754 {
00755 }
00756 
00757 PublicKey::PublicKey(const QString &type, const QString &provider)
00758 :PKey(type, provider)
00759 {
00760 }
00761 
00762 PublicKey::PublicKey(const PrivateKey &k)
00763 {
00764     set(k.toPublicKey());
00765 }
00766 
00767 PublicKey::PublicKey(const QString &fileName)
00768 {
00769     *this = fromPEMFile(fileName, 0, QString());
00770 }
00771 
00772 PublicKey::PublicKey(const PublicKey &from)
00773 :PKey(from)
00774 {
00775 }
00776 
00777 PublicKey::~PublicKey()
00778 {
00779 }
00780 
00781 PublicKey & PublicKey::operator=(const PublicKey &from)
00782 {
00783     PKey::operator=(from);
00784     return *this;
00785 }
00786 
00787 RSAPublicKey PublicKey::toRSA() const
00788 {
00789     return toRSAPublicKey();
00790 }
00791 
00792 DSAPublicKey PublicKey::toDSA() const
00793 {
00794     return toDSAPublicKey();
00795 }
00796 
00797 DHPublicKey PublicKey::toDH() const
00798 {
00799     return toDHPublicKey();
00800 }
00801 
00802 bool PublicKey::canEncrypt() const
00803 {
00804     return isRSA();
00805 }
00806 
00807 bool PublicKey::canVerify() const
00808 {
00809     return (isRSA() || isDSA());
00810 }
00811 
00812 int PublicKey::maximumEncryptSize(EncryptionAlgorithm alg) const
00813 {
00814     return static_cast<const PKeyContext *>(context())->key()->maximumEncryptSize(alg);
00815 }
00816 
00817 SecureArray PublicKey::encrypt(const SecureArray &a, EncryptionAlgorithm alg)
00818 {
00819     return static_cast<PKeyContext *>(context())->key()->encrypt(a, alg);
00820 }
00821 
00822 void PublicKey::startVerify(SignatureAlgorithm alg, SignatureFormat format)
00823 {
00824     if(isDSA() && format == DefaultFormat)
00825         format = IEEE_1363;
00826     static_cast<PKeyContext *>(context())->key()->startVerify(alg, format);
00827 }
00828 
00829 void PublicKey::update(const MemoryRegion &a)
00830 {
00831     static_cast<PKeyContext *>(context())->key()->update(a);
00832 }
00833 
00834 bool PublicKey::validSignature(const QByteArray &sig)
00835 {
00836     return static_cast<PKeyContext *>(context())->key()->endVerify(sig);
00837 }
00838 
00839 bool PublicKey::verifyMessage(const MemoryRegion &a, const QByteArray &sig, SignatureAlgorithm alg, SignatureFormat format)
00840 {
00841     startVerify(alg, format);
00842     update(a);
00843     return validSignature(sig);
00844 }
00845 
00846 QByteArray PublicKey::toDER() const
00847 {
00848     QByteArray out;
00849     const PKeyContext *cur = static_cast<const PKeyContext *>(context());
00850     Provider *p = providerForIOType(type(), cur);
00851     if(!p)
00852         return out;
00853     if(cur->provider() == p)
00854     {
00855         out = cur->publicToDER();
00856     }
00857     else
00858     {
00859         PKeyContext *pk = static_cast<PKeyContext *>(getContext("pkey", p));
00860         if(pk->importKey(cur->key()))
00861             out = pk->publicToDER();
00862         delete pk;
00863     }
00864     return out;
00865 }
00866 
00867 QString PublicKey::toPEM() const
00868 {
00869     QString out;
00870     const PKeyContext *cur = static_cast<const PKeyContext *>(context());
00871     Provider *p = providerForIOType(type(), cur);
00872     if(!p)
00873         return out;
00874     if(cur->provider() == p)
00875     {
00876         out = cur->publicToPEM();
00877     }
00878     else
00879     {
00880         PKeyContext *pk = static_cast<PKeyContext *>(getContext("pkey", p));
00881         if(pk->importKey(cur->key()))
00882             out = pk->publicToPEM();
00883         delete pk;
00884     }
00885     return out;
00886 }
00887 
00888 bool PublicKey::toPEMFile(const QString &fileName) const
00889 {
00890     return stringToFile(fileName, toPEM());
00891 }
00892 
00893 PublicKey PublicKey::fromDER(const QByteArray &a, ConvertResult *result, const QString &provider)
00894 {
00895     return getKey<PublicKey, Getter_PublicKey<QByteArray>, QByteArray>(provider, a, SecureArray(), result);
00896 }
00897 
00898 PublicKey PublicKey::fromPEM(const QString &s, ConvertResult *result, const QString &provider)
00899 {
00900     return getKey<PublicKey, Getter_PublicKey<QString>, QString>(provider, s, SecureArray(), result);
00901 }
00902 
00903 PublicKey PublicKey::fromPEMFile(const QString &fileName, ConvertResult *result, const QString &provider)
00904 {
00905     QString pem;
00906     if(!stringFromFile(fileName, &pem))
00907     {
00908         if(result)
00909             *result = ErrorFile;
00910         return PublicKey();
00911     }
00912     return fromPEM(pem, result, provider);
00913 }
00914 
00915 //----------------------------------------------------------------------------
00916 // PrivateKey
00917 //----------------------------------------------------------------------------
00918 PrivateKey::PrivateKey()
00919 {
00920 }
00921 
00922 PrivateKey::PrivateKey(const QString &type, const QString &provider)
00923 :PKey(type, provider)
00924 {
00925 }
00926 
00927 PrivateKey::PrivateKey(const QString &fileName, const SecureArray &passphrase)
00928 {
00929     *this = fromPEMFile(fileName, passphrase, 0, QString());
00930 }
00931 
00932 PrivateKey::PrivateKey(const PrivateKey &from)
00933 :PKey(from)
00934 {
00935 }
00936 
00937 PrivateKey::~PrivateKey()
00938 {
00939 }
00940 
00941 PrivateKey & PrivateKey::operator=(const PrivateKey &from)
00942 {
00943     PKey::operator=(from);
00944     return *this;
00945 }
00946 
00947 RSAPrivateKey PrivateKey::toRSA() const
00948 {
00949     return toRSAPrivateKey();
00950 }
00951 
00952 DSAPrivateKey PrivateKey::toDSA() const
00953 {
00954     return toDSAPrivateKey();
00955 }
00956 
00957 DHPrivateKey PrivateKey::toDH() const
00958 {
00959     return toDHPrivateKey();
00960 }
00961 
00962 bool PrivateKey::canDecrypt() const
00963 {
00964     return isRSA();
00965 }
00966 
00967 bool PrivateKey::canSign() const
00968 {
00969     return (isRSA() || isDSA());
00970 }
00971 
00972 bool PrivateKey::decrypt(const SecureArray &in, SecureArray *out, EncryptionAlgorithm alg)
00973 {
00974     return static_cast<PKeyContext *>(context())->key()->decrypt(in, out, alg);
00975 }
00976 
00977 void PrivateKey::startSign(SignatureAlgorithm alg, SignatureFormat format)
00978 {
00979     if(isDSA() && format == DefaultFormat)
00980         format = IEEE_1363;
00981     static_cast<PKeyContext *>(context())->key()->startSign(alg, format);
00982 }
00983 
00984 void PrivateKey::update(const MemoryRegion &a)
00985 {
00986     static_cast<PKeyContext *>(context())->key()->update(a);
00987 }
00988 
00989 QByteArray PrivateKey::signature()
00990 {
00991     return static_cast<PKeyContext *>(context())->key()->endSign();
00992 }
00993 
00994 QByteArray PrivateKey::signMessage(const MemoryRegion &a, SignatureAlgorithm alg, SignatureFormat format)
00995 {
00996     startSign(alg, format);
00997     update(a);
00998     return signature();
00999 }
01000 
01001 SymmetricKey PrivateKey::deriveKey(const PublicKey &theirs)
01002 {
01003     const PKeyContext *theirContext = static_cast<const PKeyContext *>(theirs.context());
01004     return static_cast<PKeyContext *>(context())->key()->deriveKey(*(theirContext->key()));
01005 }
01006 
01007 QList<PBEAlgorithm> PrivateKey::supportedPBEAlgorithms(const QString &provider)
01008 {
01009     return getList<PBEAlgorithm, Getter_PBE>(provider);
01010 }
01011 
01012 SecureArray PrivateKey::toDER(const SecureArray &passphrase, PBEAlgorithm pbe) const
01013 {
01014     SecureArray out;
01015     if(pbe == PBEDefault)
01016         pbe = get_pbe_default();
01017     const PKeyContext *cur = static_cast<const PKeyContext *>(context());
01018     Provider *p = providerForPBE(pbe, type(), cur);
01019     if(!p)
01020         return out;
01021     if(cur->provider() == p)
01022     {
01023         out = cur->privateToDER(passphrase, pbe);
01024     }
01025     else
01026     {
01027         PKeyContext *pk = static_cast<PKeyContext *>(getContext("pkey", p));
01028         if(pk->importKey(cur->key()))
01029             out = pk->privateToDER(passphrase, pbe);
01030         delete pk;
01031     }
01032     return out;
01033 }
01034 
01035 QString PrivateKey::toPEM(const SecureArray &passphrase, PBEAlgorithm pbe) const
01036 {
01037     QString out;
01038     if(pbe == PBEDefault)
01039         pbe = get_pbe_default();
01040     const PKeyContext *cur = static_cast<const PKeyContext *>(context());
01041     Provider *p = providerForPBE(pbe, type(), cur);
01042     if(!p)
01043         return out;
01044     if(cur->provider() == p)
01045     {
01046         out = cur->privateToPEM(passphrase, pbe);
01047     }
01048     else
01049     {
01050         PKeyContext *pk = static_cast<PKeyContext *>(getContext("pkey", p));
01051         if(pk->importKey(cur->key()))
01052             out = pk->privateToPEM(passphrase, pbe);
01053         delete pk;
01054     }
01055     return out;
01056 }
01057 
01058 bool PrivateKey::toPEMFile(const QString &fileName, const SecureArray &passphrase, PBEAlgorithm pbe) const
01059 {
01060     return stringToFile(fileName, toPEM(passphrase, pbe));
01061 }
01062 
01063 PrivateKey PrivateKey::fromDER(const SecureArray &a, const SecureArray &passphrase, ConvertResult *result, const QString &provider)
01064 {
01065     return get_privatekey_der(a, QString(), (void *)&a, passphrase, result, provider);
01066 }
01067 
01068 PrivateKey PrivateKey::fromPEM(const QString &s, const SecureArray &passphrase, ConvertResult *result, const QString &provider)
01069 {
01070     return get_privatekey_pem(s, QString(), (void *)&s, passphrase, result, provider);
01071 }
01072 
01073 PrivateKey PrivateKey::fromPEMFile(const QString &fileName, const SecureArray &passphrase, ConvertResult *result, const QString &provider)
01074 {
01075     QString pem;
01076     if(!stringFromFile(fileName, &pem))
01077     {
01078         if(result)
01079             *result = ErrorFile;
01080         return PrivateKey();
01081     }
01082     return get_privatekey_pem(pem, fileName, 0, passphrase, result, provider);
01083 }
01084 
01085 //----------------------------------------------------------------------------
01086 // KeyGenerator
01087 //----------------------------------------------------------------------------
01088 class KeyGenerator::Private : public QObject
01089 {
01090     Q_OBJECT
01091 public:
01092     KeyGenerator *parent;
01093     bool blocking, wasBlocking;
01094     PrivateKey key;
01095     DLGroup group;
01096 
01097     PKeyBase *k;
01098     PKeyContext *dest;
01099     DLGroupContext *dc;
01100 
01101     Private(KeyGenerator *_parent) : QObject(_parent), parent(_parent)
01102     {
01103         k = 0;
01104         dest = 0;
01105         dc = 0;
01106     }
01107 
01108     ~Private()
01109     {
01110         delete k;
01111         delete dest;
01112         delete dc;
01113     }
01114 
01115 public slots:
01116     void done()
01117     {
01118         if(!k->isNull())
01119         {
01120             if(!wasBlocking)
01121             {
01122                 k->setParent(0);
01123                 k->moveToThread(0);
01124             }
01125             dest->setKey(k);
01126             k = 0;
01127 
01128             key.change(dest);
01129             dest = 0;
01130         }
01131         else
01132         {
01133             delete k;
01134             k = 0;
01135             delete dest;
01136             dest = 0;
01137         }
01138 
01139         if(!wasBlocking)
01140             emit parent->finished();
01141     }
01142 
01143     void done_group()
01144     {
01145         if(!dc->isNull())
01146         {
01147             BigInteger p, q, g;
01148             dc->getResult(&p, &q, &g);
01149             group = DLGroup(p, q, g);
01150         }
01151         delete dc;
01152         dc = 0;
01153 
01154         if(!wasBlocking)
01155             emit parent->finished();
01156     }
01157 };
01158 
01159 KeyGenerator::KeyGenerator(QObject *parent)
01160 :QObject(parent)
01161 {
01162     d = new Private(this);
01163     d->blocking = true;
01164 }
01165 
01166 KeyGenerator::~KeyGenerator()
01167 {
01168     delete d;
01169 }
01170 
01171 bool KeyGenerator::blockingEnabled() const
01172 {
01173     return d->blocking;
01174 }
01175 
01176 void KeyGenerator::setBlockingEnabled(bool b)
01177 {
01178     d->blocking = b;
01179 }
01180 
01181 bool KeyGenerator::isBusy() const
01182 {
01183     return (d->k ? true: false);
01184 }
01185 
01186 PrivateKey KeyGenerator::createRSA(int bits, int exp, const QString &provider)
01187 {
01188     if(isBusy())
01189         return PrivateKey();
01190 
01191     d->key = PrivateKey();
01192     d->wasBlocking = d->blocking;
01193     d->k = static_cast<RSAContext *>(getContext("rsa", provider));
01194     d->dest = static_cast<PKeyContext *>(getContext("pkey", d->k->provider()));
01195 
01196     if(!d->blocking)
01197     {
01198         d->k->moveToThread(thread());
01199         d->k->setParent(d);
01200         connect(d->k, SIGNAL(finished()), d, SLOT(done()));
01201         static_cast<RSAContext *>(d->k)->createPrivate(bits, exp, false);
01202     }
01203     else
01204     {
01205         static_cast<RSAContext *>(d->k)->createPrivate(bits, exp, true);
01206         d->done();
01207     }
01208 
01209     return d->key;
01210 }
01211 
01212 PrivateKey KeyGenerator::createDSA(const DLGroup &domain, const QString &provider)
01213 {
01214     if(isBusy())
01215         return PrivateKey();
01216 
01217     d->key = PrivateKey();
01218     d->wasBlocking = d->blocking;
01219     d->k = static_cast<DSAContext *>(getContext("dsa", provider));
01220     d->dest = static_cast<PKeyContext *>(getContext("pkey", d->k->provider()));
01221 
01222     if(!d->blocking)
01223     {
01224         d->k->moveToThread(thread());
01225         d->k->setParent(d);
01226         connect(d->k, SIGNAL(finished()), d, SLOT(done()));
01227         static_cast<DSAContext *>(d->k)->createPrivate(domain, false);
01228     }
01229     else
01230     {
01231         static_cast<DSAContext *>(d->k)->createPrivate(domain, true);
01232         d->done();
01233     }
01234 
01235     return d->key;
01236 }
01237 
01238 PrivateKey KeyGenerator::createDH(const DLGroup &domain, const QString &provider)
01239 {
01240     if(isBusy())
01241         return PrivateKey();
01242 
01243     d->key = PrivateKey();
01244     d->wasBlocking = d->blocking;
01245     d->k = static_cast<DHContext *>(getContext("dh", provider));
01246     d->dest = static_cast<PKeyContext *>(getContext("pkey", d->k->provider()));
01247 
01248     if(!d->blocking)
01249     {
01250         d->k->moveToThread(thread());
01251         d->k->setParent(d);
01252         connect(d->k, SIGNAL(finished()), d, SLOT(done()));
01253         static_cast<DHContext *>(d->k)->createPrivate(domain, false);
01254     }
01255     else
01256     {
01257         static_cast<DHContext *>(d->k)->createPrivate(domain, true);
01258         d->done();
01259     }
01260 
01261     return d->key;
01262 }
01263 
01264 PrivateKey KeyGenerator::key() const
01265 {
01266     return d->key;
01267 }
01268 
01269 DLGroup KeyGenerator::createDLGroup(QCA::DLGroupSet set, const QString &provider)
01270 {
01271     if(isBusy())
01272         return DLGroup();
01273 
01274     Provider *p;
01275     if(!provider.isEmpty())
01276         p = providerForName(provider);
01277     else
01278         p = providerForGroupSet(set);
01279 
01280     d->group = DLGroup();
01281     d->wasBlocking = d->blocking;
01282     d->dc = static_cast<DLGroupContext *>(getContext("dlgroup", p));
01283 
01284     if(!d->blocking)
01285     {
01286         connect(d->dc, SIGNAL(finished()), d, SLOT(done_group()));
01287         d->dc->fetchGroup(set, false);
01288     }
01289     else
01290     {
01291         d->dc->fetchGroup(set, true);
01292         d->done_group();
01293     }
01294 
01295     return d->group;
01296 }
01297 
01298 DLGroup KeyGenerator::dlGroup() const
01299 {
01300     return d->group;
01301 }
01302 
01303 //----------------------------------------------------------------------------
01304 // RSAPublicKey
01305 //----------------------------------------------------------------------------
01306 RSAPublicKey::RSAPublicKey()
01307 {
01308 }
01309 
01310 RSAPublicKey::RSAPublicKey(const BigInteger &n, const BigInteger &e, const QString &provider)
01311 {
01312     RSAContext *k = static_cast<RSAContext *>(getContext("rsa", provider));
01313     k->createPublic(n, e);
01314     PKeyContext *c = static_cast<PKeyContext *>(getContext("pkey", k->provider()));
01315     c->setKey(k);
01316     change(c);
01317 }
01318 
01319 RSAPublicKey::RSAPublicKey(const RSAPrivateKey &k)
01320 :PublicKey(k)
01321 {
01322 }
01323 
01324 BigInteger RSAPublicKey::n() const
01325 {
01326     return static_cast<const RSAContext *>(static_cast<const PKeyContext *>(context())->key())->n();
01327 }
01328 
01329 BigInteger RSAPublicKey::e() const
01330 {
01331     return static_cast<const RSAContext *>(static_cast<const PKeyContext *>(context())->key())->e();
01332 }
01333 
01334 //----------------------------------------------------------------------------
01335 // RSAPrivateKey
01336 //----------------------------------------------------------------------------
01337 RSAPrivateKey::RSAPrivateKey()
01338 {
01339 }
01340 
01341 RSAPrivateKey::RSAPrivateKey(const BigInteger &n, const BigInteger &e, const BigInteger &p, const BigInteger &q, const BigInteger &d, const QString &provider)
01342 {
01343     RSAContext *k = static_cast<RSAContext *>(getContext("rsa", provider));
01344     k->createPrivate(n, e, p, q, d);
01345     PKeyContext *c = static_cast<PKeyContext *>(getContext("pkey", k->provider()));
01346     c->setKey(k);
01347     change(c);
01348 }
01349 
01350 BigInteger RSAPrivateKey::n() const
01351 {
01352     return static_cast<const RSAContext *>(static_cast<const PKeyContext *>(context())->key())->n();
01353 }
01354 
01355 BigInteger RSAPrivateKey::e() const
01356 {
01357     return static_cast<const RSAContext *>(static_cast<const PKeyContext *>(context())->key())->e();
01358 }
01359 
01360 BigInteger RSAPrivateKey::p() const
01361 {
01362     return static_cast<const RSAContext *>(static_cast<const PKeyContext *>(context())->key())->p();
01363 }
01364 
01365 BigInteger RSAPrivateKey::q() const
01366 {
01367     return static_cast<const RSAContext *>(static_cast<const PKeyContext *>(context())->key())->q();
01368 }
01369 
01370 BigInteger RSAPrivateKey::d() const
01371 {
01372     return static_cast<const RSAContext *>(static_cast<const PKeyContext *>(context())->key())->d();
01373 }
01374 
01375 //----------------------------------------------------------------------------
01376 // DSAPublicKey
01377 //----------------------------------------------------------------------------
01378 DSAPublicKey::DSAPublicKey()
01379 {
01380 }
01381 
01382 DSAPublicKey::DSAPublicKey(const DLGroup &domain, const BigInteger &y, const QString &provider)
01383 {
01384     DSAContext *k = static_cast<DSAContext *>(getContext("dsa", provider));
01385     k->createPublic(domain, y);
01386     PKeyContext *c = static_cast<PKeyContext *>(getContext("pkey", k->provider()));
01387     c->setKey(k);
01388     change(c);
01389 }
01390 
01391 DSAPublicKey::DSAPublicKey(const DSAPrivateKey &k)
01392 :PublicKey(k)
01393 {
01394 }
01395 
01396 DLGroup DSAPublicKey::domain() const
01397 {
01398     return static_cast<const DSAContext *>(static_cast<const PKeyContext *>(context())->key())->domain();
01399 }
01400 
01401 BigInteger DSAPublicKey::y() const
01402 {
01403     return static_cast<const DSAContext *>(static_cast<const PKeyContext *>(context())->key())->y();
01404 }
01405 
01406 //----------------------------------------------------------------------------
01407 // DSAPrivateKey
01408 //----------------------------------------------------------------------------
01409 DSAPrivateKey::DSAPrivateKey()
01410 {
01411 }
01412 
01413 DSAPrivateKey::DSAPrivateKey(const DLGroup &domain, const BigInteger &y, const BigInteger &x, const QString &provider)
01414 {
01415     DSAContext *k = static_cast<DSAContext *>(getContext("dsa", provider));
01416     k->createPrivate(domain, y, x);
01417     PKeyContext *c = static_cast<PKeyContext *>(getContext("pkey", k->provider()));
01418     c->setKey(k);
01419     change(c);
01420 }
01421 
01422 DLGroup DSAPrivateKey::domain() const
01423 {
01424     return static_cast<const DSAContext *>(static_cast<const PKeyContext *>(context())->key())->domain();
01425 }
01426 
01427 BigInteger DSAPrivateKey::y() const
01428 {
01429     return static_cast<const DSAContext *>(static_cast<const PKeyContext *>(context())->key())->y();
01430 }
01431 
01432 BigInteger DSAPrivateKey::x() const
01433 {
01434     return static_cast<const DSAContext *>(static_cast<const PKeyContext *>(context())->key())->x();
01435 }
01436 
01437 //----------------------------------------------------------------------------
01438 // DHPublicKey
01439 //----------------------------------------------------------------------------
01440 DHPublicKey::DHPublicKey()
01441 {
01442 }
01443 
01444 DHPublicKey::DHPublicKey(const DLGroup &domain, const BigInteger &y, const QString &provider)
01445 {
01446     DHContext *k = static_cast<DHContext *>(getContext("dh", provider));
01447     k->createPublic(domain, y);
01448     PKeyContext *c = static_cast<PKeyContext *>(getContext("pkey", k->provider()));
01449     c->setKey(k);
01450     change(c);
01451 }
01452 
01453 DHPublicKey::DHPublicKey(const DHPrivateKey &k)
01454 :PublicKey(k)
01455 {
01456 }
01457 
01458 DLGroup DHPublicKey::domain() const
01459 {
01460     return static_cast<const DHContext *>(static_cast<const PKeyContext *>(context())->key())->domain();
01461 }
01462 
01463 BigInteger DHPublicKey::y() const
01464 {
01465     return static_cast<const DHContext *>(static_cast<const PKeyContext *>(context())->key())->y();
01466 }
01467 
01468 //----------------------------------------------------------------------------
01469 // DHPrivateKey
01470 //----------------------------------------------------------------------------
01471 DHPrivateKey::DHPrivateKey()
01472 {
01473 }
01474 
01475 DHPrivateKey::DHPrivateKey(const DLGroup &domain, const BigInteger &y, const BigInteger &x, const QString &provider)
01476 {
01477     DHContext *k = static_cast<DHContext *>(getContext("dh", provider));
01478     k->createPrivate(domain, y, x);
01479     PKeyContext *c = static_cast<PKeyContext *>(getContext("pkey", k->provider()));
01480     c->setKey(k);
01481     change(c);
01482 }
01483 
01484 DLGroup DHPrivateKey::domain() const
01485 {
01486     return static_cast<const DHContext *>(static_cast<const PKeyContext *>(context())->key())->domain();
01487 }
01488 
01489 BigInteger DHPrivateKey::y() const
01490 {
01491     return static_cast<const DHContext *>(static_cast<const PKeyContext *>(context())->key())->y();
01492 }
01493 
01494 BigInteger DHPrivateKey::x() const
01495 {
01496     return static_cast<const DHContext *>(static_cast<const PKeyContext *>(context())->key())->x();
01497 }
01498 
01499 }
01500 
01501 #include "qca_publickey.moc"

qca

Skip menu "qca"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

KDE Support

Skip menu "KDE Support"
  • akonadi
  • Decibel
  • grantlee
  • kdewin
  • phonon
  •     Backend
  • polkit-qt
  • qca
  • qimageblitz
  • soprano
  • strigi
  •     searchclient
  •     streamanalyzer
  •     streams
Generated for KDE Support by doxygen 1.5.9-20090814
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal