List of usage examples for org.bouncycastle.openpgp PGPKeyRing getPublicKey
public abstract PGPPublicKey getPublicKey(byte[] fingerprint);
From source file:org.sufficientlysecure.keychain.pgp.UncachedKeyRing.java
License:Open Source License
/** This operation merges information from a different keyring, returning a combined * UncachedKeyRing.//w ww .j a v a2s .co m * * The combined keyring contains the subkeys, user ids and user attributes of both input * keyrings, but it does not necessarily have the canonicalized property. * * @param other The UncachedKeyRing to merge. Must not be empty, and of the same masterKeyId * @return A consolidated UncachedKeyRing with the data of both input keyrings. Same type as * this object, or null on error. * */ public UncachedKeyRing merge(UncachedKeyRing other, OperationLog log, int indent) { // This is logged in the calling method to provide more meta info // log.add(isSecret() ? LogType.MSG_MG_SECRET : LogType.MSG_MG_PUBLIC, // indent, KeyFormattingUtils.convertKeyIdToHex(getMasterKeyId())); indent += 1; long masterKeyId = other.getMasterKeyId(); if (getMasterKeyId() != masterKeyId || !Arrays.equals(getFingerprint(), other.getFingerprint())) { log.add(LogType.MSG_MG_ERROR_HETEROGENEOUS, indent); return null; } // remember which certs we already added. this is cheaper than semantic deduplication Set<byte[]> certs = new TreeSet<>(new Comparator<byte[]>() { public int compare(byte[] left, byte[] right) { // check for length equality if (left.length != right.length) { return left.length - right.length; } // compare byte-by-byte for (int i = 0; i < left.length; i++) { if (left[i] != right[i]) { return (left[i] & 0xff) - (right[i] & 0xff); } } // ok they're the same return 0; } }); try { PGPKeyRing result = mRing; PGPKeyRing candidate = other.mRing; // Pre-load all existing certificates for (PGPPublicKey key : new IterableIterator<PGPPublicKey>(result.getPublicKeys())) { for (PGPSignature cert : new IterableIterator<PGPSignature>(key.getSignatures())) { certs.add(cert.getEncoded()); } } // keep track of the number of new certs we add int newCerts = 0; for (PGPPublicKey key : new IterableIterator<PGPPublicKey>(candidate.getPublicKeys())) { final PGPPublicKey resultKey = result.getPublicKey(key.getKeyID()); if (resultKey == null) { log.add(LogType.MSG_MG_NEW_SUBKEY, indent); // special case: if both rings are secret, copy over the secret key if (isSecret() && other.isSecret()) { PGPSecretKey sKey = ((PGPSecretKeyRing) candidate).getSecretKey(key.getKeyID()); result = PGPSecretKeyRing.insertSecretKey((PGPSecretKeyRing) result, sKey); } else { // otherwise, just insert the public key result = replacePublicKey(result, key); } continue; } // Modifiable version of the old key, which we merge stuff into (keep old for comparison) PGPPublicKey modified = resultKey; // Iterate certifications for (PGPSignature cert : new IterableIterator<PGPSignature>(key.getKeySignatures())) { // Don't merge foreign stuff into secret keys if (cert.getKeyID() != masterKeyId && isSecret()) { continue; } byte[] encoded = cert.getEncoded(); // Known cert, skip it if (certs.contains(encoded)) { continue; } certs.add(encoded); modified = PGPPublicKey.addCertification(modified, cert); newCerts += 1; } // If this is a subkey, merge it in and stop here if (!key.isMasterKey()) { if (modified != resultKey) { result = replacePublicKey(result, modified); } continue; } // Copy over all user id certificates for (byte[] rawUserId : new IterableIterator<byte[]>(key.getRawUserIDs())) { @SuppressWarnings("unchecked") Iterator<PGPSignature> signaturesIt = key.getSignaturesForID(rawUserId); // no signatures for this User ID, skip it if (signaturesIt == null) { continue; } for (PGPSignature cert : new IterableIterator<>(signaturesIt)) { // Don't merge foreign stuff into secret keys if (cert.getKeyID() != masterKeyId && isSecret()) { continue; } byte[] encoded = cert.getEncoded(); // Known cert, skip it if (certs.contains(encoded)) { continue; } newCerts += 1; certs.add(encoded); modified = PGPPublicKey.addCertification(modified, rawUserId, cert); } } // Copy over all user attribute certificates for (PGPUserAttributeSubpacketVector vector : new IterableIterator<PGPUserAttributeSubpacketVector>( key.getUserAttributes())) { @SuppressWarnings("unchecked") Iterator<PGPSignature> signaturesIt = key.getSignaturesForUserAttribute(vector); // no signatures for this user attribute attribute, skip it if (signaturesIt == null) { continue; } for (PGPSignature cert : new IterableIterator<>(signaturesIt)) { // Don't merge foreign stuff into secret keys if (cert.getKeyID() != masterKeyId && isSecret()) { continue; } byte[] encoded = cert.getEncoded(); // Known cert, skip it if (certs.contains(encoded)) { continue; } newCerts += 1; certs.add(encoded); modified = PGPPublicKey.addCertification(modified, vector, cert); } } // If anything change, save the updated (sub)key if (modified != resultKey) { result = replacePublicKey(result, modified); } } if (newCerts > 0) { log.add(LogType.MSG_MG_FOUND_NEW, indent, Integer.toString(newCerts)); } else { log.add(LogType.MSG_MG_UNCHANGED, indent); } return new UncachedKeyRing(result); } catch (IOException e) { log.add(LogType.MSG_MG_ERROR_ENCODE, indent); return null; } }