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