The Web of Trust (WoT) is one of the advanced topics in the OpenPGP cryptography. Its primary goal is to provide custom authentication of keys, allowing everyone to participate in a decentralized certificate authority.
The implementation of the Web of Trust has been revised in version 2.6.4 of DidiSoft OpenPGP Library for Java and this article reflects this updated model.
Table of Contents
1. Quick introduction to the WoT
2. Customizing the WoT
2.1. trust inheritance
2.2. marginals needed
3. Signing a key
4. Signing as a trusted introducer
5. Setting full trust to a key
6. Setting marginal trust
7. Current limitations
8. WoT in versions prior to 2.6.4
9. External sources
1. Quick introduction to the WoT
The Web of Trust was first introduced by Phil Zimmermann in 1992 in PGP version 2.0.
The OpenPGP specification defines the trust amount as a value ranging from 0-255. For practical reasons we have adopted only the constants below:
// fully trusted com.didisoft.pgp.TrustLevel.TRUSTED = 120 // partially trusted com.didisoft.pgp.TrustLevel.MARGINAL = 60 // do not trust com.didisoft.pgp.TrustLevel.NONE |
An OpenPGP key is considered trusted (can be also met as “valid” in other sources) if:
- it is signed by a private key contained in our KeyStore (this applies to the private keys as they are self signed)
- we have marked it trusted in our key storage
- it has been signed by a key which we consider trusted
- it has been signed by a number of keys which we consider marginally trusted
2. Customizing the Web of Trust
There are two settings that we can use to customize the Web of Trust implementation in the library: trust depth and number of marginals needed.
2.1 Trust depth inheritance
Let’s suppose that we have the following keys and signature relationship:
A -> B -> C ->D
If we mark key A as fully trusted and we set the trust depth to be:
KeyStore ks = new KeyStore(); ks.setMaxTrustDepth(3); |
then key D won’t be trusted, as the number of hops from a fully trusted key exceeds the maximum trust depth.
2.2 Number of marginals needed
The number of signatures from keys that we trust marginally, needed to consider given key as trusted can be customized with:
KeyStore ks = new KeyStore(); ks.setMarginalsNeeded(3); |
3. Signing a key
With the code snippet below we sign a partner’s public key with our private key, and indicate this way that we consider it to be a trusted key.
If afterwards we export the key and send it to a third party, they will also consider it trusted if they trust our key.
KeyStore ks = ... ks.signPublicKey("partner Id", "my Key Id", "my Key password"); |
4. Signing as a trusted introducer
We can also sign a key as a trusted introducer. Let’s suppose we have the following signature relationship:
(Our key) -> A -> B
If we sign key A as a trusted introducer then we automatically trust key B as well:
KeyStore ks = ... ks.signPublicKeyAsTrustedIntroducer("partner Id", "my Key Id", "my Key password"); |
When the maximum trust depth is larger than 1 it has the same effect as the plain signing. But if we set
KeyStore ks = new KeyStore(); ks.setMaxTrustDepthCheck(1); |
Then key B will NOT be trusted if key A is only signed. It has to be signed as a trusted introducer explicitly.
5. Setting full trust to a key
By setting the trust on a key we mark the key as trusted, but that modification is stored only in the containing KeyStore instance. If the key is exported afterwards and sent to a third party, they won’t know of this.
KeyStore ks = ... ks.setTrust("partner Id", com.didisoft.pgp.TrustLevel.TRUSTED); |
As with the signing of a key, if the maximum trust depth is greater than 1 then this key introduces the trust to all keys that have signatures from it (maximum trust depth hops below).
6. Setting marginal trust to a key
The marginal trust of a key indicates that we trust partially that key. But if a few such keys have signed a particular key we can fully trust that key, just like a merchant asking for two forms of ID.
KeyStore ks = ... ks.setTrust("partner Id", com.didisoft.pgp.TrustLevel.MARGINAL); |
If we have the following signature relationship:
A -> X, B -> X, C -> X
and A, B, and C are marginally trusted in our KeyStore then key X is considered fully trusted.
7. Current limitations of the library
The Web of Trust model provided by OpenPGP provides great space for building sophisticated authentication solutions. Below are mentioned some of the current limitations in our implementation:
– Trusted introducer signatures are hard coded only for 1 level down (i.e. apply only for keys that have a signature from the introducer).
– One signature from a trusted key is needed for a key to be treated as trusted (in GnuPG for example this can be customized, the default there is also 1).
8. Web of Trust in versions prior to 2.6.4
The API methods for implementing Web of Trust was first introduced in version 2.5.8 of the library.
Until version 2.6.4 a key is considered trusted if:
- it is signed by a private key contained in our KeyStore (this applies to the private keys as they are self signed)
- we have marked it trusted in our key storage
- it has been signed by a key that we have signed as a trusted introducer
There was no practical application of keys with marginal trust and no nested inheritance of trust.
9. External sources
External sources that you may find interesting and are related to the OpenPGP Web of Trust concept are listed below:
http://en.wikipedia.org/wiki/Web_of_trust
http://www.pgpi.org/doc/pgpintro/#p17
http://www.gnupg.org/gph/en/manual.html#AEN335
http://penguincopter.blogspot.com/2011/10/web-of-trust.html
Summary
In this chapter we have tried to introduce the API provided by OpenPGP Library for Java for implementing the Web of Trust in your applications. Probably you will find some of the explanations confusing, so please don’t hesitate to contact our technical support if you have any additional questions.
List of methods used
KeyStore.signPublicKey | signs a third party public key with our private key |
KeyStore.signPublicKeyAsTrustedIntroducer | signs a third party public key as a trust introducer |
KeyStore.setTrust | sets our private trust amount in a third party key |
KeyStore.isTrusted | returns should a third party key be considered trusted |
KeyStore.setMaxTrustDepth | sets the maximum levels of trust inheritance |
KeyStore.setMarginalsNeeded | sets how many signatures from marginally trusted keys are needed in order a key to be considered trusted |