Example usage for org.bouncycastle.openpgp PGPKeyRing getPublicKey

List of usage examples for org.bouncycastle.openpgp PGPKeyRing getPublicKey

Introduction

In this page you can find the example usage for org.bouncycastle.openpgp PGPKeyRing getPublicKey.

Prototype

public abstract PGPPublicKey getPublicKey(byte[] fingerprint);

Source Link

Document

Return the public key with the passed in fingerprint if it is present.

Usage

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;
    }

}