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    }