EMMA Coverage Report (generated Wed Aug 10 12:30:04 EDT 2011)
[all classes][org.jclouds.crypto]

COVERAGE SUMMARY FOR SOURCE FILE [Pems.java]

nameclass, %method, %block, %line, %
Pems.java100% (7/7)78%  (21/27)73%  (257/351)63%  (37.7/60)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class Pems$3100% (1/1)50%  (1/2)33%  (3/9)50%  (1/2)
parseResult (byte []): KeySpec 0%   (0/1)0%   (0/6)0%   (0/1)
Pems$3 (): void 100% (1/1)100% (3/3)100% (1/1)
     
class Pems$2100% (1/1)50%  (1/2)38%  (3/8)50%  (1/2)
parseResult (byte []): KeySpec 0%   (0/1)0%   (0/5)0%   (0/1)
Pems$2 (): void 100% (1/1)100% (3/3)100% (1/1)
     
class Pems$PemProcessor100% (1/1)100% (3/3)65%  (47/72)77%  (10/13)
getResult (): Object 100% (1/1)50%  (25/50)57%  (4/7)
Pems$PemProcessor (Map): void 100% (1/1)100% (14/14)100% (4/4)
processBytes (byte [], int, int): boolean 100% (1/1)100% (8/8)100% (2/2)
     
class Pems$5100% (1/1)100% (2/2)71%  (15/21)50%  (2/4)
parseResult (byte []): X509Certificate 100% (1/1)60%  (9/15)33%  (1/3)
Pems$5 (CertificateFactory): void 100% (1/1)100% (6/6)100% (1/1)
     
class Pems100% (1/1)71%  (10/14)77%  (172/224)56%  (19.7/35)
Pems (): void 0%   (0/1)0%   (0/3)0%   (0/2)
privateKeySpec (String): KeySpec 0%   (0/1)0%   (0/4)0%   (0/1)
publicKeySpec (String): KeySpec 0%   (0/1)0%   (0/4)0%   (0/1)
x509Certificate (String): X509Certificate 0%   (0/1)0%   (0/5)0%   (0/1)
fromPem (InputSupplier, Pems$PemProcessor): Object 100% (1/1)22%  (4/18)20%  (1/5)
x509Certificate (InputSupplier, CertificateFactory): X509Certificate 100% (1/1)59%  (20/34)33%  (2/6)
pem (PrivateKey): String 100% (1/1)86%  (18/21)88%  (1.8/2)
getEncoded (RSAPrivateCrtKey): byte [] 100% (1/1)90%  (38/42)78%  (7/9)
pem (PublicKey): String 100% (1/1)92%  (11/12)96%  (1.9/2)
pem (X509Certificate): String 100% (1/1)100% (7/7)100% (2/2)
pem (byte [], String): String 100% (1/1)100% (5/5)100% (1/1)
pem (byte [], String, int): String 100% (1/1)100% (37/37)100% (1/1)
privateKeySpec (InputSupplier): KeySpec 100% (1/1)100% (16/16)100% (1/1)
publicKeySpec (InputSupplier): KeySpec 100% (1/1)100% (16/16)100% (1/1)
     
class Pems$1100% (1/1)100% (2/2)100% (9/9)100% (2/2)
Pems$1 (): void 100% (1/1)100% (3/3)100% (1/1)
parseResult (byte []): KeySpec 100% (1/1)100% (6/6)100% (1/1)
     
class Pems$4100% (1/1)100% (2/2)100% (8/8)100% (2/2)
Pems$4 (): void 100% (1/1)100% (3/3)100% (1/1)
parseResult (byte []): X509EncodedKeySpec 100% (1/1)100% (5/5)100% (1/1)

1/**
2 *
3 * Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
4 *
5 * ====================================================================
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 * ====================================================================
18 */
19package org.jclouds.crypto;
20 
21import static com.google.common.base.Preconditions.checkNotNull;
22 
23import java.io.ByteArrayInputStream;
24import java.io.ByteArrayOutputStream;
25import java.io.IOException;
26import java.io.InputStream;
27import java.security.PrivateKey;
28import java.security.PublicKey;
29import java.security.cert.CertificateEncodingException;
30import java.security.cert.CertificateException;
31import java.security.cert.CertificateFactory;
32import java.security.cert.X509Certificate;
33import java.security.interfaces.RSAPrivateCrtKey;
34import java.security.interfaces.RSAPublicKey;
35import java.security.spec.KeySpec;
36import java.security.spec.PKCS8EncodedKeySpec;
37import java.security.spec.RSAPrivateKeySpec;
38import java.security.spec.X509EncodedKeySpec;
39import java.util.Map;
40 
41import javax.annotation.Nullable;
42 
43import net.oauth.signature.pem.PEMReader;
44import net.oauth.signature.pem.PKCS1EncodedKeySpec;
45import net.oauth.signature.pem.PKCS1EncodedPublicKeySpec;
46 
47import org.bouncycastle.asn1.ASN1OutputStream;
48import org.bouncycastle.asn1.pkcs.RSAPrivateKeyStructure;
49import org.jclouds.crypto.Pems.PemProcessor.ResultParser;
50import org.jclouds.io.InputSuppliers;
51 
52import com.google.common.annotations.Beta;
53import com.google.common.base.Joiner;
54import com.google.common.base.Splitter;
55import com.google.common.base.Throwables;
56import com.google.common.collect.ImmutableMap;
57import com.google.common.io.InputSupplier;
58 
59/**
60 * Reads and writes PEM encoded Strings and Streams
61 * 
62 * @author Adrian Cole
63 */
64@Beta
65public class Pems {
66   public static final String PRIVATE_PKCS1_MARKER = "-----BEGIN RSA PRIVATE KEY-----";
67   public static final String PRIVATE_PKCS8_MARKER = "-----BEGIN PRIVATE KEY-----";
68   public static final String CERTIFICATE_X509_MARKER = "-----BEGIN CERTIFICATE-----";
69   public static final String PUBLIC_X509_MARKER = "-----BEGIN PUBLIC KEY-----";
70   public static final String PUBLIC_PKCS1_MARKER = "-----BEGIN RSA PUBLIC KEY-----";
71 
72   public static class PemProcessor<T> implements com.google.common.io.ByteProcessor<T> {
73      public interface ResultParser<T> {
74         T parseResult(byte[] bytes) throws IOException;
75      }
76 
77      private final ByteArrayOutputStream out = new ByteArrayOutputStream();
78      private final Map<String, ResultParser<T>> parsers;
79 
80      public PemProcessor(Map<String, ResultParser<T>> parsers) {
81         this.parsers = checkNotNull(parsers, "parsers");
82      }
83 
84      public boolean processBytes(byte[] buf, int off, int len) {
85         out.write(buf, off, len);
86         return true;
87      }
88 
89      public T getResult() {
90         try {
91            PEMReader reader = new PEMReader(out.toByteArray());
92            byte[] bytes = reader.getDerBytes();
93            if (parsers.containsKey(reader.getBeginMarker())) {
94               return parsers.get(reader.getBeginMarker()).parseResult(bytes);
95            } else {
96               throw new IOException(String.format("Invalid PEM file: no parsers for marker %s in %s",
97                     reader.getBeginMarker(), parsers.keySet()));
98            }
99         } catch (IOException e) {
100            throw new RuntimeException(e);
101         }
102      }
103   }
104 
105   /**
106    * Returns the object of generic type {@code T} that is pem encoded in the
107    * supplier.
108    * 
109    * @param supplier
110    *           the input stream factory
111    * @param marker
112    *           header that begins the PEM block
113    * @param processor
114    *           how to parser the object from a byte array
115    * @return the object of generic type {@code T} which was PEM encoded in the
116    *         stream
117    * @throws IOException
118    *            if an I/O error occurs
119    */
120   public static <T> T fromPem(InputSupplier<? extends InputStream> supplier, PemProcessor<T> processor)
121         throws IOException {
122      try {
123         return com.google.common.io.ByteStreams.readBytes(supplier, processor);
124      } catch (RuntimeException e) {
125         if (e.getCause() != null && e.getCause() instanceof IOException) {
126            throw (IOException) e.getCause();
127         }
128         throw e;
129      }
130   }
131 
132   /**
133    * Returns the {@link RSAPrivateKeySpec} that is pem encoded in the supplier.
134    * 
135    * @param supplier
136    *           the input stream factory
137    * 
138    * @return the {@link RSAPrivateKeySpec} which was PEM encoded in the stream
139    * @throws IOException
140    *            if an I/O error occurs
141    */
142   public static KeySpec privateKeySpec(InputSupplier<? extends InputStream> supplier) throws IOException {
143      return fromPem(
144            supplier,
145            new PemProcessor<KeySpec>(ImmutableMap.<String, ResultParser<KeySpec>> of(PRIVATE_PKCS1_MARKER,
146                  new ResultParser<KeySpec>() {
147 
148                     public KeySpec parseResult(byte[] bytes) throws IOException {
149                        return (new PKCS1EncodedKeySpec(bytes)).getKeySpec();
150                     }
151 
152                  }, PRIVATE_PKCS8_MARKER, new ResultParser<KeySpec>() {
153 
154                     public KeySpec parseResult(byte[] bytes) throws IOException {
155                        return new PKCS8EncodedKeySpec(bytes);
156                     }
157 
158                  })));
159   }
160 
161   /**
162    * Executes {@link Pems#privateKeySpec(InputSupplier)} on the string which
163    * contains an encoded private key in PEM format.
164    * 
165    * @param pem
166    *           private key in pem encoded format.
167    * @see Pems#privateKeySpec(InputSupplier)
168    */
169   public static KeySpec privateKeySpec(String pem) throws IOException {
170      return privateKeySpec(InputSuppliers.of(pem));
171   }
172 
173   /**
174    * Returns the {@link KeySpec} that is pem encoded in the supplier.
175    * 
176    * @param supplier
177    *           the input stream factory
178    * 
179    * @return the {@link KeySpec} which was PEM encoded in the stream
180    * @throws IOException
181    *            if an I/O error occurs
182    */
183   public static KeySpec publicKeySpec(InputSupplier<? extends InputStream> supplier) throws IOException {
184      return fromPem(
185            supplier,
186            new PemProcessor<KeySpec>(ImmutableMap.<String, ResultParser<KeySpec>> of(PUBLIC_PKCS1_MARKER,
187                  new ResultParser<KeySpec>() {
188 
189                     public KeySpec parseResult(byte[] bytes) throws IOException {
190                        return (new PKCS1EncodedPublicKeySpec(bytes)).getKeySpec();
191                     }
192 
193                  }, PUBLIC_X509_MARKER, new ResultParser<KeySpec>() {
194 
195                     public X509EncodedKeySpec parseResult(byte[] bytes) throws IOException {
196                        return new X509EncodedKeySpec(bytes);
197                     }
198 
199                  })));
200   }
201 
202   /**
203    * Executes {@link Pems#publicKeySpec(InputSupplier)} on the string which
204    * contains an encoded public key in PEM format.
205    * 
206    * @param pem
207    *           public key in pem encoded format.
208    * @see Pems#publicKeySpec(InputSupplier)
209    */
210   public static KeySpec publicKeySpec(String pem) throws IOException {
211      return publicKeySpec(InputSuppliers.of(pem));
212   }
213 
214   /**
215    * Returns the {@link X509EncodedKeySpec} that is pem encoded in the
216    * supplier.
217    * 
218    * @param supplier
219    *           the input stream factory
220    * @param certFactory
221    *           or null to use default
222    * 
223    * @return the {@link X509EncodedKeySpec} which was PEM encoded in the stream
224    * @throws IOException
225    *            if an I/O error occurs
226    * @throws CertificateException
227    */
228   public static X509Certificate x509Certificate(InputSupplier<? extends InputStream> supplier,
229         @Nullable CertificateFactory certFactory) throws IOException, CertificateException {
230      final CertificateFactory finalCertFactory = certFactory != null ? certFactory : CertificateFactory
231            .getInstance("X.509");
232      try {
233         return fromPem(
234               supplier,
235               new PemProcessor<X509Certificate>(ImmutableMap.<String, ResultParser<X509Certificate>> of(
236                     CERTIFICATE_X509_MARKER, new ResultParser<X509Certificate>() {
237 
238                        public X509Certificate parseResult(byte[] bytes) throws IOException {
239                           try {
240                              return (X509Certificate) finalCertFactory.generateCertificate(new ByteArrayInputStream(
241                                    bytes));
242                           } catch (CertificateException e) {
243                              throw new RuntimeException(e);
244                           }
245                        }
246 
247                     })));
248      } catch (RuntimeException e) {
249         if (e.getCause() != null && e.getCause() instanceof CertificateException) {
250            throw (CertificateException) e.getCause();
251         }
252         throw e;
253      }
254   }
255 
256   /**
257    * Executes {@link Pems#x509Certificate(InputSupplier, CertificateFactory)}
258    * on the string which contains an X.509 certificate in PEM format.
259    * 
260    * @param pem
261    *           certificate in pem encoded format.
262    * @see Pems#x509Certificate(InputSupplier, CertificateFactory)
263    */
264   public static X509Certificate x509Certificate(String pem) throws IOException, CertificateException {
265      return x509Certificate(InputSuppliers.of(pem), null);
266   }
267 
268   /**
269    * encodes the {@link X509Certificate} to PEM format.
270    * 
271    * @param cert
272    *           what to encode
273    * @return the PEM encoded certificate
274    * @throws IOException
275    * @throws CertificateEncodingException
276    */
277   public static String pem(X509Certificate cert) throws CertificateEncodingException {
278      String marker = CERTIFICATE_X509_MARKER;
279      return pem(cert.getEncoded(), marker);
280   }
281 
282   /**
283    * encodes the {@link PublicKey} to PEM format.
284    * 
285    * @param cert
286    *           what to encode
287    * @return the PEM encoded public key
288    * @throws IOException
289    * @throws CertificateEncodingException
290    */
291   public static String pem(PublicKey key) {
292      String marker = key instanceof RSAPublicKey ? PUBLIC_PKCS1_MARKER : PUBLIC_X509_MARKER;
293      return pem(key.getEncoded(), marker);
294   }
295 
296   /**
297    * encodes the {@link PrivateKey} to PEM format. Note
298    * 
299    * @param cert
300    *           what to encode
301    * @return the PEM encoded private key
302    * @throws IOException
303    * @throws CertificateEncodingException
304    */
305   public static String pem(PrivateKey key) {
306      String marker = key instanceof RSAPrivateCrtKey ? PRIVATE_PKCS1_MARKER : PRIVATE_PKCS8_MARKER;
307      return pem(key instanceof RSAPrivateCrtKey ? getEncoded(RSAPrivateCrtKey.class.cast(key)) : key.getEncoded(),
308            marker);
309   }
310 
311   // TODO find a way to do this without using bouncycastle
312   static byte[] getEncoded(RSAPrivateCrtKey key) {
313      RSAPrivateKeyStructure keyStruct = new RSAPrivateKeyStructure(key.getModulus(), key.getPublicExponent(),
314            key.getPrivateExponent(), key.getPrimeP(), key.getPrimeQ(), key.getPrimeExponentP(),
315            key.getPrimeExponentQ(), key.getCrtCoefficient());
316 
317      ByteArrayOutputStream bOut = new ByteArrayOutputStream();
318      ASN1OutputStream aOut = new ASN1OutputStream(bOut);
319 
320      try {
321         aOut.writeObject(keyStruct);
322         aOut.close();
323      } catch (IOException e) {
324         Throwables.propagate(e);
325      }
326 
327      return bOut.toByteArray();
328   }
329 
330   private static String pem(byte[] key, String marker) {
331      return pem(key, marker, 64);
332   }
333 
334   static String pem(byte[] key, String marker, int length) {
335      return new StringBuilder(marker + "\n")
336            .append(Joiner.on('\n').join(Splitter.fixedLength(length).split(CryptoStreams.base64(key))))
337            .append("\n" + marker.replace("BEGIN", "END") + "\n").toString().trim();
338   }
339 
340}

[all classes][org.jclouds.crypto]
EMMA 2.0.5312 (C) Vladimir Roubtsov