16e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrompackage org.bouncycastle.util.io.pem;
26e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
36e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstromimport java.io.BufferedReader;
46e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstromimport java.io.IOException;
56e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstromimport java.io.Reader;
66e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstromimport java.util.ArrayList;
76e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstromimport java.util.List;
86e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
96e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstromimport org.bouncycastle.util.encoders.Base64;
106e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
11d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root/**
12d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root * A generic PEM reader, based on the format outlined in RFC 1421
13d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root */
146e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrompublic class PemReader
156e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    extends BufferedReader
166e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom{
176e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    private static final String BEGIN = "-----BEGIN ";
186e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    private static final String END = "-----END ";
196e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
206e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    public PemReader(Reader reader)
216e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    {
226e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        super(reader);
236e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    }
246e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
256e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    public PemObject readPemObject()
266e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        throws IOException
276e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    {
286e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        String line = readLine();
296e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
304c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        while (line != null && !line.startsWith(BEGIN))
314c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
324c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            line = readLine();
334c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
344c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
354c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        if (line != null)
366e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        {
376e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            line = line.substring(BEGIN.length());
386e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            int index = line.indexOf('-');
396e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            String type = line.substring(0, index);
406e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
416e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            if (index > 0)
426e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            {
436e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                return loadObject(type);
446e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            }
456e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        }
466e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
476e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        return null;
486e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    }
496e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
506e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    private PemObject loadObject(String type)
516e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        throws IOException
526e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    {
536e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        String          line;
546e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        String          endMarker = END + type;
556e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        StringBuffer    buf = new StringBuffer();
566e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        List            headers = new ArrayList();
576e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
586e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        while ((line = readLine()) != null)
596e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        {
606e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            if (line.indexOf(":") >= 0)
616e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            {
626e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                int index = line.indexOf(':');
636e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                String hdr = line.substring(0, index);
646e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                String value = line.substring(index + 1).trim();
656e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
666e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                headers.add(new PemHeader(hdr, value));
676e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
686e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                continue;
696e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            }
706e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
716e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            if (line.indexOf(endMarker) != -1)
726e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            {
736e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                break;
746e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            }
756e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
766e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            buf.append(line.trim());
776e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        }
786e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
796e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        if (line == null)
806e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        {
816e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            throw new IOException(endMarker + " not found");
826e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        }
836e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
846e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        return new PemObject(type, headers, Base64.decode(buf.toString()));
856e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    }
866e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
876e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom}
88