All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.spongycastle.openpgp.PGPSecretKeyRing Maven / Gradle / Ivy

Go to download

Spongy Castle is a package-rename (org.bouncycastle.* to org.spongycastle.*) of Bouncy Castle intended for the Android platform. Android unfortunately ships with a stripped-down version of Bouncy Castle, which prevents easy upgrades - Spongy Castle overcomes this and provides a full, up-to-date version of the Bouncy Castle cryptographic libs.

The newest version!
package org.spongycastle.openpgp;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import org.spongycastle.bcpg.BCPGInputStream;
import org.spongycastle.bcpg.PacketTags;
import org.spongycastle.bcpg.PublicSubkeyPacket;
import org.spongycastle.bcpg.SecretKeyPacket;
import org.spongycastle.bcpg.SecretSubkeyPacket;
import org.spongycastle.bcpg.TrustPacket;
import org.spongycastle.openpgp.operator.KeyFingerPrintCalculator;
import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor;
import org.spongycastle.openpgp.operator.PBESecretKeyEncryptor;
import org.spongycastle.util.Iterable;

/**
 * Class to hold a single master secret key and its subkeys.
 * 

* Often PGP keyring files consist of multiple master keys, if you are trying to process * or construct one of these you should use the {@link PGPSecretKeyRingCollection} class. */ public class PGPSecretKeyRing extends PGPKeyRing implements Iterable { List keys; List extraPubKeys; PGPSecretKeyRing(List keys) { this(keys, new ArrayList()); } private PGPSecretKeyRing(List keys, List extraPubKeys) { this.keys = keys; this.extraPubKeys = extraPubKeys; } public PGPSecretKeyRing( byte[] encoding, KeyFingerPrintCalculator fingerPrintCalculator) throws IOException, PGPException { this(new ByteArrayInputStream(encoding), fingerPrintCalculator); } public PGPSecretKeyRing( InputStream in, KeyFingerPrintCalculator fingerPrintCalculator) throws IOException, PGPException { this.keys = new ArrayList(); this.extraPubKeys = new ArrayList(); BCPGInputStream pIn = wrap(in); int initialTag = pIn.nextPacketTag(); if (initialTag != PacketTags.SECRET_KEY && initialTag != PacketTags.SECRET_SUBKEY) { throw new IOException( "secret key ring doesn't start with secret key tag: " + "tag 0x" + Integer.toHexString(initialTag)); } SecretKeyPacket secret = (SecretKeyPacket)pIn.readPacket(); // // ignore GPG comment packets if found. // while (pIn.nextPacketTag() == PacketTags.EXPERIMENTAL_2) { pIn.readPacket(); } TrustPacket trust = readOptionalTrustPacket(pIn); // revocation and direct signatures List keySigs = readSignaturesAndTrust(pIn); List ids = new ArrayList(); List idTrusts = new ArrayList(); List idSigs = new ArrayList(); readUserIDs(pIn, ids, idTrusts, idSigs); keys.add(new PGPSecretKey(secret, new PGPPublicKey(secret.getPublicKeyPacket(), trust, keySigs, ids, idTrusts, idSigs, fingerPrintCalculator))); // Read subkeys while (pIn.nextPacketTag() == PacketTags.SECRET_SUBKEY || pIn.nextPacketTag() == PacketTags.PUBLIC_SUBKEY) { if (pIn.nextPacketTag() == PacketTags.SECRET_SUBKEY) { SecretSubkeyPacket sub = (SecretSubkeyPacket)pIn.readPacket(); // // ignore GPG comment packets if found. // while (pIn.nextPacketTag() == PacketTags.EXPERIMENTAL_2) { pIn.readPacket(); } TrustPacket subTrust = readOptionalTrustPacket(pIn); List sigList = readSignaturesAndTrust(pIn); keys.add(new PGPSecretKey(sub, new PGPPublicKey(sub.getPublicKeyPacket(), subTrust, sigList, fingerPrintCalculator))); } else { PublicSubkeyPacket sub = (PublicSubkeyPacket)pIn.readPacket(); TrustPacket subTrust = readOptionalTrustPacket(pIn); List sigList = readSignaturesAndTrust(pIn); extraPubKeys.add(new PGPPublicKey(sub, subTrust, sigList, fingerPrintCalculator)); } } } /** * Return the public key for the master key. * * @return PGPPublicKey */ public PGPPublicKey getPublicKey() { return ((PGPSecretKey)keys.get(0)).getPublicKey(); } /** * Return the public key referred to by the passed in keyID if it * is present. * * @param keyID * @return PGPPublicKey */ public PGPPublicKey getPublicKey( long keyID) { PGPSecretKey key = getSecretKey(keyID); if (key != null) { return key.getPublicKey(); } for (int i = 0; i != extraPubKeys.size(); i++) { PGPPublicKey k = (PGPPublicKey)keys.get(i); if (keyID == k.getKeyID()) { return k; } } return null; } /** * Return an iterator containing all the public keys. * * @return Iterator */ public Iterator getPublicKeys() { List pubKeys = new ArrayList(); for (Iterator it = getSecretKeys(); it.hasNext();) { pubKeys.add(((PGPSecretKey)it.next()).getPublicKey()); } pubKeys.addAll(extraPubKeys); return Collections.unmodifiableList(pubKeys).iterator(); } /** * Return the master private key. * * @return PGPSecretKey */ public PGPSecretKey getSecretKey() { return ((PGPSecretKey)keys.get(0)); } /** * Return an iterator containing all the secret keys. * * @return Iterator */ public Iterator getSecretKeys() { return Collections.unmodifiableList(keys).iterator(); } public PGPSecretKey getSecretKey( long keyId) { for (int i = 0; i != keys.size(); i++) { PGPSecretKey k = (PGPSecretKey)keys.get(i); if (keyId == k.getKeyID()) { return k; } } return null; } /** * Return an iterator of the public keys in the secret key ring that * have no matching private key. At the moment only personal certificate data * appears in this fashion. * * @return iterator of unattached, or extra, public keys. */ public Iterator getExtraPublicKeys() { return extraPubKeys.iterator(); } public byte[] getEncoded() throws IOException { ByteArrayOutputStream bOut = new ByteArrayOutputStream(); this.encode(bOut); return bOut.toByteArray(); } public void encode( OutputStream outStream) throws IOException { for (int i = 0; i != keys.size(); i++) { PGPSecretKey k = (PGPSecretKey)keys.get(i); k.encode(outStream); } for (int i = 0; i != extraPubKeys.size(); i++) { PGPPublicKey k = (PGPPublicKey)extraPubKeys.get(i); k.encode(outStream); } } /** * Support method for Iterable where available. */ public Iterator iterator() { return getSecretKeys(); } /** * Replace the public key set on the secret ring with the corresponding key off the public ring. * * @param secretRing secret ring to be changed. * @param publicRing public ring containing the new public key set. */ public static PGPSecretKeyRing replacePublicKeys(PGPSecretKeyRing secretRing, PGPPublicKeyRing publicRing) { List newList = new ArrayList(secretRing.keys.size()); for (Iterator it = secretRing.keys.iterator(); it.hasNext();) { PGPSecretKey sk = (PGPSecretKey)it.next(); PGPPublicKey pk = publicRing.getPublicKey(sk.getKeyID()); newList.add(PGPSecretKey.replacePublicKey(sk, pk)); } return new PGPSecretKeyRing(newList); } /** * Return a copy of the passed in secret key ring, with the private keys (where present) associated with the master key and sub keys * are encrypted using a new password and the passed in algorithm. * * @param ring the PGPSecretKeyRing to be copied. * @param oldKeyDecryptor the current decryptor based on the current password for key. * @param newKeyEncryptor a new encryptor based on a new password for encrypting the secret key material. * @return the updated key ring. */ public static PGPSecretKeyRing copyWithNewPassword( PGPSecretKeyRing ring, PBESecretKeyDecryptor oldKeyDecryptor, PBESecretKeyEncryptor newKeyEncryptor) throws PGPException { List newKeys = new ArrayList(ring.keys.size()); for (Iterator keys = ring.getSecretKeys(); keys.hasNext();) { PGPSecretKey key = (PGPSecretKey)keys.next(); if (key.isPrivateKeyEmpty()) { newKeys.add(key); } else { newKeys.add(PGPSecretKey.copyWithNewPassword(key, oldKeyDecryptor, newKeyEncryptor)); } } return new PGPSecretKeyRing(newKeys, ring.extraPubKeys); } /** * Returns a new key ring with the secret key passed in either added or * replacing an existing one with the same key ID. * * @param secRing the secret key ring to be modified. * @param secKey the secret key to be added. * @return a new secret key ring. */ public static PGPSecretKeyRing insertSecretKey( PGPSecretKeyRing secRing, PGPSecretKey secKey) { List keys = new ArrayList(secRing.keys); boolean found = false; boolean masterFound = false; for (int i = 0; i != keys.size();i++) { PGPSecretKey key = (PGPSecretKey)keys.get(i); if (key.getKeyID() == secKey.getKeyID()) { found = true; keys.set(i, secKey); } if (key.isMasterKey()) { masterFound = true; } } if (!found) { if (secKey.isMasterKey()) { if (masterFound) { throw new IllegalArgumentException("cannot add a master key to a ring that already has one"); } keys.add(0, secKey); } else { keys.add(secKey); } } return new PGPSecretKeyRing(keys, secRing.extraPubKeys); } /** * Returns a new key ring with the secret key passed in removed from the * key ring. * * @param secRing the secret key ring to be modified. * @param secKey the secret key to be removed. * @return a new secret key ring, or null if secKey is not found. */ public static PGPSecretKeyRing removeSecretKey( PGPSecretKeyRing secRing, PGPSecretKey secKey) { List keys = new ArrayList(secRing.keys); boolean found = false; for (int i = 0; i < keys.size();i++) { PGPSecretKey key = (PGPSecretKey)keys.get(i); if (key.getKeyID() == secKey.getKeyID()) { found = true; keys.remove(i); } } if (!found) { return null; } return new PGPSecretKeyRing(keys, secRing.extraPubKeys); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy