1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.apksig.internal.util; 18 19 import java.io.IOException; 20 import java.io.InputStream; 21 import java.security.KeyFactory; 22 import java.security.NoSuchAlgorithmException; 23 import java.security.PrivateKey; 24 import java.security.cert.Certificate; 25 import java.security.cert.CertificateException; 26 import java.security.cert.CertificateFactory; 27 import java.security.cert.X509Certificate; 28 import java.security.spec.InvalidKeySpecException; 29 import java.security.spec.PKCS8EncodedKeySpec; 30 import java.util.ArrayList; 31 import java.util.Collection; 32 import java.util.List; 33 import java.util.Locale; 34 35 /** 36 * Assorted methods to obtaining test input from resources. 37 */ 38 public final class Resources { 39 private Resources() {} 40 41 public static byte[] toByteArray(Class<?> cls, String resourceName) throws IOException { 42 try (InputStream in = cls.getResourceAsStream(resourceName)) { 43 if (in == null) { 44 throw new IllegalArgumentException("Resource not found: " + resourceName); 45 } 46 return ByteStreams.toByteArray(in); 47 } 48 } 49 50 public static X509Certificate toCertificate( 51 Class <?> cls, String resourceName) throws IOException, CertificateException { 52 try (InputStream in = cls.getResourceAsStream(resourceName)) { 53 if (in == null) { 54 throw new IllegalArgumentException("Resource not found: " + resourceName); 55 } 56 return (X509Certificate) 57 CertificateFactory.getInstance("X.509").generateCertificate(in); 58 } 59 } 60 61 public static List<X509Certificate> toCertificateChain( 62 Class <?> cls, String resourceName) throws IOException, CertificateException { 63 Collection<? extends Certificate> certs; 64 try (InputStream in = cls.getResourceAsStream(resourceName)) { 65 if (in == null) { 66 throw new IllegalArgumentException("Resource not found: " + resourceName); 67 } 68 certs = CertificateFactory.getInstance("X.509").generateCertificates(in); 69 } 70 List<X509Certificate> result = new ArrayList<>(certs.size()); 71 for (Certificate cert : certs) { 72 result.add((X509Certificate) cert); 73 } 74 return result; 75 } 76 77 public static PrivateKey toPrivateKey(Class <?> cls, String resourceName) 78 throws IOException, InvalidKeySpecException, NoSuchAlgorithmException { 79 int delimiterIndex = resourceName.indexOf('-'); 80 if (delimiterIndex == -1) { 81 throw new IllegalArgumentException( 82 "Failed to autodetect key algorithm from resource name: " + resourceName); 83 } 84 String keyAlgorithm = resourceName.substring(0, delimiterIndex).toUpperCase(Locale.US); 85 return toPrivateKey(cls, resourceName, keyAlgorithm); 86 } 87 88 public static PrivateKey toPrivateKey( 89 Class <?> cls, String resourceName, String keyAlgorithm) 90 throws IOException, InvalidKeySpecException, NoSuchAlgorithmException { 91 byte[] encoded = toByteArray(cls, resourceName); 92 93 // Keep overly strictly linter happy by limiting what JCA KeyFactory algorithms are used 94 // here 95 KeyFactory keyFactory; 96 switch (keyAlgorithm.toUpperCase(Locale.US)) { 97 case "RSA": 98 keyFactory = KeyFactory.getInstance("rsa"); 99 break; 100 case "DSA": 101 keyFactory = KeyFactory.getInstance("dsa"); 102 break; 103 case "EC": 104 keyFactory = KeyFactory.getInstance("ec"); 105 break; 106 default: 107 throw new InvalidKeySpecException("Unsupported key algorithm: " + keyAlgorithm); 108 } 109 110 return keyFactory.generatePrivate(new PKCS8EncodedKeySpec(encoded)); 111 } 112 } 113