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 }