    001    /**
    002     *
    003     */
    004    package com.skype.util;
    005
    006    import java.io.BufferedReader;
    007    import java.io.ByteArrayInputStream;
    008    import java.io.ByteArrayOutputStream;
    009    import java.io.File;
    010    import java.io.FileInputStream;
    011    import java.io.FileNotFoundException;
    012    import java.io.IOException;
    013    import java.io.InputStream;
    014    import java.io.InputStreamReader;
    015    import java.security.KeyFactory;
    016    import java.security.NoSuchAlgorithmException;
    017    import java.security.PrivateKey;
    018    import java.security.cert.CertificateException;
    019    import java.security.cert.CertificateFactory;
    020    import java.security.cert.X509Certificate;
    021    import java.security.spec.InvalidKeySpecException;
    022    import java.security.spec.PKCS8EncodedKeySpec;
    023
    024
    025    /**
    026     * Minimal utilities for reading and decoding PEM certificate files
    027     *
    028     * @author kcjones
    029     *
    030     */
    031    public class PemReader
    032    {
    033
    034        private static final String TAG          = "PemReader";
    035        private static final String certStart    = "-----BEGIN CERTIFICATE-----";
    036        private static final String certEnd      = "-----END CERTIFICATE-----";
    037        private InputStream         certInStream    = null;
    038        private InputStream         keyInStream  = null;
    039
    040        public PemReader(InputStream cert, InputStream key)
    041        {
    042            certInStream = cert;
    043            keyInStream = key;
    044        }
    045
    046        public PemReader(String pemFilePath) throws FileNotFoundException
    047        {
    048            File file = new File(pemFilePath);
    049
    050            certInStream = new FileInputStream(file);
    051
    052            assert (pemFilePath.endsWith("pem"));
    053            String derPath = pemFilePath.substring(0, pemFilePath.length() - 3);
    054            derPath += "der";
    055
    056            file = new File(derPath);
    057            Log.d(TAG, "file length:" + file.length());
    058
    059            keyInStream = new FileInputStream(file);
    060        }
    061
    062        public X509Certificate getCertificate() throws IOException, InvalidKeySpecException
    063        {
    064            if (certInStream == null)
    065                throw new IOException("No certification source specified");
    066
    067            StringBuffer contents = new StringBuffer();
    068
    069            try {
    070                BufferedReader reader = new BufferedReader(new InputStreamReader(certInStream));
    071                String text;
    072                while ((text = reader.readLine()) != null) {
    073                    contents.append(text).append(System.getProperty("line.separator"));
    074                }
    075
    076                // find and parse certificate
    077                int ci = contents.indexOf(certStart);
    078                int cf = contents.indexOf(certEnd) + certEnd.length();
    079                if ( ! (ci >= 0 && cf > ci))
    080                    throw new InvalidKeySpecException("Missing or malformed certificate data.");
    081
    082                String certString = contents.substring(ci, cf);
    083                certInStream = new ByteArrayInputStream(certString.getBytes());
    084
    085                CertificateFactory cfac = CertificateFactory.getInstance("X.509");
    086                return (X509Certificate)cfac.generateCertificate(certInStream);
    087            }
    088            catch (CertificateException e) {
    089                throw new IOException("Invalid certificate in PEM file: " + e.getMessage());
    090            }
    091        }
    092
    093        public PrivateKey getKey() throws IOException
    094        {
    095
    096            if (keyInStream == null)
    097                throw new IOException("No private key source specified");
    098
    099            try {
    100                ByteArrayOutputStream baos = new ByteArrayOutputStream();
    101                int bite;
    102                while ((bite = keyInStream.read()) != - 1) {
    103                    baos.write(bite);
    104                }
    105
    106                byte[] encodedKey = baos.toByteArray();
    107
    108                PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(encodedKey);
    109
    110                KeyFactory factory = KeyFactory.getInstance("RSA");
    111                return factory.generatePrivate(spec);
    112            }
    113            catch (IndexOutOfBoundsException e) {
    114                throw new IOException("Invalid private key source");
    115            }
    116            catch (InvalidKeySpecException e) {
    117                throw new IOException("Invalid private key in DER file: " + e.getMessage());
    118            }
    119            catch (NoSuchAlgorithmException e) {
    120                // I'll be damned. No RSA? I don't believe it.
    121                e.printStackTrace();
    122                System.exit(1);
    123            }
    124            return null;
    125        }
    126    }