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 }