2 key.cpp - wraps a gpgme key
3 Copyright (C) 2003, 2005 Klarälvdalens Datakonsult AB
5 This file is part of GPGME++.
7 GPGME++ is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public
9 License as published by the Free Software Foundation; either
10 version 2 of the License, or (at your option) any later version.
12 GPGME++ is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU Library General Public License for more details.
17 You should have received a copy of the GNU Library General Public License
18 along with GPGME++; see the file COPYING.LIB. If not, write to the
19 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA.
32 #include "engineinfo.h"
42 const GpgME::Key::Null GpgME::Key::null;
49 Key::Key(const Null &) : key() {}
51 Key::Key(const shared_gpgme_key_t &k) : key(k) {}
53 Key::Key(gpgme_key_t k, bool ref)
55 ? shared_gpgme_key_t(k, &gpgme_key_unref)
56 : shared_gpgme_key_t())
59 gpgme_key_ref(impl());
63 UserID Key::userID(unsigned int index) const
65 return UserID(key, index);
68 Subkey Key::subkey(unsigned int index) const
70 return Subkey(key, index);
73 unsigned int Key::numUserIDs() const
78 unsigned int count = 0;
79 for (gpgme_user_id_t uid = key->uids ; uid ; uid = uid->next) {
85 unsigned int Key::numSubkeys() const
90 unsigned int count = 0;
91 for (gpgme_sub_key_t subkey = key->subkeys ; subkey ; subkey = subkey->next) {
97 std::vector<UserID> Key::userIDs() const
100 return std::vector<UserID>();
103 std::vector<UserID> v;
104 v.reserve(numUserIDs());
105 for (gpgme_user_id_t uid = key->uids ; uid ; uid = uid->next) {
106 v.push_back(UserID(key, uid));
111 std::vector<Subkey> Key::subkeys() const
114 return std::vector<Subkey>();
117 std::vector<Subkey> v;
118 v.reserve(numSubkeys());
119 for (gpgme_sub_key_t subkey = key->subkeys ; subkey ; subkey = subkey->next) {
120 v.push_back(Subkey(key, subkey));
125 Key::OwnerTrust Key::ownerTrust() const
130 switch (key->owner_trust) {
132 case GPGME_VALIDITY_UNKNOWN: return Unknown;
133 case GPGME_VALIDITY_UNDEFINED: return Undefined;
134 case GPGME_VALIDITY_NEVER: return Never;
135 case GPGME_VALIDITY_MARGINAL: return Marginal;
136 case GPGME_VALIDITY_FULL: return Full;
137 case GPGME_VALIDITY_ULTIMATE: return Ultimate;
140 char Key::ownerTrustAsString() const
145 switch (key->owner_trust) {
147 case GPGME_VALIDITY_UNKNOWN: return '?';
148 case GPGME_VALIDITY_UNDEFINED: return 'q';
149 case GPGME_VALIDITY_NEVER: return 'n';
150 case GPGME_VALIDITY_MARGINAL: return 'm';
151 case GPGME_VALIDITY_FULL: return 'f';
152 case GPGME_VALIDITY_ULTIMATE: return 'u';
156 Protocol Key::protocol() const
159 return UnknownProtocol;
161 switch (key->protocol) {
162 case GPGME_PROTOCOL_CMS: return CMS;
163 case GPGME_PROTOCOL_OpenPGP: return OpenPGP;
164 default: return UnknownProtocol;
168 const char *Key::protocolAsString() const
170 return key ? gpgme_get_protocol_name(key->protocol) : nullptr ;
173 bool Key::isRevoked() const
175 return key && key->revoked;
178 bool Key::isExpired() const
180 return key && key->expired;
183 bool Key::isDisabled() const
185 return key && key->disabled;
188 bool Key::isInvalid() const
190 return key && key->invalid;
193 bool Key::hasSecret() const
195 return key && key->secret;
198 bool Key::isRoot() const
200 return key && key->subkeys && key->subkeys->fpr && key->chain_id &&
201 strcasecmp(key->subkeys->fpr, key->chain_id) == 0;
204 bool Key::canEncrypt() const
206 return key && key->can_encrypt;
209 bool Key::canSign() const
211 #ifndef GPGME_CAN_SIGN_ON_SECRET_OPENPGP_KEYLISTING_NOT_BROKEN
212 if (key && key->protocol == GPGME_PROTOCOL_OpenPGP) {
216 return canReallySign();
219 bool Key::canReallySign() const
221 return key && key->can_sign;
224 bool Key::canCertify() const
226 return key && key->can_certify;
229 bool Key::canAuthenticate() const
231 return key && key->can_authenticate;
234 bool Key::isQualified() const
236 return key && key->is_qualified;
239 bool Key::isDeVs() const
244 if (!key->subkeys || !key->subkeys->is_de_vs) {
247 for (gpgme_sub_key_t subkey = key->subkeys ; subkey ; subkey = subkey->next) {
248 if (!subkey->is_de_vs) {
255 const char *Key::issuerSerial() const
257 return key ? key->issuer_serial : nullptr ;
259 const char *Key::issuerName() const
261 return key ? key->issuer_name : nullptr ;
263 const char *Key::chainID() const
265 return key ? key->chain_id : nullptr ;
268 const char *Key::keyID() const
270 return key && key->subkeys ? key->subkeys->keyid : nullptr ;
273 const char *Key::shortKeyID() const
275 if (!key || !key->subkeys || !key->subkeys->keyid) {
278 const int len = strlen(key->subkeys->keyid);
280 return key->subkeys->keyid + len - 8; // return the last 8 bytes (in hex notation)
282 return key->subkeys->keyid;
286 const char *Key::primaryFingerprint() const
292 /* Return what gpgme thinks is the primary fingerprint */
296 /* Return the first subkeys fingerprint */
297 return key->subkeys->fpr;
302 unsigned int Key::keyListMode() const
304 return key ? convert_from_gpgme_keylist_mode_t(key->keylist_mode) : 0;
307 const Key &Key::mergeWith(const Key &other)
309 // ### incomplete. Just merges has* and can*, nothing else atm
310 // ### detach also missing
312 if (!this->primaryFingerprint() ||
313 !other.primaryFingerprint() ||
314 strcasecmp(this->primaryFingerprint(), other.primaryFingerprint()) != 0) {
315 return *this; // only merge the Key object which describe the same key
318 const gpgme_key_t me = impl();
319 const gpgme_key_t him = other.impl();
325 me->revoked |= him->revoked;
326 me->expired |= him->expired;
327 me->disabled |= him->disabled;
328 me->invalid |= him->invalid;
329 me->can_encrypt |= him->can_encrypt;
330 me->can_sign |= him->can_sign;
331 me->can_certify |= him->can_certify;
332 me->secret |= him->secret;
333 me->can_authenticate |= him->can_authenticate;
334 me->is_qualified |= him->is_qualified;
335 me->keylist_mode |= him->keylist_mode;
337 // make sure the gpgme_sub_key_t::is_cardkey flag isn't lost:
338 for (gpgme_sub_key_t mysk = me->subkeys ; mysk ; mysk = mysk->next) {
339 for (gpgme_sub_key_t hissk = him->subkeys ; hissk ; hissk = hissk->next) {
340 if (strcmp(mysk->fpr, hissk->fpr) == 0) {
341 mysk->is_cardkey |= hissk->is_cardkey;
342 mysk->secret |= hissk->secret;
343 if (hissk->keygrip && !mysk->keygrip) {
344 mysk->keygrip = strdup(hissk->keygrip);
356 if (isNull() || !primaryFingerprint()) {
359 auto ctx = Context::createForProtocol(protocol());
363 ctx->setKeyListMode(KeyListMode::Local |
364 KeyListMode::Signatures |
365 KeyListMode::SignatureNotations |
366 KeyListMode::Validate |
367 KeyListMode::WithTofu |
368 KeyListMode::WithKeygrip |
369 KeyListMode::WithSecret);
372 if (GpgME::engineInfo(GpgME::GpgEngine).engineVersion() < "2.1.0") {
373 newKey = ctx->key(primaryFingerprint(), err, true);
374 // Not secret so we get the information from the pubring.
375 if (newKey.isNull()) {
376 newKey = ctx->key(primaryFingerprint(), err, false);
379 newKey = ctx->key(primaryFingerprint(), err, false);
389 Key Key::locate(const char *mbox)
395 auto ctx = Context::createForProtocol(OpenPGP);
400 ctx->setKeyListMode (Extern | Local);
402 Error e = ctx->startKeyListing (mbox);
403 auto ret = ctx->nextKey (e);
415 static gpgme_sub_key_t find_subkey(const shared_gpgme_key_t &key, unsigned int idx)
418 for (gpgme_sub_key_t s = key->subkeys ; s ; s = s->next, --idx) {
427 static gpgme_sub_key_t verify_subkey(const shared_gpgme_key_t &key, gpgme_sub_key_t subkey)
430 for (gpgme_sub_key_t s = key->subkeys ; s ; s = s->next) {
439 Subkey::Subkey() : key(), subkey(nullptr) {}
441 Subkey::Subkey(const shared_gpgme_key_t &k, unsigned int idx)
442 : key(k), subkey(find_subkey(k, idx))
447 Subkey::Subkey(const shared_gpgme_key_t &k, gpgme_sub_key_t sk)
448 : key(k), subkey(verify_subkey(k, sk))
453 Key Subkey::parent() const
458 const char *Subkey::keyID() const
460 return subkey ? subkey->keyid : nullptr ;
463 const char *Subkey::fingerprint() const
465 return subkey ? subkey->fpr : nullptr ;
468 Subkey::PubkeyAlgo Subkey::publicKeyAlgorithm() const
470 return subkey ? static_cast<PubkeyAlgo>(subkey->pubkey_algo) : AlgoUnknown;
473 const char *Subkey::publicKeyAlgorithmAsString() const
475 return gpgme_pubkey_algo_name(subkey ? subkey->pubkey_algo : (gpgme_pubkey_algo_t)0);
479 const char *Subkey::publicKeyAlgorithmAsString(PubkeyAlgo algo)
481 if (algo == AlgoUnknown) {
484 return gpgme_pubkey_algo_name(static_cast<gpgme_pubkey_algo_t>(algo));
487 std::string Subkey::algoName() const
490 if (subkey && (gpgmeStr = gpgme_pubkey_algo_string(subkey))) {
491 std::string ret = std::string(gpgmeStr);
492 gpgme_free(gpgmeStr);
495 return std::string();
498 bool Subkey::canEncrypt() const
500 return subkey && subkey->can_encrypt;
503 bool Subkey::canSign() const
505 return subkey && subkey->can_sign;
508 bool Subkey::canCertify() const
510 return subkey && subkey->can_certify;
513 bool Subkey::canAuthenticate() const
515 return subkey && subkey->can_authenticate;
518 bool Subkey::isQualified() const
520 return subkey && subkey->is_qualified;
523 bool Subkey::isDeVs() const
525 return subkey && subkey->is_de_vs;
528 bool Subkey::isCardKey() const
530 return subkey && subkey->is_cardkey;
533 const char *Subkey::cardSerialNumber() const
535 return subkey ? subkey->card_number : nullptr;
538 const char *Subkey::keyGrip() const
540 return subkey ? subkey->keygrip : nullptr;
543 bool Subkey::isSecret() const
545 return subkey && subkey->secret;
548 unsigned int Subkey::length() const
550 return subkey ? subkey->length : 0 ;
553 time_t Subkey::creationTime() const
555 return static_cast<time_t>(subkey ? subkey->timestamp : 0);
558 time_t Subkey::expirationTime() const
560 return static_cast<time_t>(subkey ? subkey->expires : 0);
563 bool Subkey::neverExpires() const
565 return expirationTime() == time_t(0);
568 bool Subkey::isRevoked() const
570 return subkey && subkey->revoked;
573 bool Subkey::isInvalid() const
575 return subkey && subkey->invalid;
578 bool Subkey::isExpired() const
580 return subkey && subkey->expired;
583 bool Subkey::isDisabled() const
585 return subkey && subkey->disabled;
594 static gpgme_user_id_t find_uid(const shared_gpgme_key_t &key, unsigned int idx)
597 for (gpgme_user_id_t u = key->uids ; u ; u = u->next, --idx) {
606 static gpgme_user_id_t verify_uid(const shared_gpgme_key_t &key, gpgme_user_id_t uid)
609 for (gpgme_user_id_t u = key->uids ; u ; u = u->next) {
618 UserID::UserID() : key(), uid(nullptr) {}
620 UserID::UserID(const shared_gpgme_key_t &k, gpgme_user_id_t u)
621 : key(k), uid(verify_uid(k, u))
626 UserID::UserID(const shared_gpgme_key_t &k, unsigned int idx)
627 : key(k), uid(find_uid(k, idx))
632 Key UserID::parent() const
637 UserID::Signature UserID::signature(unsigned int index) const
639 return Signature(key, uid, index);
642 unsigned int UserID::numSignatures() const
647 unsigned int count = 0;
648 for (gpgme_key_sig_t sig = uid->signatures ; sig ; sig = sig->next) {
654 std::vector<UserID::Signature> UserID::signatures() const
657 return std::vector<Signature>();
660 std::vector<Signature> v;
661 v.reserve(numSignatures());
662 for (gpgme_key_sig_t sig = uid->signatures ; sig ; sig = sig->next) {
663 v.push_back(Signature(key, uid, sig));
668 const char *UserID::id() const
670 return uid ? uid->uid : nullptr ;
673 const char *UserID::name() const
675 return uid ? uid->name : nullptr ;
678 const char *UserID::email() const
680 return uid ? uid->email : nullptr ;
683 const char *UserID::comment() const
685 return uid ? uid->comment : nullptr ;
688 const char *UserID::uidhash() const
690 return uid ? uid->uidhash : nullptr ;
693 UserID::Validity UserID::validity() const
698 switch (uid->validity) {
700 case GPGME_VALIDITY_UNKNOWN: return Unknown;
701 case GPGME_VALIDITY_UNDEFINED: return Undefined;
702 case GPGME_VALIDITY_NEVER: return Never;
703 case GPGME_VALIDITY_MARGINAL: return Marginal;
704 case GPGME_VALIDITY_FULL: return Full;
705 case GPGME_VALIDITY_ULTIMATE: return Ultimate;
709 char UserID::validityAsString() const
714 switch (uid->validity) {
716 case GPGME_VALIDITY_UNKNOWN: return '?';
717 case GPGME_VALIDITY_UNDEFINED: return 'q';
718 case GPGME_VALIDITY_NEVER: return 'n';
719 case GPGME_VALIDITY_MARGINAL: return 'm';
720 case GPGME_VALIDITY_FULL: return 'f';
721 case GPGME_VALIDITY_ULTIMATE: return 'u';
725 bool UserID::isRevoked() const
727 return uid && uid->revoked;
730 bool UserID::isInvalid() const
732 return uid && uid->invalid;
735 TofuInfo UserID::tofuInfo() const
740 return TofuInfo(uid->tofu);
743 static gpgme_key_sig_t find_last_valid_sig_for_keyid (gpgme_user_id_t uid,
749 gpgme_key_sig_t ret = NULL;
750 for (gpgme_key_sig_t s = uid->signatures ; s ; s = s->next) {
751 if (s->keyid && !strcmp(keyid, s->keyid)) {
752 if (!s->expired && !s->revoked && !s->invalid && !s->status) {
755 } else if (ret && ret->timestamp <= s->timestamp) {
756 /* Equals because when the timestamps are the same we prefer
757 the last in the list */
766 const char *UserID::remark(const Key &remarker, Error &err) const
768 if (!uid || remarker.isNull()) {
769 err = Error::fromCode(GPG_ERR_GENERAL);
773 if (key->protocol != GPGME_PROTOCOL_OpenPGP) {
777 if (!(key->keylist_mode & GPGME_KEYLIST_MODE_SIG_NOTATIONS) ||
778 !(key->keylist_mode & GPGME_KEYLIST_MODE_SIGS)) {
779 err = Error::fromCode(GPG_ERR_NO_DATA);
783 gpgme_key_sig_t s = find_last_valid_sig_for_keyid(uid, remarker.keyID());
789 for (gpgme_sig_notation_t n = s->notations; n ; n = n->next) {
790 if (n->name && !strcmp(n->name, "rem@gnupg.org")) {
797 std::vector<std::string> UserID::remarks(std::vector<Key> keys, Error &err) const
799 std::vector<std::string> ret;
801 for (const auto &key: keys) {
802 const char *rem = remark(key, err);
819 static gpgme_key_sig_t find_signature(gpgme_user_id_t uid, unsigned int idx)
822 for (gpgme_key_sig_t s = uid->signatures ; s ; s = s->next, --idx) {
831 static gpgme_key_sig_t verify_signature(gpgme_user_id_t uid, gpgme_key_sig_t sig)
834 for (gpgme_key_sig_t s = uid->signatures ; s ; s = s->next) {
843 static int signature_index(gpgme_user_id_t uid, gpgme_key_sig_t sig)
847 for (gpgme_key_sig_t s = uid->signatures ; s ; s = s->next, ++i) {
856 UserID::Signature::Signature() : key(), uid(nullptr), sig(nullptr) {}
858 UserID::Signature::Signature(const shared_gpgme_key_t &k, gpgme_user_id_t u, unsigned int idx)
859 : key(k), uid(verify_uid(k, u)), sig(find_signature(uid, idx))
863 UserID::Signature::Signature(const shared_gpgme_key_t &k, gpgme_user_id_t u, gpgme_key_sig_t s)
864 : key(k), uid(verify_uid(k, u)), sig(verify_signature(uid, s))
868 bool UserID::Signature::operator<(const Signature &other)
870 // kept for binary compatibility
871 return static_cast<const UserID::Signature *>(this)->operator<(other);
874 bool UserID::Signature::operator<(const Signature &other) const
876 // based on cmp_signodes() in g10/keylist.c
878 // both signatures must belong to the same user ID
879 assert(uid == other.uid);
881 // self-signatures are ordered first
882 const char *primaryKeyId = parent().parent().keyID();
883 const bool thisIsSelfSignature = strcmp(signerKeyID(), primaryKeyId) == 0;
884 const bool otherIsSelfSignature = strcmp(other.signerKeyID(), primaryKeyId) == 0;
885 if (thisIsSelfSignature && !otherIsSelfSignature) {
888 if (otherIsSelfSignature && !thisIsSelfSignature) {
892 // then sort by signer key ID (which are or course the same for self-sigs)
893 const int keyIdComparison = strcmp(signerKeyID(), other.signerKeyID());
894 if (keyIdComparison < 0) {
897 if (keyIdComparison > 0) {
901 // followed by creation time
902 if (creationTime() < other.creationTime()) {
905 if (creationTime() > other.creationTime()) {
909 // followed by the class in a way that a rev comes first
910 if (certClass() < other.certClass()) {
913 if (certClass() > other.certClass()) {
917 // to make the sort stable we compare the indexes of the signatures as last resort
918 return signature_index(uid, sig) < signature_index(uid, other.sig);
921 UserID UserID::Signature::parent() const
923 return UserID(key, uid);
926 const char *UserID::Signature::signerKeyID() const
928 return sig ? sig->keyid : nullptr ;
931 const char *UserID::Signature::algorithmAsString() const
933 return gpgme_pubkey_algo_name(sig ? sig->pubkey_algo : (gpgme_pubkey_algo_t)0);
936 unsigned int UserID::Signature::algorithm() const
938 return sig ? sig->pubkey_algo : 0 ;
941 time_t UserID::Signature::creationTime() const
943 return static_cast<time_t>(sig ? sig->timestamp : 0);
946 time_t UserID::Signature::expirationTime() const
948 return static_cast<time_t>(sig ? sig->expires : 0);
951 bool UserID::Signature::neverExpires() const
953 return expirationTime() == time_t(0);
956 bool UserID::Signature::isRevokation() const
958 return sig && sig->revoked;
961 bool UserID::Signature::isInvalid() const
963 return sig && sig->invalid;
966 bool UserID::Signature::isExpired() const
968 return sig && sig->expired;
971 bool UserID::Signature::isExportable() const
973 return sig && sig->exportable;
976 const char *UserID::Signature::signerUserID() const
978 return sig ? sig->uid : nullptr ;
981 const char *UserID::Signature::signerName() const
983 return sig ? sig->name : nullptr ;
986 const char *UserID::Signature::signerEmail() const
988 return sig ? sig->email : nullptr ;
991 const char *UserID::Signature::signerComment() const
993 return sig ? sig->comment : nullptr ;
996 unsigned int UserID::Signature::certClass() const
998 return sig ? sig->sig_class : 0 ;
1001 UserID::Signature::Status UserID::Signature::status() const
1004 return GeneralError;
1007 switch (gpgme_err_code(sig->status)) {
1008 case GPG_ERR_NO_ERROR: return NoError;
1009 case GPG_ERR_SIG_EXPIRED: return SigExpired;
1010 case GPG_ERR_KEY_EXPIRED: return KeyExpired;
1011 case GPG_ERR_BAD_SIGNATURE: return BadSignature;
1012 case GPG_ERR_NO_PUBKEY: return NoPublicKey;
1014 case GPG_ERR_GENERAL: return GeneralError;
1018 std::string UserID::Signature::statusAsString() const
1021 return std::string();
1024 gpgme_strerror_r(sig->status, buf, sizeof buf);
1025 buf[ sizeof buf - 1 ] = '\0';
1026 return std::string(buf);
1029 GpgME::Notation UserID::Signature::notation(unsigned int idx) const
1032 return GpgME::Notation();
1034 for (gpgme_sig_notation_t nota = sig->notations ; nota ; nota = nota->next) {
1037 return GpgME::Notation(nota);
1041 return GpgME::Notation();
1044 unsigned int UserID::Signature::numNotations() const
1049 unsigned int count = 0;
1050 for (gpgme_sig_notation_t nota = sig->notations ; nota ; nota = nota->next) {
1052 ++count; // others are policy URLs...
1058 std::vector<Notation> UserID::Signature::notations() const
1061 return std::vector<GpgME::Notation>();
1063 std::vector<GpgME::Notation> v;
1064 v.reserve(numNotations());
1065 for (gpgme_sig_notation_t nota = sig->notations ; nota ; nota = nota->next) {
1067 v.push_back(GpgME::Notation(nota));
1073 const char *UserID::Signature::policyURL() const
1078 for (gpgme_sig_notation_t nota = sig->notations ; nota ; nota = nota->next) {
1086 bool UserID::Signature::isTrustSignature() const
1088 return sig && sig->trust_depth > 0;
1091 TrustSignatureTrust UserID::Signature::trustValue() const
1093 if (!sig || !isTrustSignature()) {
1094 return TrustSignatureTrust::None;
1096 return sig->trust_value >= 120 ? TrustSignatureTrust::Complete : TrustSignatureTrust::Partial;
1099 unsigned int UserID::Signature::trustDepth() const
1101 return sig ? sig->trust_depth : 0;
1104 const char *UserID::Signature::trustScope() const
1106 return sig ? sig->trust_scope : nullptr;
1109 std::string UserID::addrSpecFromString(const char *userid)
1112 return std::string();
1114 char *normalized = gpgme_addrspec_from_uid (userid);
1116 std::string ret(normalized);
1117 gpgme_free(normalized);
1120 return std::string();
1123 std::string UserID::addrSpec() const
1125 if (!uid || !uid->address) {
1126 return std::string();
1129 return uid->address;
1132 Error UserID::revoke()
1135 return Error::fromCode(GPG_ERR_GENERAL);
1137 auto ctx = Context::createForProtocol(parent().protocol());
1139 return Error::fromCode(GPG_ERR_INV_ENGINE);
1141 Error ret = ctx->revUid(key, id());
1146 static Key::Origin gpgme_origin_to_pp_origin (const unsigned int origin)
1149 case GPGME_KEYORG_KS:
1150 return Key::OriginKS;
1151 case GPGME_KEYORG_DANE:
1152 return Key::OriginDane;
1153 case GPGME_KEYORG_WKD:
1154 return Key::OriginWKD;
1155 case GPGME_KEYORG_URL:
1156 return Key::OriginURL;
1157 case GPGME_KEYORG_FILE:
1158 return Key::OriginFile;
1159 case GPGME_KEYORG_SELF:
1160 return Key::OriginSelf;
1161 case GPGME_KEYORG_OTHER:
1162 return Key::OriginOther;
1163 case GPGME_KEYORG_UNKNOWN:
1165 return Key::OriginUnknown;
1169 Key::Origin UserID::origin() const
1172 return Key::OriginUnknown;
1174 return gpgme_origin_to_pp_origin(uid->origin);
1177 time_t UserID::lastUpdate() const
1179 return static_cast<time_t>(uid ? uid->last_update : 0);
1182 Error Key::addUid(const char *uid)
1185 return Error::fromCode(GPG_ERR_GENERAL);
1187 auto ctx = Context::createForProtocol(protocol());
1189 return Error::fromCode(GPG_ERR_INV_ENGINE);
1191 Error ret = ctx->addUid(key, uid);
1196 Key::Origin Key::origin() const
1199 return OriginUnknown;
1201 return gpgme_origin_to_pp_origin(key->origin);
1204 time_t Key::lastUpdate() const
1206 return static_cast<time_t>(key ? key->last_update : 0);
1209 bool Key::isBad() const
1211 return isNull() || isRevoked() || isExpired() || isDisabled() || isInvalid();
1214 bool Subkey::isBad() const
1216 return isNull() || isRevoked() || isExpired() || isDisabled() || isInvalid();
1219 bool UserID::isBad() const
1221 return isNull() || isRevoked() || isInvalid();
1224 bool UserID::Signature::isBad() const
1226 return isNull() || isExpired() || isInvalid();
1229 std::ostream &operator<<(std::ostream &os, const UserID &uid)
1231 os << "GpgME::UserID(";
1232 if (!uid.isNull()) {
1233 os << "\n name: " << protect(uid.name())
1234 << "\n email: " << protect(uid.email())
1235 << "\n mbox: " << uid.addrSpec()
1236 << "\n comment: " << protect(uid.comment())
1237 << "\n validity: " << uid.validityAsString()
1238 << "\n revoked: " << uid.isRevoked()
1239 << "\n invalid: " << uid.isInvalid()
1240 << "\n numsigs: " << uid.numSignatures()
1241 << "\n origin: " << uid.origin()
1242 << "\n updated: " << uid.lastUpdate()
1243 << "\n tofuinfo:\n" << uid.tofuInfo();
1248 std::ostream &operator<<(std::ostream &os, const Subkey &subkey)
1250 os << "GpgME::Subkey(";
1251 if (!subkey.isNull()) {
1252 os << "\n fingerprint: " << protect(subkey.fingerprint())
1253 << "\n creationTime: " << subkey.creationTime()
1254 << "\n expirationTime:" << subkey.expirationTime()
1255 << "\n isRevoked: " << subkey.isRevoked()
1256 << "\n isExpired: " << subkey.isExpired()
1257 << "\n isInvalid: " << subkey.isRevoked()
1258 << "\n isDisabled: " << subkey.isInvalid()
1259 << "\n canSign: " << subkey.canSign()
1260 << "\n canEncrypt: " << subkey.canEncrypt()
1261 << "\n canCertify: " << subkey.canCertify()
1262 << "\n canAuth: " << subkey.canAuthenticate();
1267 std::ostream &operator<<(std::ostream &os, const Key &key)
1269 os << "GpgME::Key(";
1270 if (!key.isNull()) {
1271 os << "\n protocol: " << protect(key.protocolAsString())
1272 << "\n ownertrust: " << key.ownerTrustAsString()
1273 << "\n issuer: " << protect(key.issuerName())
1274 << "\n fingerprint:" << protect(key.primaryFingerprint())
1275 << "\n listmode: " << key.keyListMode()
1276 << "\n canSign: " << key.canReallySign()
1277 << "\n canEncrypt: " << key.canEncrypt()
1278 << "\n canCertify: " << key.canCertify()
1279 << "\n canAuth: " << key.canAuthenticate()
1280 << "\n origin: " << key.origin()
1281 << "\n updated: " << key.lastUpdate()
1283 const std::vector<UserID> uids = key.userIDs();
1284 std::copy(uids.begin(), uids.end(),
1285 std::ostream_iterator<UserID>(os, "\n"));
1286 const std::vector<Subkey> subkeys = key.subkeys();
1287 std::copy(subkeys.begin(), subkeys.end(),
1288 std::ostream_iterator<Subkey>(os, "\n"));
1293 } // namespace GpgME