1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/KeyRing.cc
18 #include <zypp/TmpPath.h>
19 #include <zypp/ZYppFactory.h>
20 #include <zypp/ZYpp.h>
22 #include <zypp/base/LogTools.h>
23 #include <zypp/base/IOStream.h>
24 #include <zypp/base/String.h>
25 #include <zypp/base/Regex.h>
26 #include <zypp/base/Gettext.h>
27 #include <zypp/base/WatchFile.h>
28 #include <zypp/PathInfo.h>
29 #include <zypp/KeyRing.h>
30 #include <zypp/ExternalProgram.h>
31 #include <zypp/TmpPath.h>
32 #include <zypp/ZYppCallbacks.h> // JobReport::instance
33 #include <zypp/KeyManager.h>
37 #undef ZYPP_BASE_LOGGER_LOGGROUP
38 #define ZYPP_BASE_LOGGER_LOGGROUP "zypp::KeyRing"
40 ///////////////////////////////////////////////////////////////////
42 { /////////////////////////////////////////////////////////////////
44 IMPL_PTR_TYPE(KeyRing);
48 KeyRing::DefaultAccept _keyRingDefaultAccept( KeyRing::ACCEPT_NOTHING );
51 KeyRing::DefaultAccept KeyRing::defaultAccept()
52 { return _keyRingDefaultAccept; }
54 void KeyRing::setDefaultAccept( DefaultAccept value_r )
56 MIL << "Set new KeyRing::DefaultAccept: " << value_r << endl;
57 _keyRingDefaultAccept = value_r;
60 void KeyRingReport::infoVerify( const std::string & file_r, const PublicKeyData & keyData_r, const KeyContext & keycontext )
63 bool KeyRingReport::askUserToAcceptUnsignedFile( const std::string & file, const KeyContext & keycontext )
64 { return _keyRingDefaultAccept.testFlag( KeyRing::ACCEPT_UNSIGNED_FILE ); }
66 KeyRingReport::KeyTrust
67 KeyRingReport::askUserToAcceptKey( const PublicKey & key, const KeyContext & keycontext )
69 if ( _keyRingDefaultAccept.testFlag( KeyRing::TRUST_KEY_TEMPORARILY ) )
70 return KEY_TRUST_TEMPORARILY;
71 if ( _keyRingDefaultAccept.testFlag( KeyRing::TRUST_AND_IMPORT_KEY ) )
72 return KEY_TRUST_AND_IMPORT;
73 return KEY_DONT_TRUST;
76 bool KeyRingReport::askUserToAcceptUnknownKey( const std::string & file, const std::string & id, const KeyContext & keycontext )
77 { return _keyRingDefaultAccept.testFlag( KeyRing::ACCEPT_UNKNOWNKEY ); }
79 bool KeyRingReport::askUserToAcceptVerificationFailed( const std::string & file, const PublicKey & key, const KeyContext & keycontext )
80 { return _keyRingDefaultAccept.testFlag( KeyRing::ACCEPT_VERIFICATION_FAILED ); }
82 bool KeyRingReport::askUserToAcceptPackageKey(const PublicKey &key_r, const KeyContext &keycontext_r)
84 UserData data(ACCEPT_PACKAGE_KEY_REQUEST);
85 data.set("PublicKey", key_r);
86 data.set("KeyContext", keycontext_r);
89 if ( data.hasvalue("TrustKey") )
90 return data.get<bool>("TrustKey");
94 void KeyRingReport::reportNonImportedKeys(const std::set<Edition> &keys_r)
96 UserData data(KEYS_NOT_IMPORTED_REPORT);
97 data.set("Keys", keys_r);
103 ///////////////////////////////////////////////////////////////////
104 /// \class CachedPublicKeyData
105 /// \brief Functor returning the keyrings data (cached).
107 /// const std::list<PublicKeyData> & cachedPublicKeyData( const Pathname & keyring );
109 ///////////////////////////////////////////////////////////////////
110 struct CachedPublicKeyData : private base::NonCopyable
112 const std::list<PublicKeyData> & operator()( const Pathname & keyring_r ) const
113 { return getData( keyring_r ); }
115 void setDirty( const Pathname & keyring_r )
116 { _cacheMap[keyring_r].setDirty(); }
129 void assertCache( const Pathname & keyring_r )
131 // .kbx since gpg2-2.1
133 _keyringK.reset( new WatchFile( keyring_r/"pubring.kbx", WatchFile::NO_INIT ) );
135 _keyringP.reset( new WatchFile( keyring_r/"pubring.gpg", WatchFile::NO_INIT ) );
138 bool hasChanged() const
140 bool k = _keyringK->hasChanged(); // be sure both files are checked
141 bool p = _keyringP->hasChanged();
145 std::list<PublicKeyData> _data;
148 scoped_ptr<WatchFile> _keyringK;
149 scoped_ptr<WatchFile> _keyringP;
152 typedef std::map<Pathname,Cache> CacheMap;
154 const std::list<PublicKeyData> & getData( const Pathname & keyring_r ) const
156 Cache & cache( _cacheMap[keyring_r] );
157 // init new cache entry
158 cache.assertCache( keyring_r );
159 return getData( keyring_r, cache );
162 const std::list<PublicKeyData> & getData( const Pathname & keyring_r, Cache & cache_r ) const
164 if ( cache_r.hasChanged() ) {
165 cache_r._data = KeyManagerCtx::createForOpenPGP( keyring_r ).listKeys();
166 MIL << "Found keys: " << cache_r._data << endl;
168 return cache_r._data;
171 mutable CacheMap _cacheMap;
173 ///////////////////////////////////////////////////////////////////
176 ///////////////////////////////////////////////////////////////////
178 // CLASS NAME : KeyRing::Impl
180 /** KeyRing implementation. */
183 Impl( const Pathname & baseTmpDir )
184 : _trusted_tmp_dir( baseTmpDir, "zypp-trusted-kr" )
185 , _general_tmp_dir( baseTmpDir, "zypp-general-kr" )
186 , _base_dir( baseTmpDir )
188 MIL << "Current KeyRing::DefaultAccept: " << _keyRingDefaultAccept << endl;
191 void importKey( const PublicKey & key, bool trusted = false );
192 void multiKeyImport( const Pathname & keyfile_r, bool trusted_r = false );
193 void deleteKey( const std::string & id, bool trusted );
195 std::string readSignatureKeyId( const Pathname & signature );
197 bool isKeyTrusted( const std::string & id )
198 { return bool(publicKeyExists( id, trustedKeyRing() )); }
199 bool isKeyKnown( const std::string & id )
200 { return publicKeyExists( id, trustedKeyRing() ) || publicKeyExists( id, generalKeyRing() ); }
202 std::list<PublicKey> trustedPublicKeys()
203 { return publicKeys( trustedKeyRing() ); }
204 std::list<PublicKey> publicKeys()
205 { return publicKeys( generalKeyRing() ); }
207 const std::list<PublicKeyData> & trustedPublicKeyData()
208 { return publicKeyData( trustedKeyRing() ); }
209 const std::list<PublicKeyData> & publicKeyData()
210 { return publicKeyData( generalKeyRing() ); }
212 void dumpPublicKey( const std::string & id, bool trusted, std::ostream & stream )
213 { dumpPublicKey( id, ( trusted ? trustedKeyRing() : generalKeyRing() ), stream ); }
215 PublicKey exportPublicKey( const PublicKeyData & keyData )
216 { return exportKey( keyData, generalKeyRing() ); }
217 PublicKey exportTrustedPublicKey( const PublicKeyData & keyData )
218 { return exportKey( keyData, trustedKeyRing() ); }
220 bool verifyFileSignatureWorkflow( const Pathname & file, const std::string & filedesc, const Pathname & signature, bool & sigValid_r, const KeyContext & keycontext = KeyContext());
222 bool verifyFileSignature( const Pathname & file, const Pathname & signature )
223 { return verifyFile( file, signature, generalKeyRing() ); }
224 bool verifyFileTrustedSignature( const Pathname & file, const Pathname & signature )
225 { return verifyFile( file, signature, trustedKeyRing() ); }
227 PublicKeyData trustedPublicKeyExists( const std::string & id )
228 { return publicKeyExists(id, trustedKeyRing());}
230 bool provideAndImportKeyFromRepositoryWorkflow (const std::string &id_r , const RepoInfo &info_r );
233 bool verifyFile( const Pathname & file, const Pathname & signature, const Pathname & keyring );
234 void importKey( const Pathname & keyfile, const Pathname & keyring );
236 PublicKey exportKey( const std::string & id, const Pathname & keyring );
237 PublicKey exportKey( const PublicKeyData & keyData, const Pathname & keyring );
238 PublicKey exportKey( const PublicKey & key, const Pathname & keyring )
239 { return exportKey( key.keyData(), keyring ); }
241 void dumpPublicKey( const std::string & id, const Pathname & keyring, std::ostream & stream );
242 filesystem::TmpFile dumpPublicKeyToTmp( const std::string & id, const Pathname & keyring );
244 void deleteKey( const std::string & id, const Pathname & keyring );
246 std::list<PublicKey> publicKeys( const Pathname & keyring);
247 const std::list<PublicKeyData> & publicKeyData( const Pathname & keyring )
248 { return cachedPublicKeyData( keyring ); }
250 /** Get \ref PublicKeyData for ID (\c false if ID is not found). */
251 PublicKeyData publicKeyExists( const std::string & id, const Pathname & keyring );
253 const Pathname generalKeyRing() const
254 { return _general_tmp_dir.path(); }
255 const Pathname trustedKeyRing() const
256 { return _trusted_tmp_dir.path(); }
258 // Used for trusted and untrusted keyrings
259 filesystem::TmpDir _trusted_tmp_dir;
260 filesystem::TmpDir _general_tmp_dir;
264 /** Functor returning the keyrings data (cached).
266 * const std::list<PublicKeyData> & cachedPublicKeyData( const Pathname & keyring );
269 CachedPublicKeyData cachedPublicKeyData;
271 ///////////////////////////////////////////////////////////////////
275 /// Handle signal emission from within KeyRing::Impl::importKey
276 struct ImportKeyCBHelper
278 void operator()( const PublicKey & key_r )
281 _rpmdbEmitSignal->trustedKeyAdded( key_r );
282 _emitSignal->trustedKeyAdded( key_r );
284 catch ( const Exception & excp )
286 ERR << "Could not import key into rpmdb: " << excp << endl;
287 // TODO: JobReport as hotfix for bsc#1057188; should bubble up and go through some callback
288 JobReport::error( excp.asUserHistory() );
293 callback::SendReport<target::rpm::KeyRingSignals> _rpmdbEmitSignal;
294 callback::SendReport<KeyRingSignals> _emitSignal;
299 void KeyRing::Impl::importKey( const PublicKey & key, bool trusted )
301 importKey( key.path(), trusted ? trustedKeyRing() : generalKeyRing() );
302 MIL << "Imported key " << key << " to " << (trusted ? "trustedKeyRing" : "generalKeyRing" ) << endl;
306 ImportKeyCBHelper emitSignal;
307 if ( key.hiddenKeys().empty() )
313 // multiple keys: Export individual keys ascii armored to import in rpmdb
314 emitSignal( exportKey( key, trustedKeyRing() ) );
315 for ( const PublicKeyData & hkey : key.hiddenKeys() )
316 emitSignal( exportKey( hkey, trustedKeyRing() ) );
321 void KeyRing::Impl::multiKeyImport( const Pathname & keyfile_r, bool trusted_r )
323 importKey( keyfile_r, trusted_r ? trustedKeyRing() : generalKeyRing() );
326 void KeyRing::Impl::deleteKey( const std::string & id, bool trusted )
328 PublicKeyData keyDataToDel( publicKeyExists( id, trusted ? trustedKeyRing() : generalKeyRing() ) );
329 if ( ! keyDataToDel )
331 WAR << "Key to delete [" << id << "] is not in " << (trusted ? "trustedKeyRing" : "generalKeyRing" ) << endl;
334 deleteKey( id, trusted ? trustedKeyRing() : generalKeyRing() );
335 MIL << "Deleted key [" << id << "] from " << (trusted ? "trustedKeyRing" : "generalKeyRing" ) << endl;
339 PublicKey key( keyDataToDel );
341 callback::SendReport<target::rpm::KeyRingSignals> rpmdbEmitSignal;
342 rpmdbEmitSignal->trustedKeyRemoved( key );
344 callback::SendReport<KeyRingSignals> emitSignal;
345 emitSignal->trustedKeyRemoved( key );
347 catch ( const Exception & excp )
349 ERR << "Could not delete key from rpmmdb: " << excp << endl;
350 // TODO: JobReport as hotfix for bsc#1057188; should bubble up and go through some callback
351 JobReport::error( excp.asUserHistory() );
355 PublicKeyData KeyRing::Impl::publicKeyExists( const std::string & id, const Pathname & keyring )
358 for ( const PublicKeyData & key : publicKeyData( keyring ) )
360 if ( key.providesKey( id ) )
366 MIL << (ret ? "Found" : "No") << " key [" << id << "] in keyring " << keyring << endl;
370 PublicKey KeyRing::Impl::exportKey( const PublicKeyData & keyData, const Pathname & keyring )
372 return PublicKey( dumpPublicKeyToTmp( keyData.id(), keyring ), keyData );
375 PublicKey KeyRing::Impl::exportKey( const std::string & id, const Pathname & keyring )
377 PublicKeyData keyData( publicKeyExists( id, keyring ) );
379 return PublicKey( dumpPublicKeyToTmp( keyData.id(), keyring ), keyData );
381 // Here: key not found
382 WAR << "No key [" << id << "] to export from " << keyring << endl;
387 void KeyRing::Impl::dumpPublicKey( const std::string & id, const Pathname & keyring, std::ostream & stream )
389 KeyManagerCtx::createForOpenPGP( keyring ).exportKey(id, stream);
392 filesystem::TmpFile KeyRing::Impl::dumpPublicKeyToTmp( const std::string & id, const Pathname & keyring )
394 filesystem::TmpFile tmpFile( _base_dir, "pubkey-"+id+"-" );
395 MIL << "Going to export key [" << id << "] from " << keyring << " to " << tmpFile.path() << endl;
397 std::ofstream os( tmpFile.path().c_str() );
398 dumpPublicKey( id, keyring, os );
403 bool KeyRing::Impl::verifyFileSignatureWorkflow( const Pathname & file, const std::string & filedesc, const Pathname & signature, bool & sigValid_r, const KeyContext & context )
405 sigValid_r = false; // set true if signature is actually successfully validated!
407 callback::SendReport<KeyRingReport> report;
408 MIL << "Going to verify signature for " << filedesc << " ( " << file << " ) with " << signature << endl;
410 // if signature does not exists, ask user if he wants to accept unsigned file.
411 if( signature.empty() || (!PathInfo( signature ).isExist()) )
413 bool res = report->askUserToAcceptUnsignedFile( filedesc, context );
414 MIL << "askUserToAcceptUnsignedFile: " << res << endl;
418 // get the id of the signature (it might be a subkey id!)
419 std::string id = readSignatureKeyId( signature );
421 PublicKeyData foundKey;
422 Pathname whichKeyring;
426 // does key exists in trusted keyring
427 PublicKeyData trustedKeyData( publicKeyExists( id, trustedKeyRing() ) );
428 if ( trustedKeyData )
430 MIL << "Key is trusted: " << trustedKeyData << endl;
432 // lets look if there is an updated key in the
434 PublicKeyData generalKeyData( publicKeyExists( id, generalKeyRing() ) );
435 if ( generalKeyData )
437 // bnc #393160: Comment #30: Compare at least the fingerprint
438 // in case an attacker created a key the the same id.
440 // FIXME: bsc#1008325: For keys using subkeys, we'd actually need
441 // to compare the subkey sets, to tell whether a key was updated.
442 // because created() remains unchanged if the primary key is not touched.
443 // For now we wait until a new subkey signs the data and treat it as a
444 // new key (else part below).
445 if ( trustedKeyData.fingerprint() == generalKeyData.fingerprint()
446 && trustedKeyData.created() < generalKeyData.created() )
448 MIL << "Key was updated. Saving new version into trusted keyring: " << generalKeyData << endl;
449 importKey( exportKey( generalKeyData, generalKeyRing() ), true );
450 trustedKeyData = publicKeyExists( id, trustedKeyRing() ); // re-read: invalidated by import?
454 foundKey = trustedKeyData;
455 whichKeyring = trustedKeyRing();
459 PublicKeyData generalKeyData( publicKeyExists( id, generalKeyRing() ) );
460 if ( generalKeyData )
462 PublicKey key( exportKey( generalKeyData, generalKeyRing() ) );
463 MIL << "Key [" << id << "] " << key.name() << " is not trusted" << endl;
465 // ok the key is not trusted, ask the user to trust it or not
466 KeyRingReport::KeyTrust reply = report->askUserToAcceptKey( key, context );
467 if ( reply == KeyRingReport::KEY_TRUST_TEMPORARILY ||
468 reply == KeyRingReport::KEY_TRUST_AND_IMPORT )
470 MIL << "User wants to trust key [" << id << "] " << key.name() << endl;
472 if ( reply == KeyRingReport::KEY_TRUST_AND_IMPORT )
474 MIL << "User wants to import key [" << id << "] " << key.name() << endl;
475 importKey( key, true );
476 whichKeyring = trustedKeyRing();
479 whichKeyring = generalKeyRing();
481 foundKey = generalKeyData;
485 MIL << "User does not want to trust key [" << id << "] " << key.name() << endl;
489 else if ( ! context.empty() )
491 // try to find the key in the repository info
492 if ( provideAndImportKeyFromRepositoryWorkflow( id, context.repoInfo() ) ) {
493 whichKeyring = trustedKeyRing();
494 foundKey = PublicKeyData( publicKeyExists( id, trustedKeyRing() ) );
501 // it exists, is trusted, does it validate?
502 report->infoVerify( filedesc, foundKey, context );
503 if ( verifyFile( file, signature, whichKeyring ) )
505 return (sigValid_r=true); // signature is actually successfully validated!
509 bool res = report->askUserToAcceptVerificationFailed( filedesc, exportKey( foundKey, whichKeyring ), context );
510 MIL << "askUserToAcceptVerificationFailed: " << res << endl;
514 // signed with an unknown key...
515 MIL << "File [" << file << "] ( " << filedesc << " ) signed with unknown key [" << id << "]" << endl;
516 bool res = report->askUserToAcceptUnknownKey( filedesc, id, context );
517 MIL << "askUserToAcceptUnknownKey: " << res << endl;
524 bool KeyRing::Impl::provideAndImportKeyFromRepositoryWorkflow(const std::string &id_r, const RepoInfo &info_r)
529 const ZConfig &conf = ZConfig::instance();
530 Pathname cacheDir = conf.repoManagerRoot() / conf.pubkeyCachePath();
532 Pathname myKey = info_r.provideKey( id_r, cacheDir );
534 // if we did not find any keys, there is no point in checking again, break
537 callback::SendReport<KeyRingReport> report;
541 key = PublicKey( myKey );
542 } catch ( const Exception &e ) {
547 if ( !key.isValid() ) {
548 ERR << "Key [" << id_r << "] from cache: " << cacheDir << " is not valid" << endl;
552 MIL << "Key [" << id_r << "] " << key.name() << " loaded from cache" << endl;
555 context.setRepoInfo( info_r );
556 if ( ! report->askUserToAcceptPackageKey( key, context ) ) {
560 MIL << "User wants to import key [" << id_r << "] " << key.name() << " from cache" << endl;
562 importKey( key, true );
563 } catch ( const KeyRingException &e ) {
565 ERR << "Failed to import key: "<<id_r;
572 std::list<PublicKey> KeyRing::Impl::publicKeys( const Pathname & keyring )
574 const std::list<PublicKeyData> & keys( publicKeyData( keyring ) );
575 std::list<PublicKey> ret;
577 for_( it, keys.begin(), keys.end() )
579 PublicKey key( exportKey( *it, keyring ) );
580 ret.push_back( key );
581 MIL << "Found key " << key << endl;
586 void KeyRing::Impl::importKey( const Pathname & keyfile, const Pathname & keyring )
588 if ( ! PathInfo( keyfile ).isExist() )
589 // TranslatorExplanation first %s is key name, second is keyring name
590 ZYPP_THROW(KeyRingException( str::Format(_("Tried to import not existent key %s into keyring %s"))
592 % keyring.asString() ));
594 cachedPublicKeyData.setDirty( keyring );
595 if ( ! KeyManagerCtx::createForOpenPGP( keyring ).importKey( keyfile ) )
596 ZYPP_THROW(KeyRingException(_("Failed to import key.")));
599 void KeyRing::Impl::deleteKey( const std::string & id, const Pathname & keyring )
601 cachedPublicKeyData.setDirty( keyring );
602 if ( ! KeyManagerCtx::createForOpenPGP( keyring ).deleteKey( id ) )
603 ZYPP_THROW(KeyRingException(_("Failed to delete key.")));
606 std::string KeyRing::Impl::readSignatureKeyId( const Pathname & signature )
608 if ( ! PathInfo( signature ).isFile() )
609 ZYPP_THROW(KeyRingException( str::Format(_("Signature file %s not found")) % signature.asString() ));
611 MIL << "Determining key id of signature " << signature << endl;
613 std::list<std::string> fprs = KeyManagerCtx::createForOpenPGP().readSignatureFingerprints( signature );
614 if ( ! fprs.empty() ) {
615 std::string &id = fprs.back();
616 MIL << "Determined key id [" << id << "] for signature " << signature << endl;
619 return std::string();
622 bool KeyRing::Impl::verifyFile( const Pathname & file, const Pathname & signature, const Pathname & keyring )
624 return KeyManagerCtx::createForOpenPGP( keyring ).verify( file, signature );
627 ///////////////////////////////////////////////////////////////////
629 ///////////////////////////////////////////////////////////////////
631 // CLASS NAME : KeyRing
633 ///////////////////////////////////////////////////////////////////
635 KeyRing::KeyRing( const Pathname & baseTmpDir )
636 : _pimpl( new Impl( baseTmpDir ) )
643 void KeyRing::importKey( const PublicKey & key, bool trusted )
644 { _pimpl->importKey( key, trusted ); }
646 void KeyRing::multiKeyImport( const Pathname & keyfile_r, bool trusted_r )
647 { _pimpl->multiKeyImport( keyfile_r, trusted_r ); }
649 std::string KeyRing::readSignatureKeyId( const Pathname & signature )
650 { return _pimpl->readSignatureKeyId( signature ); }
652 void KeyRing::deleteKey( const std::string & id, bool trusted )
653 { _pimpl->deleteKey( id, trusted ); }
655 std::list<PublicKey> KeyRing::publicKeys()
656 { return _pimpl->publicKeys(); }
658 std:: list<PublicKey> KeyRing::trustedPublicKeys()
659 { return _pimpl->trustedPublicKeys(); }
661 std::list<PublicKeyData> KeyRing::publicKeyData()
662 { return _pimpl->publicKeyData(); }
664 std::list<PublicKeyData> KeyRing::trustedPublicKeyData()
665 { return _pimpl->trustedPublicKeyData(); }
667 PublicKeyData KeyRing::trustedPublicKeyData(const std::string &id_r)
668 { return _pimpl->trustedPublicKeyExists( id_r ); }
670 bool KeyRing::verifyFileSignatureWorkflow( const Pathname & file, const std::string & filedesc, const Pathname & signature, bool & sigValid_r, const KeyContext & keycontext )
671 { return _pimpl->verifyFileSignatureWorkflow( file, filedesc, signature, sigValid_r, keycontext ); }
673 bool KeyRing::verifyFileSignatureWorkflow( const Pathname & file, const std::string filedesc, const Pathname & signature, const KeyContext & keycontext )
674 { bool unused; return _pimpl->verifyFileSignatureWorkflow( file, filedesc, signature, unused, keycontext ); }
676 bool KeyRing::verifyFileSignature( const Pathname & file, const Pathname & signature )
677 { return _pimpl->verifyFileSignature( file, signature ); }
679 bool KeyRing::verifyFileTrustedSignature( const Pathname & file, const Pathname & signature )
680 { return _pimpl->verifyFileTrustedSignature( file, signature ); }
682 bool KeyRing::provideAndImportKeyFromRepositoryWorkflow(const std::string &id, const RepoInfo &info)
684 return _pimpl->provideAndImportKeyFromRepositoryWorkflow( id, info );
687 void KeyRing::dumpPublicKey( const std::string & id, bool trusted, std::ostream & stream )
688 { _pimpl->dumpPublicKey( id, trusted, stream ); }
690 PublicKey KeyRing::exportPublicKey( const PublicKeyData & keyData )
691 { return _pimpl->exportPublicKey( keyData ); }
693 PublicKey KeyRing::exportTrustedPublicKey( const PublicKeyData & keyData )
694 { return _pimpl->exportTrustedPublicKey( keyData ); }
696 bool KeyRing::isKeyTrusted( const std::string & id )
697 { return _pimpl->isKeyTrusted( id ); }
699 bool KeyRing::isKeyKnown( const std::string & id )
700 { return _pimpl->isKeyKnown( id ); }
702 /////////////////////////////////////////////////////////////////
704 ///////////////////////////////////////////////////////////////////