001: package org.bouncycastle.openpgp;
002:
003: import org.bouncycastle.bcpg.BCPGInputStream;
004: import org.bouncycastle.bcpg.PacketTags;
005: import org.bouncycastle.bcpg.PublicKeyPacket;
006: import org.bouncycastle.bcpg.TrustPacket;
007:
008: import java.io.ByteArrayInputStream;
009: import java.io.ByteArrayOutputStream;
010: import java.io.IOException;
011: import java.io.InputStream;
012: import java.io.OutputStream;
013: import java.util.ArrayList;
014: import java.util.Collections;
015: import java.util.Iterator;
016: import java.util.List;
017:
018: /**
019: * general class to hold a collection of PGP Public Keys.
020: */
021: public class PGPPublicKeyRing extends PGPKeyRing {
022: final List keys;
023:
024: public PGPPublicKeyRing(byte[] encoding) throws IOException {
025: this (new ByteArrayInputStream(encoding));
026: }
027:
028: /**
029: * @param pubKeys
030: */
031: PGPPublicKeyRing(List pubKeys) {
032: this .keys = pubKeys;
033: }
034:
035: public PGPPublicKeyRing(InputStream in) throws IOException {
036: this .keys = new ArrayList();
037:
038: BCPGInputStream pIn = wrap(in);
039:
040: int initialTag = pIn.nextPacketTag();
041: if (initialTag != PacketTags.PUBLIC_KEY
042: && initialTag != PacketTags.PUBLIC_SUBKEY) {
043: throw new IOException(
044: "public key ring doesn't start with public key tag: "
045: + "tag 0x"
046: + Integer.toHexString(initialTag));
047: }
048:
049: PublicKeyPacket pubPk = (PublicKeyPacket) pIn.readPacket();
050: TrustPacket trustPk = readOptionalTrustPacket(pIn);
051:
052: // direct signatures and revocations
053: List keySigs = readSignaturesAndTrust(pIn);
054:
055: List ids = new ArrayList();
056: List idTrusts = new ArrayList();
057: List idSigs = new ArrayList();
058: readUserIDs(pIn, ids, idTrusts, idSigs);
059:
060: keys.add(new PGPPublicKey(pubPk, trustPk, keySigs, ids,
061: idTrusts, idSigs));
062:
063: // Read subkeys
064: while (pIn.nextPacketTag() == PacketTags.PUBLIC_SUBKEY) {
065: PublicKeyPacket pk = (PublicKeyPacket) pIn.readPacket();
066: TrustPacket kTrust = readOptionalTrustPacket(pIn);
067:
068: // PGP 8 actually leaves out the signature.
069: List sigList = readSignaturesAndTrust(pIn);
070:
071: keys.add(new PGPPublicKey(pk, kTrust, sigList));
072: }
073: }
074:
075: /**
076: * Return the first public key in the ring.
077: *
078: * @return PGPPublicKey
079: */
080: public PGPPublicKey getPublicKey() {
081: return (PGPPublicKey) keys.get(0);
082: }
083:
084: /**
085: * Return the public key refered to by the passed in keyID if it
086: * is present.
087: *
088: * @param keyID
089: * @return PGPPublicKey
090: * @throws PGPException
091: */
092: public PGPPublicKey getPublicKey(long keyID) throws PGPException {
093: for (int i = 0; i != keys.size(); i++) {
094: PGPPublicKey k = (PGPPublicKey) keys.get(i);
095:
096: if (keyID == k.getKeyID()) {
097: return k;
098: }
099: }
100:
101: return null;
102: }
103:
104: /**
105: * Return an iterator containing all the public keys.
106: *
107: * @return Iterator
108: */
109: public Iterator getPublicKeys() {
110: return Collections.unmodifiableList(keys).iterator();
111: }
112:
113: public byte[] getEncoded() throws IOException {
114: ByteArrayOutputStream bOut = new ByteArrayOutputStream();
115:
116: this .encode(bOut);
117:
118: return bOut.toByteArray();
119: }
120:
121: public void encode(OutputStream outStream) throws IOException {
122: for (int i = 0; i != keys.size(); i++) {
123: PGPPublicKey k = (PGPPublicKey) keys.get(i);
124:
125: k.encode(outStream);
126: }
127: }
128:
129: /**
130: * Returns a new key ring with the public key passed in
131: * either added or replacing an existing one.
132: *
133: * @param pubRing the public key ring to be modified
134: * @param pubKey the public key to be inserted.
135: * @return a new keyRing
136: */
137: public static PGPPublicKeyRing insertPublicKey(
138: PGPPublicKeyRing pubRing, PGPPublicKey pubKey) {
139: List keys = new ArrayList(pubRing.keys);
140: boolean found = false;
141:
142: for (int i = 0; i != keys.size(); i++) {
143: PGPPublicKey key = (PGPPublicKey) keys.get(i);
144:
145: if (key.getKeyID() == pubKey.getKeyID()) {
146: found = true;
147: keys.set(i, pubKey);
148: }
149: }
150:
151: if (!found) {
152: keys.add(pubKey);
153: }
154:
155: return new PGPPublicKeyRing(keys);
156: }
157:
158: /**
159: * Returns a new key ring with the public key passed in
160: * removed from the key ring.
161: *
162: * @param pubRing the public key ring to be modified
163: * @param pubKey the public key to be removed.
164: * @return a new keyRing, null if pubKey is not found.
165: */
166: public static PGPPublicKeyRing removePublicKey(
167: PGPPublicKeyRing pubRing, PGPPublicKey pubKey) {
168: List keys = new ArrayList(pubRing.keys);
169: boolean found = false;
170:
171: for (int i = 0; i < keys.size(); i++) {
172: PGPPublicKey key = (PGPPublicKey) keys.get(i);
173:
174: if (key.getKeyID() == pubKey.getKeyID()) {
175: found = true;
176: keys.remove(i);
177: }
178: }
179:
180: if (!found) {
181: return null;
182: }
183:
184: return new PGPPublicKeyRing(keys);
185: }
186: }
|