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