use of org.bouncycastle.openpgp.PGPPublicKey in project gerrit by GerritCodeReview.
the class PostGpgKeys method toJson.
private Map<String, GpgKeyInfo> toJson(Collection<PGPPublicKeyRing> keys, Set<Fingerprint> deleted, PublicKeyStore store, IdentifiedUser user) throws IOException {
// Unlike when storing keys, include web-of-trust checks when producing
// result JSON, so the user at least knows of any issues.
PublicKeyChecker checker = checkerFactory.create(user, store);
Map<String, GpgKeyInfo> infos = Maps.newHashMapWithExpectedSize(keys.size() + deleted.size());
for (PGPPublicKeyRing keyRing : keys) {
PGPPublicKey key = keyRing.getPublicKey();
CheckResult result = checker.check(key);
GpgKeyInfo info = GpgKeys.toJson(key, result);
infos.put(info.id, info);
info.id = null;
}
for (Fingerprint fp : deleted) {
infos.put(keyIdToString(fp.getId()), new GpgKeyInfo());
}
return infos;
}
use of org.bouncycastle.openpgp.PGPPublicKey in project gerrit by GerritCodeReview.
the class GerritPublicKeyCheckerTest method keyLaterInTrustChainMissingUserId.
@Test
public void keyLaterInTrustChainMissingUserId() throws Exception {
// A---Bx
// \
// \---C
//
// The server ultimately trusts B.
// C signed A's key but is not in the store.
TestKey keyA = add(keyA(), user);
PGPPublicKeyRing keyRingB = keyB().getPublicKeyRing();
PGPPublicKey keyB = keyRingB.getPublicKey();
keyB = PGPPublicKey.removeCertification(keyB, (String) keyB.getUserIDs().next());
keyRingB = PGPPublicKeyRing.insertPublicKey(keyRingB, keyB);
add(keyRingB, addUser("userB"));
PublicKeyChecker checkerA = checkerFactory.create(user, store);
assertProblems(checkerA.check(keyA.getPublicKey()), Status.OK, "No path to a trusted key", "Certification by " + keyToString(keyB) + " is valid, but key is not trusted", "Key D24FE467 used for certification is not in store");
}
use of org.bouncycastle.openpgp.PGPPublicKey in project gerrit by GerritCodeReview.
the class PublicKeyStore method add.
/**
* Add a public key to the store.
*
* <p>Multiple calls may be made to buffer keys in memory, and they are not saved until {@link
* #save(CommitBuilder)} is called.
*
* @param keyRing a key ring containing exactly one public master key.
*/
public void add(PGPPublicKeyRing keyRing) {
int numMaster = 0;
for (PGPPublicKey key : keyRing) {
if (key.isMasterKey()) {
numMaster++;
}
}
// here. The alternative is insane but harmless.
if (numMaster != 1) {
throw new IllegalArgumentException("Exactly 1 master key is required, found " + numMaster);
}
Fingerprint fp = new Fingerprint(keyRing.getPublicKey().getFingerprint());
toAdd.put(fp, keyRing);
toRemove.remove(fp);
}
use of org.bouncycastle.openpgp.PGPPublicKey in project gerrit by GerritCodeReview.
the class PushCertificateChecker method combine.
private static Result combine(Result sigResult, List<CheckResult> results) {
// Combine results:
// - If any input result is BAD, the final result is bad.
// - If sigResult is TRUSTED and no other result is BAD, the final result
// is TRUSTED.
// - Otherwise, the result is OK.
List<String> problems = new ArrayList<>();
boolean bad = false;
for (CheckResult result : results) {
problems.addAll(result.getProblems());
bad |= result.getStatus() == BAD;
}
Status status = bad ? BAD : OK;
PGPPublicKey key;
if (sigResult != null) {
key = sigResult.getPublicKey();
CheckResult cr = sigResult.getCheckResult();
problems.addAll(cr.getProblems());
if (cr.getStatus() == BAD) {
status = BAD;
} else if (!bad && cr.getStatus() == TRUSTED) {
status = TRUSTED;
}
} else {
key = null;
}
return new Result(key, CheckResult.create(status, problems));
}
use of org.bouncycastle.openpgp.PGPPublicKey in project gerrit by GerritCodeReview.
the class PublicKeyChecker method checkWebOfTrust.
private CheckResult checkWebOfTrust(PGPPublicKey key, PublicKeyStore store, int depth, Set<Fingerprint> seen) {
if (trusted == null) {
// Trust checking not configured, server trusts all OK keys.
return CheckResult.trusted();
}
Fingerprint fp = new Fingerprint(key.getFingerprint());
if (seen.contains(fp)) {
return CheckResult.ok("Key is trusted in a cycle");
}
seen.add(fp);
Fingerprint trustedFp = trusted.get(key.getKeyID());
if (trustedFp != null && trustedFp.equals(fp)) {
// Directly trusted.
return CheckResult.trusted();
} else if (depth >= maxTrustDepth) {
return CheckResult.ok("No path of depth <= " + maxTrustDepth + " to a trusted key");
}
List<CheckResult> signerResults = new ArrayList<>();
@SuppressWarnings("unchecked") Iterator<String> userIds = key.getUserIDs();
while (userIds.hasNext()) {
String userId = userIds.next();
// Don't check the timestamp of these certifications. This allows admins
// to correct untrusted keys by signing them with a trusted key, such that
// older signatures created by those keys retroactively appear valid.
Iterator<PGPSignature> sigs = key.getSignaturesForID(userId);
while (sigs.hasNext()) {
PGPSignature sig = sigs.next();
// TODO(dborowitz): Handle CERTIFICATION_REVOCATION.
if (sig.getSignatureType() != PGPSignature.DEFAULT_CERTIFICATION && sig.getSignatureType() != PGPSignature.POSITIVE_CERTIFICATION) {
// Not a certification.
continue;
}
PGPPublicKey signer = getSigner(store, sig, userId, key, signerResults);
// TODO(dborowitz): Require self certification.
if (signer == null || Arrays.equals(signer.getFingerprint(), key.getFingerprint())) {
continue;
}
String subpacketProblem = checkTrustSubpacket(sig, depth);
if (subpacketProblem == null) {
CheckResult signerResult = check(signer, depth + 1, false, seen);
if (signerResult.isTrusted()) {
return CheckResult.trusted();
}
}
signerResults.add(CheckResult.ok("Certification by " + keyToString(signer) + " is valid, but key is not trusted"));
}
}
List<String> problems = new ArrayList<>();
problems.add("No path to a trusted key");
for (CheckResult signerResult : signerResults) {
problems.addAll(signerResult.getProblems());
}
return CheckResult.create(OK, problems);
}
Aggregations