File indexing completed on 2024-04-21 04:43:52

0001 /*
0002  * Copyright (C) 2003-2007  Justin Karneges <justin@affinix.com>
0003  * Copyright (C) 2004,2005  Brad Hards <bradh@frogmouth.net>
0004  *
0005  * This library is free software; you can redistribute it and/or
0006  * modify it under the terms of the GNU Lesser General Public
0007  * License as published by the Free Software Foundation; either
0008  * version 2.1 of the License, or (at your option) any later version.
0009  *
0010  * This library is distributed in the hope that it will be useful,
0011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0013  * Lesser General Public License for more details.
0014  *
0015  * You should have received a copy of the GNU Lesser General Public
0016  * License along with this library; if not, write to the Free Software
0017  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
0018  * 02110-1301  USA
0019  *
0020  */
0021 
0022 #include "qca_publickey.h"
0023 
0024 #include "qcaprovider.h"
0025 
0026 #include <QFile>
0027 #include <QTextStream>
0028 
0029 namespace QCA {
0030 
0031 Provider::Context *getContext(const QString &type, const QString &provider);
0032 Provider::Context *getContext(const QString &type, Provider *p);
0033 
0034 bool stringToFile(const QString &fileName, const QString &content)
0035 {
0036     QFile f(fileName);
0037     if (!f.open(QFile::WriteOnly))
0038         return false;
0039     QTextStream ts(&f);
0040     ts << content;
0041     return true;
0042 }
0043 
0044 bool stringFromFile(const QString &fileName, QString *s)
0045 {
0046     QFile f(fileName);
0047     if (!f.open(QFile::ReadOnly))
0048         return false;
0049     QTextStream ts(&f);
0050     *s = ts.readAll();
0051     return true;
0052 }
0053 
0054 bool arrayToFile(const QString &fileName, const QByteArray &content)
0055 {
0056     QFile f(fileName);
0057     if (!f.open(QFile::WriteOnly))
0058         return false;
0059     f.write(content.data(), content.size());
0060     return true;
0061 }
0062 
0063 bool arrayFromFile(const QString &fileName, QByteArray *a)
0064 {
0065     QFile f(fileName);
0066     if (!f.open(QFile::ReadOnly))
0067         return false;
0068     *a = f.readAll();
0069     return true;
0070 }
0071 
0072 bool ask_passphrase(const QString &fname, void *ptr, SecureArray *answer)
0073 {
0074     PasswordAsker asker;
0075     asker.ask(Event::StylePassphrase, fname, ptr);
0076     asker.waitForResponse();
0077     if (!asker.accepted())
0078         return false;
0079     *answer = asker.password();
0080     return true;
0081 }
0082 
0083 ProviderList allProviders()
0084 {
0085     ProviderList pl = providers();
0086     pl += defaultProvider();
0087     return pl;
0088 }
0089 
0090 Provider *providerForName(const QString &name)
0091 {
0092     ProviderList pl = allProviders();
0093     for (int n = 0; n < pl.count(); ++n) {
0094         if (pl[n]->name() == name)
0095             return pl[n];
0096     }
0097     return nullptr;
0098 }
0099 
0100 bool use_asker_fallback(ConvertResult r)
0101 {
0102     // FIXME: we should only do this if we get ErrorPassphrase?
0103     // if(r == ErrorPassphrase)
0104     if (r != ConvertGood)
0105         return true;
0106     return false;
0107 }
0108 
0109 class Getter_GroupSet
0110 {
0111 public:
0112     static QList<DLGroupSet> getList(Provider *p)
0113     {
0114         QList<DLGroupSet>     list;
0115         const DLGroupContext *c = static_cast<const DLGroupContext *>(getContext(QStringLiteral("dlgroup"), p));
0116         if (!c)
0117             return list;
0118         list = c->supportedGroupSets();
0119         delete c;
0120         return list;
0121     }
0122 };
0123 
0124 class Getter_PBE
0125 {
0126 public:
0127     static QList<PBEAlgorithm> getList(Provider *p)
0128     {
0129         QList<PBEAlgorithm> list;
0130         const PKeyContext  *c = static_cast<const PKeyContext *>(getContext(QStringLiteral("pkey"), p));
0131         if (!c)
0132             return list;
0133         list = c->supportedPBEAlgorithms();
0134         delete c;
0135         return list;
0136     }
0137 };
0138 
0139 class Getter_Type
0140 {
0141 public:
0142     static QList<PKey::Type> getList(Provider *p)
0143     {
0144         QList<PKey::Type>  list;
0145         const PKeyContext *c = static_cast<const PKeyContext *>(getContext(QStringLiteral("pkey"), p));
0146         if (!c)
0147             return list;
0148         list = c->supportedTypes();
0149         delete c;
0150         return list;
0151     }
0152 };
0153 
0154 class Getter_IOType
0155 {
0156 public:
0157     static QList<PKey::Type> getList(Provider *p)
0158     {
0159         QList<PKey::Type>  list;
0160         const PKeyContext *c = static_cast<const PKeyContext *>(getContext(QStringLiteral("pkey"), p));
0161         if (!c)
0162             return list;
0163         list = c->supportedIOTypes();
0164         delete c;
0165         return list;
0166     }
0167 };
0168 
0169 template<typename I> class Getter_PublicKey
0170 {
0171 public:
0172     // DER
0173     static ConvertResult fromData(PKeyContext *c, const QByteArray &in)
0174     {
0175         return c->publicFromDER(in);
0176     }
0177 
0178     // PEM
0179     static ConvertResult fromData(PKeyContext *c, const QString &in)
0180     {
0181         return c->publicFromPEM(in);
0182     }
0183 
0184     static PublicKey getKey(Provider *p, const I &in, const SecureArray &, ConvertResult *result)
0185     {
0186         PublicKey    k;
0187         PKeyContext *c = static_cast<PKeyContext *>(getContext(QStringLiteral("pkey"), p));
0188         if (!c) {
0189             if (result)
0190                 *result = ErrorDecode;
0191             return k;
0192         }
0193         ConvertResult r = fromData(c, in);
0194         if (result)
0195             *result = r;
0196         if (r == ConvertGood)
0197             k.change(c);
0198         else
0199             delete c;
0200         return k;
0201     }
0202 };
0203 
0204 template<typename I> class Getter_PrivateKey
0205 {
0206 public:
0207     // DER
0208     static ConvertResult fromData(PKeyContext *c, const SecureArray &in, const SecureArray &passphrase)
0209     {
0210         return c->privateFromDER(in, passphrase);
0211     }
0212 
0213     // PEM
0214     static ConvertResult fromData(PKeyContext *c, const QString &in, const SecureArray &passphrase)
0215     {
0216         return c->privateFromPEM(in, passphrase);
0217     }
0218 
0219     static PrivateKey getKey(Provider *p, const I &in, const SecureArray &passphrase, ConvertResult *result)
0220     {
0221         PrivateKey   k;
0222         PKeyContext *c = static_cast<PKeyContext *>(getContext(QStringLiteral("pkey"), p));
0223         if (!c) {
0224             if (result)
0225                 *result = ErrorDecode;
0226             return k;
0227         }
0228         ConvertResult r = fromData(c, in, passphrase);
0229         if (result)
0230             *result = r;
0231         if (r == ConvertGood)
0232             k.change(c);
0233         else
0234             delete c;
0235         return k;
0236     }
0237 };
0238 
0239 Provider *providerForGroupSet(DLGroupSet set)
0240 {
0241     ProviderList pl = allProviders();
0242     for (int n = 0; n < pl.count(); ++n) {
0243         if (Getter_GroupSet::getList(pl[n]).contains(set))
0244             return pl[n];
0245     }
0246     return nullptr;
0247 }
0248 
0249 Provider *providerForPBE(PBEAlgorithm alg, PKey::Type ioType, const PKeyContext *prefer = nullptr)
0250 {
0251     Provider *preferProvider = nullptr;
0252     if (prefer) {
0253         preferProvider = prefer->provider();
0254         if (prefer->supportedPBEAlgorithms().contains(alg) && prefer->supportedIOTypes().contains(ioType))
0255             return preferProvider;
0256     }
0257 
0258     ProviderList pl = allProviders();
0259     for (int n = 0; n < pl.count(); ++n) {
0260         if (preferProvider && pl[n] == preferProvider)
0261             continue;
0262 
0263         if (Getter_PBE::getList(pl[n]).contains(alg) && Getter_IOType::getList(pl[n]).contains(ioType))
0264             return pl[n];
0265     }
0266     return nullptr;
0267 }
0268 
0269 Provider *providerForIOType(PKey::Type type, const PKeyContext *prefer = nullptr)
0270 {
0271     Provider *preferProvider = nullptr;
0272     if (prefer) {
0273         preferProvider = prefer->provider();
0274         if (prefer && prefer->supportedIOTypes().contains(type))
0275             return preferProvider;
0276     }
0277 
0278     ProviderList pl = allProviders();
0279     for (int n = 0; n < pl.count(); ++n) {
0280         if (preferProvider && pl[n] == preferProvider)
0281             continue;
0282 
0283         if (Getter_IOType::getList(pl[n]).contains(type))
0284             return pl[n];
0285     }
0286     return nullptr;
0287 }
0288 
0289 template<typename T, typename G> QList<T> getList(const QString &provider)
0290 {
0291     QList<T> list;
0292 
0293     // single
0294     if (!provider.isEmpty()) {
0295         Provider *p = providerForName(provider);
0296         if (p)
0297             list = G::getList(p);
0298     }
0299     // all
0300     else {
0301         ProviderList pl = allProviders();
0302         for (int n = 0; n < pl.count(); ++n) {
0303             const QList<T> other = G::getList(pl[n]);
0304             for (int k = 0; k < other.count(); ++k) {
0305                 // only add what we don't have in the list
0306                 if (!list.contains(other[k]))
0307                     list += other[k];
0308             }
0309         }
0310     }
0311 
0312     return list;
0313 }
0314 
0315 template<typename T, typename G, typename I>
0316 T getKey(const QString &provider, const I &in, const SecureArray &passphrase, ConvertResult *result)
0317 {
0318     T k;
0319 
0320     // single
0321     if (!provider.isEmpty()) {
0322         Provider *p = providerForName(provider);
0323         if (!p)
0324             return k;
0325         k = G::getKey(p, in, passphrase, result);
0326     }
0327     // all
0328     else {
0329         ProviderList pl = allProviders();
0330         for (int n = 0; n < pl.count(); ++n) {
0331             ConvertResult r;
0332             k = G::getKey(pl[n], in, passphrase, &r);
0333             if (result)
0334                 *result = r;
0335             if (!k.isNull())
0336                 break;
0337             if (r == ErrorPassphrase) // don't loop if we get this
0338                 break;
0339         }
0340     }
0341 
0342     return k;
0343 }
0344 
0345 PBEAlgorithm get_pbe_default()
0346 {
0347     return PBES2_TripleDES_SHA1;
0348 }
0349 
0350 static PrivateKey get_privatekey_der(const SecureArray &der,
0351                                      const QString     &fileName,
0352                                      void              *ptr,
0353                                      const SecureArray &passphrase,
0354                                      ConvertResult     *result,
0355                                      const QString     &provider)
0356 {
0357     PrivateKey    out;
0358     ConvertResult r;
0359     out = getKey<PrivateKey, Getter_PrivateKey<SecureArray>, SecureArray>(provider, der, passphrase, &r);
0360 
0361     // error converting without passphrase?  maybe a passphrase is needed
0362     if (use_asker_fallback(r) && passphrase.isEmpty()) {
0363         SecureArray pass;
0364         if (ask_passphrase(fileName, ptr, &pass))
0365             out = getKey<PrivateKey, Getter_PrivateKey<SecureArray>, SecureArray>(provider, der, pass, &r);
0366     }
0367     if (result)
0368         *result = r;
0369     return out;
0370 }
0371 
0372 static PrivateKey get_privatekey_pem(const QString     &pem,
0373                                      const QString     &fileName,
0374                                      void              *ptr,
0375                                      const SecureArray &passphrase,
0376                                      ConvertResult     *result,
0377                                      const QString     &provider)
0378 {
0379     PrivateKey    out;
0380     ConvertResult r;
0381     out = getKey<PrivateKey, Getter_PrivateKey<QString>, QString>(provider, pem, passphrase, &r);
0382 
0383     // error converting without passphrase?  maybe a passphrase is needed
0384     if (use_asker_fallback(r) && passphrase.isEmpty()) {
0385         SecureArray pass;
0386         if (ask_passphrase(fileName, ptr, &pass))
0387             out = getKey<PrivateKey, Getter_PrivateKey<QString>, QString>(provider, pem, pass, &r);
0388     }
0389     if (result)
0390         *result = r;
0391     return out;
0392 }
0393 
0394 //----------------------------------------------------------------------------
0395 // Global
0396 //----------------------------------------------------------------------------
0397 
0398 // adapted from Botan
0399 static const unsigned char pkcs_sha1[] =
0400     {0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14};
0401 
0402 static const unsigned char pkcs_md5[] =
0403     {0x30, 0x20, 0x30, 0x0C, 0x06, 0x08, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10};
0404 
0405 static const unsigned char pkcs_md2[] =
0406     {0x30, 0x20, 0x30, 0x0C, 0x06, 0x08, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x02, 0x05, 0x00, 0x04, 0x10};
0407 
0408 static const unsigned char pkcs_ripemd160[] =
0409     {0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x24, 0x03, 0x02, 0x01, 0x05, 0x00, 0x04, 0x14};
0410 
0411 QByteArray get_hash_id(const QString &name)
0412 {
0413     if (name == QLatin1String("sha1"))
0414         return QByteArray::fromRawData((const char *)pkcs_sha1, sizeof(pkcs_sha1));
0415     else if (name == QLatin1String("md5"))
0416         return QByteArray::fromRawData((const char *)pkcs_md5, sizeof(pkcs_md5));
0417     else if (name == QLatin1String("md2"))
0418         return QByteArray::fromRawData((const char *)pkcs_md2, sizeof(pkcs_md2));
0419     else if (name == QLatin1String("ripemd160"))
0420         return QByteArray::fromRawData((const char *)pkcs_ripemd160, sizeof(pkcs_ripemd160));
0421     else
0422         return QByteArray();
0423 }
0424 
0425 QByteArray emsa3Encode(const QString &hashName, const QByteArray &digest, int size)
0426 {
0427     const QByteArray hash_id = get_hash_id(hashName);
0428     if (hash_id.isEmpty())
0429         return QByteArray();
0430 
0431     // logic adapted from Botan
0432     const int basesize = hash_id.size() + digest.size() + 2;
0433     if (size == -1)
0434         size = basesize + 1; // default to 1-byte pad
0435     int padlen = size - basesize;
0436     if (padlen < 1)
0437         return QByteArray();
0438 
0439     QByteArray out(size, (char)0xff); // pad with 0xff
0440     out[0]          = 0x01;
0441     out[padlen + 1] = 0x00;
0442     int at          = padlen + 2;
0443     memcpy(out.data() + at, hash_id.data(), hash_id.size());
0444     at += hash_id.size();
0445     memcpy(out.data() + at, digest.data(), digest.size());
0446     return out;
0447 }
0448 
0449 //----------------------------------------------------------------------------
0450 // DLGroup
0451 //----------------------------------------------------------------------------
0452 class DLGroup::Private
0453 {
0454 public:
0455     BigInteger p, q, g;
0456 
0457     Private(const BigInteger &p1, const BigInteger &q1, const BigInteger &g1)
0458         : p(p1)
0459         , q(q1)
0460         , g(g1)
0461     {
0462     }
0463 };
0464 
0465 DLGroup::DLGroup()
0466 {
0467     d = nullptr;
0468 }
0469 
0470 DLGroup::DLGroup(const BigInteger &p, const BigInteger &q, const BigInteger &g)
0471 {
0472     d = new Private(p, q, g);
0473 }
0474 
0475 DLGroup::DLGroup(const BigInteger &p, const BigInteger &g)
0476 {
0477     d = new Private(p, 0, g);
0478 }
0479 
0480 DLGroup::DLGroup(const DLGroup &from)
0481 {
0482     d     = nullptr;
0483     *this = from;
0484 }
0485 
0486 DLGroup::~DLGroup()
0487 {
0488     delete d;
0489 }
0490 
0491 DLGroup &DLGroup::operator=(const DLGroup &from)
0492 {
0493     delete d;
0494     d = nullptr;
0495 
0496     if (from.d)
0497         d = new Private(*from.d);
0498 
0499     return *this;
0500 }
0501 
0502 QList<DLGroupSet> DLGroup::supportedGroupSets(const QString &provider)
0503 {
0504     return getList<DLGroupSet, Getter_GroupSet>(provider);
0505 }
0506 
0507 bool DLGroup::isNull() const
0508 {
0509     return (d ? false : true);
0510 }
0511 
0512 BigInteger DLGroup::p() const
0513 {
0514     Q_ASSERT(d);
0515     return d->p;
0516 }
0517 
0518 BigInteger DLGroup::q() const
0519 {
0520     Q_ASSERT(d);
0521     return d->q;
0522 }
0523 
0524 BigInteger DLGroup::g() const
0525 {
0526     Q_ASSERT(d);
0527     return d->g;
0528 }
0529 
0530 //----------------------------------------------------------------------------
0531 // PKey
0532 //----------------------------------------------------------------------------
0533 class PKey::Private
0534 {
0535 public:
0536 };
0537 
0538 PKey::PKey()
0539 {
0540     d = new Private;
0541 }
0542 
0543 PKey::PKey(const QString &type, const QString &provider)
0544     : Algorithm(type, provider)
0545 {
0546     d = new Private;
0547 }
0548 
0549 PKey::PKey(const PKey &from)
0550     : Algorithm(from)
0551 {
0552     d     = new Private;
0553     *this = from;
0554 }
0555 
0556 PKey::~PKey()
0557 {
0558     delete d;
0559 }
0560 
0561 PKey &PKey::operator=(const PKey &from)
0562 {
0563     Algorithm::operator=(from);
0564     *d = *from.d;
0565     return *this;
0566 }
0567 
0568 void PKey::set(const PKey &k)
0569 {
0570     *this = k;
0571 }
0572 
0573 void PKey::assignToPublic(PKey *dest) const
0574 {
0575     dest->set(*this);
0576 
0577     // converting private to public
0578     if (dest->isPrivate())
0579         static_cast<PKeyContext *>(dest->context())->key()->convertToPublic();
0580 }
0581 
0582 void PKey::assignToPrivate(PKey *dest) const
0583 {
0584     dest->set(*this);
0585 }
0586 
0587 QList<PKey::Type> PKey::supportedTypes(const QString &provider)
0588 {
0589     return getList<Type, Getter_Type>(provider);
0590 }
0591 
0592 QList<PKey::Type> PKey::supportedIOTypes(const QString &provider)
0593 {
0594     return getList<Type, Getter_IOType>(provider);
0595 }
0596 
0597 bool PKey::isNull() const
0598 {
0599     return (!context() ? true : false);
0600 }
0601 
0602 PKey::Type PKey::type() const
0603 {
0604     if (isNull())
0605         return RSA; // some default so we don't explode
0606     return static_cast<const PKeyContext *>(context())->key()->type();
0607 }
0608 
0609 int PKey::bitSize() const
0610 {
0611     return static_cast<const PKeyContext *>(context())->key()->bits();
0612 }
0613 
0614 bool PKey::isRSA() const
0615 {
0616     return (type() == RSA);
0617 }
0618 
0619 bool PKey::isDSA() const
0620 {
0621     return (type() == DSA);
0622 }
0623 
0624 bool PKey::isDH() const
0625 {
0626     return (type() == DH);
0627 }
0628 
0629 bool PKey::isPublic() const
0630 {
0631     if (isNull())
0632         return false;
0633     return !isPrivate();
0634 }
0635 
0636 bool PKey::isPrivate() const
0637 {
0638     if (isNull())
0639         return false;
0640     return static_cast<const PKeyContext *>(context())->key()->isPrivate();
0641 }
0642 
0643 bool PKey::canExport() const
0644 {
0645     return static_cast<const PKeyContext *>(context())->key()->canExport();
0646 }
0647 
0648 bool PKey::canKeyAgree() const
0649 {
0650     return isDH();
0651 }
0652 
0653 PublicKey PKey::toPublicKey() const
0654 {
0655     PublicKey k;
0656     if (!isNull())
0657         assignToPublic(&k);
0658     return k;
0659 }
0660 
0661 PrivateKey PKey::toPrivateKey() const
0662 {
0663     PrivateKey k;
0664     if (!isNull() && isPrivate())
0665         assignToPrivate(&k);
0666     return k;
0667 }
0668 
0669 RSAPublicKey PKey::toRSAPublicKey() const
0670 {
0671     RSAPublicKey k;
0672     if (!isNull() && isRSA())
0673         assignToPublic(&k);
0674     return k;
0675 }
0676 
0677 RSAPrivateKey PKey::toRSAPrivateKey() const
0678 {
0679     RSAPrivateKey k;
0680     if (!isNull() && isRSA() && isPrivate())
0681         assignToPrivate(&k);
0682     return k;
0683 }
0684 
0685 DSAPublicKey PKey::toDSAPublicKey() const
0686 {
0687     DSAPublicKey k;
0688     if (!isNull() && isDSA())
0689         assignToPublic(&k);
0690     return k;
0691 }
0692 
0693 DSAPrivateKey PKey::toDSAPrivateKey() const
0694 {
0695     DSAPrivateKey k;
0696     if (!isNull() && isDSA() && isPrivate())
0697         assignToPrivate(&k);
0698     return k;
0699 }
0700 
0701 DHPublicKey PKey::toDHPublicKey() const
0702 {
0703     DHPublicKey k;
0704     if (!isNull() && isDH())
0705         assignToPublic(&k);
0706     return k;
0707 }
0708 
0709 DHPrivateKey PKey::toDHPrivateKey() const
0710 {
0711     DHPrivateKey k;
0712     if (!isNull() && isDH() && isPrivate())
0713         assignToPrivate(&k);
0714     return k;
0715 }
0716 
0717 bool PKey::operator==(const PKey &a) const
0718 {
0719     if (isNull() || a.isNull() || type() != a.type())
0720         return false;
0721 
0722     if (a.isPrivate())
0723         return (toPrivateKey().toDER() == a.toPrivateKey().toDER());
0724     else
0725         return (toPublicKey().toDER() == a.toPublicKey().toDER());
0726 }
0727 
0728 bool PKey::operator!=(const PKey &a) const
0729 {
0730     return !(*this == a);
0731 }
0732 
0733 //----------------------------------------------------------------------------
0734 // PublicKey
0735 //----------------------------------------------------------------------------
0736 PublicKey::PublicKey()
0737 {
0738 }
0739 
0740 PublicKey::PublicKey(const QString &type, const QString &provider)
0741     : PKey(type, provider)
0742 {
0743 }
0744 
0745 PublicKey::PublicKey(const PrivateKey &k)
0746 {
0747     set(k.toPublicKey());
0748 }
0749 
0750 PublicKey::PublicKey(const QString &fileName)
0751 {
0752     *this = fromPEMFile(fileName, nullptr, QString());
0753 }
0754 
0755 PublicKey::PublicKey(const PublicKey &from)
0756     : PKey(from)
0757 {
0758 }
0759 
0760 PublicKey::~PublicKey()
0761 {
0762 }
0763 
0764 PublicKey &PublicKey::operator=(const PublicKey &from)
0765 {
0766     PKey::operator=(from);
0767     return *this;
0768 }
0769 
0770 RSAPublicKey PublicKey::toRSA() const
0771 {
0772     return toRSAPublicKey();
0773 }
0774 
0775 DSAPublicKey PublicKey::toDSA() const
0776 {
0777     return toDSAPublicKey();
0778 }
0779 
0780 DHPublicKey PublicKey::toDH() const
0781 {
0782     return toDHPublicKey();
0783 }
0784 
0785 bool PublicKey::canEncrypt() const
0786 {
0787     return isRSA();
0788 }
0789 
0790 bool PublicKey::canDecrypt() const
0791 {
0792     return isRSA();
0793 }
0794 
0795 bool PublicKey::canVerify() const
0796 {
0797     return (isRSA() || isDSA());
0798 }
0799 
0800 int PublicKey::maximumEncryptSize(EncryptionAlgorithm alg) const
0801 {
0802     const PKeyContext *ctx = qobject_cast<const PKeyContext *>(context());
0803     if (ctx)
0804         return ctx->key()->maximumEncryptSize(alg);
0805     else
0806         return -1;
0807 }
0808 
0809 SecureArray PublicKey::encrypt(const SecureArray &a, EncryptionAlgorithm alg)
0810 {
0811     PKeyContext *ctx = qobject_cast<PKeyContext *>(context());
0812     if (ctx)
0813         return ctx->key()->encrypt(a, alg);
0814     else
0815         return SecureArray();
0816 }
0817 
0818 bool PublicKey::decrypt(const SecureArray &in, SecureArray *out, EncryptionAlgorithm alg)
0819 {
0820     PKeyContext *ctx = qobject_cast<PKeyContext *>(context());
0821     if (ctx)
0822         return ctx->key()->decrypt(in, out, alg);
0823     else
0824         return false;
0825 }
0826 
0827 void PublicKey::startVerify(SignatureAlgorithm alg, SignatureFormat format)
0828 {
0829     if (isDSA() && format == DefaultFormat)
0830         format = IEEE_1363;
0831     PKeyContext *ctx = qobject_cast<PKeyContext *>(context());
0832     if (ctx)
0833         ctx->key()->startVerify(alg, format);
0834 }
0835 
0836 void PublicKey::update(const MemoryRegion &a)
0837 {
0838     PKeyContext *ctx = qobject_cast<PKeyContext *>(context());
0839     if (ctx) {
0840         ctx->key()->update(a);
0841     }
0842 }
0843 
0844 bool PublicKey::validSignature(const QByteArray &sig)
0845 {
0846     PKeyContext *ctx = qobject_cast<PKeyContext *>(context());
0847     if (ctx)
0848         return ctx->key()->endVerify(sig);
0849     return false;
0850 }
0851 
0852 bool PublicKey::verifyMessage(const MemoryRegion &a,
0853                               const QByteArray   &sig,
0854                               SignatureAlgorithm  alg,
0855                               SignatureFormat     format)
0856 {
0857     startVerify(alg, format);
0858     update(a);
0859     return validSignature(sig);
0860 }
0861 
0862 QByteArray PublicKey::toDER() const
0863 {
0864     QByteArray         out;
0865     const PKeyContext *cur = static_cast<const PKeyContext *>(context());
0866     Provider          *p   = providerForIOType(type(), cur);
0867     if (!p)
0868         return out;
0869     if (cur->provider() == p) {
0870         out = cur->publicToDER();
0871     } else {
0872         PKeyContext *pk = static_cast<PKeyContext *>(getContext(QStringLiteral("pkey"), p));
0873         if (pk && pk->importKey(cur->key()))
0874             out = pk->publicToDER();
0875         delete pk;
0876     }
0877     return out;
0878 }
0879 
0880 QString PublicKey::toPEM() const
0881 {
0882     QString            out;
0883     const PKeyContext *cur = static_cast<const PKeyContext *>(context());
0884     if (!cur)
0885         return out;
0886     Provider *p = providerForIOType(type(), cur);
0887     if (!p)
0888         return out;
0889     if (cur->provider() == p) {
0890         out = cur->publicToPEM();
0891     } else {
0892         PKeyContext *pk = static_cast<PKeyContext *>(getContext(QStringLiteral("pkey"), p));
0893         if (pk && pk->importKey(cur->key()))
0894             out = pk->publicToPEM();
0895         delete pk;
0896     }
0897     return out;
0898 }
0899 
0900 bool PublicKey::toPEMFile(const QString &fileName) const
0901 {
0902     return stringToFile(fileName, toPEM());
0903 }
0904 
0905 PublicKey PublicKey::fromDER(const QByteArray &a, ConvertResult *result, const QString &provider)
0906 {
0907     return getKey<PublicKey, Getter_PublicKey<QByteArray>, QByteArray>(provider, a, SecureArray(), result);
0908 }
0909 
0910 PublicKey PublicKey::fromPEM(const QString &s, ConvertResult *result, const QString &provider)
0911 {
0912     return getKey<PublicKey, Getter_PublicKey<QString>, QString>(provider, s, SecureArray(), result);
0913 }
0914 
0915 PublicKey PublicKey::fromPEMFile(const QString &fileName, ConvertResult *result, const QString &provider)
0916 {
0917     QString pem;
0918     if (!stringFromFile(fileName, &pem)) {
0919         if (result)
0920             *result = ErrorFile;
0921         return PublicKey();
0922     }
0923     return fromPEM(pem, result, provider);
0924 }
0925 
0926 //----------------------------------------------------------------------------
0927 // PrivateKey
0928 //----------------------------------------------------------------------------
0929 PrivateKey::PrivateKey()
0930 {
0931 }
0932 
0933 PrivateKey::PrivateKey(const QString &type, const QString &provider)
0934     : PKey(type, provider)
0935 {
0936 }
0937 
0938 PrivateKey::PrivateKey(const QString &fileName, const SecureArray &passphrase)
0939 {
0940     *this = fromPEMFile(fileName, passphrase, nullptr, QString());
0941 }
0942 
0943 PrivateKey::PrivateKey(const PrivateKey &from)
0944     : PKey(from)
0945 {
0946 }
0947 
0948 PrivateKey::~PrivateKey()
0949 {
0950 }
0951 
0952 PrivateKey &PrivateKey::operator=(const PrivateKey &from)
0953 {
0954     PKey::operator=(from);
0955     return *this;
0956 }
0957 
0958 RSAPrivateKey PrivateKey::toRSA() const
0959 {
0960     return toRSAPrivateKey();
0961 }
0962 
0963 DSAPrivateKey PrivateKey::toDSA() const
0964 {
0965     return toDSAPrivateKey();
0966 }
0967 
0968 DHPrivateKey PrivateKey::toDH() const
0969 {
0970     return toDHPrivateKey();
0971 }
0972 
0973 bool PrivateKey::canDecrypt() const
0974 {
0975     return isRSA();
0976 }
0977 
0978 bool PrivateKey::canEncrypt() const
0979 {
0980     return isRSA();
0981 }
0982 
0983 bool PrivateKey::canSign() const
0984 {
0985     return (isRSA() || isDSA());
0986 }
0987 
0988 int PrivateKey::maximumEncryptSize(EncryptionAlgorithm alg) const
0989 {
0990     return static_cast<const PKeyContext *>(context())->key()->maximumEncryptSize(alg);
0991 }
0992 
0993 bool PrivateKey::decrypt(const SecureArray &in, SecureArray *out, EncryptionAlgorithm alg)
0994 {
0995     return static_cast<PKeyContext *>(context())->key()->decrypt(in, out, alg);
0996 }
0997 
0998 SecureArray PrivateKey::encrypt(const SecureArray &a, EncryptionAlgorithm alg)
0999 {
1000     return static_cast<PKeyContext *>(context())->key()->encrypt(a, alg);
1001 }
1002 
1003 void PrivateKey::startSign(SignatureAlgorithm alg, SignatureFormat format)
1004 {
1005     if (isDSA() && format == DefaultFormat)
1006         format = IEEE_1363;
1007     static_cast<PKeyContext *>(context())->key()->startSign(alg, format);
1008 }
1009 
1010 void PrivateKey::update(const MemoryRegion &a)
1011 {
1012     static_cast<PKeyContext *>(context())->key()->update(a);
1013 }
1014 
1015 QByteArray PrivateKey::signature()
1016 {
1017     return static_cast<PKeyContext *>(context())->key()->endSign();
1018 }
1019 
1020 QByteArray PrivateKey::signMessage(const MemoryRegion &a, SignatureAlgorithm alg, SignatureFormat format)
1021 {
1022     startSign(alg, format);
1023     update(a);
1024     return signature();
1025 }
1026 
1027 SymmetricKey PrivateKey::deriveKey(const PublicKey &theirs)
1028 {
1029     const PKeyContext *theirContext = static_cast<const PKeyContext *>(theirs.context());
1030     return static_cast<PKeyContext *>(context())->key()->deriveKey(*(theirContext->key()));
1031 }
1032 
1033 QList<PBEAlgorithm> PrivateKey::supportedPBEAlgorithms(const QString &provider)
1034 {
1035     return getList<PBEAlgorithm, Getter_PBE>(provider);
1036 }
1037 
1038 SecureArray PrivateKey::toDER(const SecureArray &passphrase, PBEAlgorithm pbe) const
1039 {
1040     SecureArray out;
1041     if (pbe == PBEDefault)
1042         pbe = get_pbe_default();
1043     const PKeyContext *cur = static_cast<const PKeyContext *>(context());
1044     Provider          *p   = providerForPBE(pbe, type(), cur);
1045     if (!p)
1046         return out;
1047     if (cur->provider() == p) {
1048         out = cur->privateToDER(passphrase, pbe);
1049     } else {
1050         PKeyContext *pk = static_cast<PKeyContext *>(getContext(QStringLiteral("pkey"), p));
1051         if (pk->importKey(cur->key()))
1052             out = pk->privateToDER(passphrase, pbe);
1053         delete pk;
1054     }
1055     return out;
1056 }
1057 
1058 QString PrivateKey::toPEM(const SecureArray &passphrase, PBEAlgorithm pbe) const
1059 {
1060     QString out;
1061     if (pbe == PBEDefault)
1062         pbe = get_pbe_default();
1063     const PKeyContext *cur = static_cast<const PKeyContext *>(context());
1064     Provider          *p   = providerForPBE(pbe, type(), cur);
1065     if (!p)
1066         return out;
1067     if (cur->provider() == p) {
1068         out = cur->privateToPEM(passphrase, pbe);
1069     } else {
1070         PKeyContext *pk = static_cast<PKeyContext *>(getContext(QStringLiteral("pkey"), p));
1071         if (pk->importKey(cur->key()))
1072             out = pk->privateToPEM(passphrase, pbe);
1073         delete pk;
1074     }
1075     return out;
1076 }
1077 
1078 bool PrivateKey::toPEMFile(const QString &fileName, const SecureArray &passphrase, PBEAlgorithm pbe) const
1079 {
1080     return stringToFile(fileName, toPEM(passphrase, pbe));
1081 }
1082 
1083 PrivateKey
1084 PrivateKey::fromDER(const SecureArray &a, const SecureArray &passphrase, ConvertResult *result, const QString &provider)
1085 {
1086     return get_privatekey_der(a, QString(), (void *)&a, passphrase, result, provider);
1087 }
1088 
1089 PrivateKey
1090 PrivateKey::fromPEM(const QString &s, const SecureArray &passphrase, ConvertResult *result, const QString &provider)
1091 {
1092     return get_privatekey_pem(s, QString(), (void *)&s, passphrase, result, provider);
1093 }
1094 
1095 PrivateKey PrivateKey::fromPEMFile(const QString     &fileName,
1096                                    const SecureArray &passphrase,
1097                                    ConvertResult     *result,
1098                                    const QString     &provider)
1099 {
1100     QString pem;
1101     if (!stringFromFile(fileName, &pem)) {
1102         if (result)
1103             *result = ErrorFile;
1104         return PrivateKey();
1105     }
1106     return get_privatekey_pem(pem, fileName, nullptr, passphrase, result, provider);
1107 }
1108 
1109 //----------------------------------------------------------------------------
1110 // KeyGenerator
1111 //----------------------------------------------------------------------------
1112 class KeyGenerator::Private : public QObject
1113 {
1114     Q_OBJECT
1115 public:
1116     KeyGenerator *parent;
1117     bool          blocking, wasBlocking;
1118     PrivateKey    key;
1119     DLGroup       group;
1120 
1121     PKeyBase       *k;
1122     PKeyContext    *dest;
1123     DLGroupContext *dc;
1124 
1125     Private(KeyGenerator *_parent)
1126         : QObject(_parent)
1127         , parent(_parent)
1128     {
1129         k    = nullptr;
1130         dest = nullptr;
1131         dc   = nullptr;
1132     }
1133 
1134     ~Private() override
1135     {
1136         delete k;
1137         delete dest;
1138         delete dc;
1139     }
1140 
1141 public Q_SLOTS:
1142     void done()
1143     {
1144         if (!k->isNull()) {
1145             if (!wasBlocking) {
1146                 k->setParent(nullptr);
1147                 k->moveToThread(nullptr);
1148             }
1149             dest->setKey(k);
1150             k = nullptr;
1151 
1152             key.change(dest);
1153             dest = nullptr;
1154         } else {
1155             delete k;
1156             k = nullptr;
1157             delete dest;
1158             dest = nullptr;
1159         }
1160 
1161         if (!wasBlocking)
1162             emit parent->finished();
1163     }
1164 
1165     void done_group()
1166     {
1167         if (!dc->isNull()) {
1168             BigInteger p, q, g;
1169             dc->getResult(&p, &q, &g);
1170             group = DLGroup(p, q, g);
1171         }
1172         delete dc;
1173         dc = nullptr;
1174 
1175         if (!wasBlocking)
1176             emit parent->finished();
1177     }
1178 };
1179 
1180 KeyGenerator::KeyGenerator(QObject *parent)
1181     : QObject(parent)
1182 {
1183     d           = new Private(this);
1184     d->blocking = true;
1185 }
1186 
1187 KeyGenerator::~KeyGenerator()
1188 {
1189     delete d;
1190 }
1191 
1192 bool KeyGenerator::blockingEnabled() const
1193 {
1194     return d->blocking;
1195 }
1196 
1197 void KeyGenerator::setBlockingEnabled(bool b)
1198 {
1199     d->blocking = b;
1200 }
1201 
1202 bool KeyGenerator::isBusy() const
1203 {
1204     return (d->k ? true : false);
1205 }
1206 
1207 PrivateKey KeyGenerator::createRSA(int bits, int exp, const QString &provider)
1208 {
1209     if (isBusy())
1210         return PrivateKey();
1211 
1212     d->key         = PrivateKey();
1213     d->wasBlocking = d->blocking;
1214     d->k           = static_cast<RSAContext *>(getContext(QStringLiteral("rsa"), provider));
1215     if (!d->k)
1216         return PrivateKey();
1217     d->dest = static_cast<PKeyContext *>(getContext(QStringLiteral("pkey"), d->k->provider()));
1218 
1219     if (!d->blocking) {
1220         d->k->moveToThread(thread());
1221         d->k->setParent(d);
1222         connect(d->k, &RSAContext::finished, d, &Private::done);
1223         static_cast<RSAContext *>(d->k)->createPrivate(bits, exp, false);
1224     } else {
1225         static_cast<RSAContext *>(d->k)->createPrivate(bits, exp, true);
1226         d->done();
1227     }
1228 
1229     return d->key;
1230 }
1231 
1232 PrivateKey KeyGenerator::createDSA(const DLGroup &domain, const QString &provider)
1233 {
1234     if (isBusy())
1235         return PrivateKey();
1236 
1237     d->key         = PrivateKey();
1238     d->wasBlocking = d->blocking;
1239     d->k           = static_cast<DSAContext *>(getContext(QStringLiteral("dsa"), provider));
1240     d->dest        = static_cast<PKeyContext *>(getContext(QStringLiteral("pkey"), d->k->provider()));
1241 
1242     if (!d->blocking) {
1243         d->k->moveToThread(thread());
1244         d->k->setParent(d);
1245         connect(d->k, &DSAContext::finished, d, &Private::done);
1246         static_cast<DSAContext *>(d->k)->createPrivate(domain, false);
1247     } else {
1248         static_cast<DSAContext *>(d->k)->createPrivate(domain, true);
1249         d->done();
1250     }
1251 
1252     return d->key;
1253 }
1254 
1255 PrivateKey KeyGenerator::createDH(const DLGroup &domain, const QString &provider)
1256 {
1257     if (isBusy())
1258         return PrivateKey();
1259 
1260     d->key         = PrivateKey();
1261     d->wasBlocking = d->blocking;
1262     d->k           = static_cast<DHContext *>(getContext(QStringLiteral("dh"), provider));
1263     d->dest        = static_cast<PKeyContext *>(getContext(QStringLiteral("pkey"), d->k->provider()));
1264 
1265     if (!d->blocking) {
1266         d->k->moveToThread(thread());
1267         d->k->setParent(d);
1268         connect(d->k, &DHContext::finished, d, &Private::done);
1269         static_cast<DHContext *>(d->k)->createPrivate(domain, false);
1270     } else {
1271         static_cast<DHContext *>(d->k)->createPrivate(domain, true);
1272         d->done();
1273     }
1274 
1275     return d->key;
1276 }
1277 
1278 PrivateKey KeyGenerator::key() const
1279 {
1280     return d->key;
1281 }
1282 
1283 DLGroup KeyGenerator::createDLGroup(QCA::DLGroupSet set, const QString &provider)
1284 {
1285     if (isBusy())
1286         return DLGroup();
1287 
1288     Provider *p;
1289     if (!provider.isEmpty())
1290         p = providerForName(provider);
1291     else
1292         p = providerForGroupSet(set);
1293 
1294     d->dc    = static_cast<DLGroupContext *>(getContext(QStringLiteral("dlgroup"), p));
1295     d->group = DLGroup();
1296 
1297     if (d->dc) {
1298         d->wasBlocking = d->blocking;
1299         if (!d->blocking) {
1300             connect(d->dc, &DLGroupContext ::finished, d, &Private::done_group);
1301             d->dc->fetchGroup(set, false);
1302         } else {
1303             d->dc->fetchGroup(set, true);
1304             d->done_group();
1305         }
1306     }
1307 
1308     return d->group;
1309 }
1310 
1311 DLGroup KeyGenerator::dlGroup() const
1312 {
1313     return d->group;
1314 }
1315 
1316 //----------------------------------------------------------------------------
1317 // RSAPublicKey
1318 //----------------------------------------------------------------------------
1319 RSAPublicKey::RSAPublicKey()
1320 {
1321 }
1322 
1323 RSAPublicKey::RSAPublicKey(const BigInteger &n, const BigInteger &e, const QString &provider)
1324 {
1325     RSAContext *k = static_cast<RSAContext *>(getContext(QStringLiteral("rsa"), provider));
1326     k->createPublic(n, e);
1327     PKeyContext *c = static_cast<PKeyContext *>(getContext(QStringLiteral("pkey"), k->provider()));
1328     c->setKey(k);
1329     change(c);
1330 }
1331 
1332 RSAPublicKey::RSAPublicKey(const RSAPrivateKey &k)
1333     : PublicKey(k)
1334 {
1335 }
1336 
1337 BigInteger RSAPublicKey::n() const
1338 {
1339     return static_cast<const RSAContext *>(static_cast<const PKeyContext *>(context())->key())->n();
1340 }
1341 
1342 BigInteger RSAPublicKey::e() const
1343 {
1344     return static_cast<const RSAContext *>(static_cast<const PKeyContext *>(context())->key())->e();
1345 }
1346 
1347 //----------------------------------------------------------------------------
1348 // RSAPrivateKey
1349 //----------------------------------------------------------------------------
1350 RSAPrivateKey::RSAPrivateKey()
1351 {
1352 }
1353 
1354 RSAPrivateKey::RSAPrivateKey(const BigInteger &n,
1355                              const BigInteger &e,
1356                              const BigInteger &p,
1357                              const BigInteger &q,
1358                              const BigInteger &d,
1359                              const QString    &provider)
1360 {
1361     RSAContext *k = static_cast<RSAContext *>(getContext(QStringLiteral("rsa"), provider));
1362     k->createPrivate(n, e, p, q, d);
1363     PKeyContext *c = static_cast<PKeyContext *>(getContext(QStringLiteral("pkey"), k->provider()));
1364     c->setKey(k);
1365     change(c);
1366 }
1367 
1368 BigInteger RSAPrivateKey::n() const
1369 {
1370     return static_cast<const RSAContext *>(static_cast<const PKeyContext *>(context())->key())->n();
1371 }
1372 
1373 BigInteger RSAPrivateKey::e() const
1374 {
1375     return static_cast<const RSAContext *>(static_cast<const PKeyContext *>(context())->key())->e();
1376 }
1377 
1378 BigInteger RSAPrivateKey::p() const
1379 {
1380     return static_cast<const RSAContext *>(static_cast<const PKeyContext *>(context())->key())->p();
1381 }
1382 
1383 BigInteger RSAPrivateKey::q() const
1384 {
1385     return static_cast<const RSAContext *>(static_cast<const PKeyContext *>(context())->key())->q();
1386 }
1387 
1388 BigInteger RSAPrivateKey::d() const
1389 {
1390     return static_cast<const RSAContext *>(static_cast<const PKeyContext *>(context())->key())->d();
1391 }
1392 
1393 //----------------------------------------------------------------------------
1394 // DSAPublicKey
1395 //----------------------------------------------------------------------------
1396 DSAPublicKey::DSAPublicKey()
1397 {
1398 }
1399 
1400 DSAPublicKey::DSAPublicKey(const DLGroup &domain, const BigInteger &y, const QString &provider)
1401 {
1402     DSAContext *k = static_cast<DSAContext *>(getContext(QStringLiteral("dsa"), provider));
1403     k->createPublic(domain, y);
1404     PKeyContext *c = static_cast<PKeyContext *>(getContext(QStringLiteral("pkey"), k->provider()));
1405     c->setKey(k);
1406     change(c);
1407 }
1408 
1409 DSAPublicKey::DSAPublicKey(const DSAPrivateKey &k)
1410     : PublicKey(k)
1411 {
1412 }
1413 
1414 DLGroup DSAPublicKey::domain() const
1415 {
1416     return static_cast<const DSAContext *>(static_cast<const PKeyContext *>(context())->key())->domain();
1417 }
1418 
1419 BigInteger DSAPublicKey::y() const
1420 {
1421     return static_cast<const DSAContext *>(static_cast<const PKeyContext *>(context())->key())->y();
1422 }
1423 
1424 //----------------------------------------------------------------------------
1425 // DSAPrivateKey
1426 //----------------------------------------------------------------------------
1427 DSAPrivateKey::DSAPrivateKey()
1428 {
1429 }
1430 
1431 DSAPrivateKey::DSAPrivateKey(const DLGroup &domain, const BigInteger &y, const BigInteger &x, const QString &provider)
1432 {
1433     DSAContext *k = static_cast<DSAContext *>(getContext(QStringLiteral("dsa"), provider));
1434     k->createPrivate(domain, y, x);
1435     PKeyContext *c = static_cast<PKeyContext *>(getContext(QStringLiteral("pkey"), k->provider()));
1436     c->setKey(k);
1437     change(c);
1438 }
1439 
1440 DLGroup DSAPrivateKey::domain() const
1441 {
1442     return static_cast<const DSAContext *>(static_cast<const PKeyContext *>(context())->key())->domain();
1443 }
1444 
1445 BigInteger DSAPrivateKey::y() const
1446 {
1447     return static_cast<const DSAContext *>(static_cast<const PKeyContext *>(context())->key())->y();
1448 }
1449 
1450 BigInteger DSAPrivateKey::x() const
1451 {
1452     return static_cast<const DSAContext *>(static_cast<const PKeyContext *>(context())->key())->x();
1453 }
1454 
1455 //----------------------------------------------------------------------------
1456 // DHPublicKey
1457 //----------------------------------------------------------------------------
1458 DHPublicKey::DHPublicKey()
1459 {
1460 }
1461 
1462 DHPublicKey::DHPublicKey(const DLGroup &domain, const BigInteger &y, const QString &provider)
1463 {
1464     DHContext *k = static_cast<DHContext *>(getContext(QStringLiteral("dh"), provider));
1465     k->createPublic(domain, y);
1466     PKeyContext *c = static_cast<PKeyContext *>(getContext(QStringLiteral("pkey"), k->provider()));
1467     c->setKey(k);
1468     change(c);
1469 }
1470 
1471 DHPublicKey::DHPublicKey(const DHPrivateKey &k)
1472     : PublicKey(k)
1473 {
1474 }
1475 
1476 DLGroup DHPublicKey::domain() const
1477 {
1478     return static_cast<const DHContext *>(static_cast<const PKeyContext *>(context())->key())->domain();
1479 }
1480 
1481 BigInteger DHPublicKey::y() const
1482 {
1483     return static_cast<const DHContext *>(static_cast<const PKeyContext *>(context())->key())->y();
1484 }
1485 
1486 //----------------------------------------------------------------------------
1487 // DHPrivateKey
1488 //----------------------------------------------------------------------------
1489 DHPrivateKey::DHPrivateKey()
1490 {
1491 }
1492 
1493 DHPrivateKey::DHPrivateKey(const DLGroup &domain, const BigInteger &y, const BigInteger &x, const QString &provider)
1494 {
1495     DHContext *k = static_cast<DHContext *>(getContext(QStringLiteral("dh"), provider));
1496     k->createPrivate(domain, y, x);
1497     PKeyContext *c = static_cast<PKeyContext *>(getContext(QStringLiteral("pkey"), k->provider()));
1498     c->setKey(k);
1499     change(c);
1500 }
1501 
1502 DLGroup DHPrivateKey::domain() const
1503 {
1504     return static_cast<const DHContext *>(static_cast<const PKeyContext *>(context())->key())->domain();
1505 }
1506 
1507 BigInteger DHPrivateKey::y() const
1508 {
1509     return static_cast<const DHContext *>(static_cast<const PKeyContext *>(context())->key())->y();
1510 }
1511 
1512 BigInteger DHPrivateKey::x() const
1513 {
1514     return static_cast<const DHContext *>(static_cast<const PKeyContext *>(context())->key())->x();
1515 }
1516 
1517 }
1518 
1519 #include "qca_publickey.moc"