File indexing completed on 2024-09-08 10:15:37
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"