package parser.utils; import sun.security.pkcs.PKCS7; import java.io.*; import java.security.MessageDigest; import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.Enumeration; import java.util.HashMap; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.jar.JarInputStream; /** * Created with IntelliJ IDEA. * User: lai * Date: 5/23/13 * Time: 10:08 AM */ public class CertTool { /** * 从证书信息中获取MD5值 * * @param cert Certificate * @return MD5 */ public static String getCertMd5(Certificate cert) { try { final MessageDigest md = MessageDigest.getInstance("MD5"); md.update(cert.getEncoded()); return HashTool.hex2Str(md.digest()); } catch (final Exception e) { e.printStackTrace(); return ""; } } /** * 获取一个 jar/zip 文件的证书信息 * * @param file jar/zip 文件 * @return hashMap, */ public static HashMap<String, String> getCertificateInfos(File file) { Certificate[] certs; HashMap<String, String> hashMap = new HashMap<>(); try { certs = getCertificates(file); for (Certificate cert : certs) { hashMap.put(getCertMd5(cert), getCertSubject(cert)); } } catch (NullPointerException e) { return hashMap; } catch (IOException e) { e.printStackTrace(); } return hashMap; } @SuppressWarnings("UnusedDeclaration") private static File bytes2File(byte[] bytes) throws IOException { File file = new File("sub.apk.tmp"); FileOutputStream fos = new FileOutputStream(file); new BufferedOutputStream(fos).write(bytes); fos.close(); return file; } private static File inputStream2File(InputStream inputStream) throws IOException { File file; byte[] buffer = new byte[1024]; file = new File("sub.apk.tmp"); FileOutputStream fos = new FileOutputStream(file); int len; int offset = 0; while ((len = inputStream.read(buffer)) != -1) { fos.write(buffer, offset, len); } fos.close(); inputStream.reset(); // inputStream.close(); return file; } public static HashMap<String, String> getCertificateInfos(InputStream inputStream) { Certificate[] certs; HashMap<String, String> hashMap = new HashMap<>(); try { final byte[] readBuffer = new byte[1024 * 8]; final JarInputStream jis = new JarInputStream(inputStream, true); for (JarEntry entry = jis.getNextJarEntry(); entry != null; entry = jis.getNextJarEntry()) { if (entry.getName().startsWith("META-INF/") && !entry.getName().endsWith(".MF") && !entry.getName().endsWith(".SF")) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); while (jis.read(readBuffer, 0, 1024 * 8) != -1) { baos.write(readBuffer, 0, 1024 * 8); } // System.out.println(entry.getName()); PKCS7 pkcs7 = new PKCS7(baos.toByteArray()); certs = pkcs7.getCertificates(); for (Certificate cert : certs) { hashMap.put(getCertMd5(cert), getCertSubject(cert)); } baos.close(); } } } catch (NullPointerException e) { return hashMap; } catch (IOException e) { // e.printStackTrace(); return hashMap; } return hashMap; } /** * 获取一个 jar/zip 文件的证书信息 * * @param bytes jar/zip 文件 bytes[] * @return hashMap, */ public static HashMap<String, String> getCertificateInfos(byte[] bytes) { Certificate[] certs; HashMap<String, String> hashMap = new HashMap<>(); try { certs = getCertificates(bytes); for (Certificate cert : certs) { hashMap.put(getCertMd5(cert), getCertSubject(cert)); } } catch (NullPointerException e) { return hashMap; } catch (IOException e) { e.printStackTrace(); } return hashMap; } /** * 获取证书的发行人信息 * * @param cert Certificate * @return 证书的发行人信息 String */ public static String getCertSubject(Certificate cert) { String subjectDN = null; try { final CertificateFactory cf = CertificateFactory.getInstance("X.509"); final X509Certificate x509Certificate = (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(cert.getEncoded())); subjectDN = x509Certificate.getSubjectDN().getName(); } catch (final CertificateException e) { e.printStackTrace(); } return subjectDN; } /** * 从证书信息中获取所有详细信息 * * @param cert Certificate * @return certDetail */ public static String getCertDetail(Certificate cert) { String certDetail = null; try { final CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509"); final X509Certificate x509Certificate = (X509Certificate) certificateFactory.generateCertificate(new ByteArrayInputStream(cert.getEncoded())); certDetail = x509Certificate.toString(); } catch (final CertificateException e) { e.printStackTrace(); } return certDetail; } /** * 从 ZIP 文件中获取证书 * * @param file ZIP 文件 * @return Certificate[] * @throws IOException */ private static Certificate[] getCertificates(File file) throws IOException { Certificate[] certs = null; final byte[] readBuffer = new byte[1024 * 8]; final JarFile jarFile = new JarFile(file); final Enumeration<JarEntry> jarEntryEnumeration = jarFile.entries(); while (jarEntryEnumeration.hasMoreElements()) { final JarEntry jarEntry = jarEntryEnumeration.nextElement(); if (jarEntry.isDirectory()) continue; if (jarEntry.getName().startsWith("META-INF/")) continue; final InputStream inputStream = jarFile.getInputStream(jarEntry); certs = loadCertificates(inputStream, jarEntry, readBuffer); if (certs != null) break; inputStream.close(); } jarFile.close(); return certs; } /** * @param bytes ZIP 文件 * @return Certificate[] * @throws IOException */ private static Certificate[] getCertificates(byte[] bytes) throws IOException { Certificate[] certs = null; final byte[] readBuffer = new byte[1024 * 8]; final JarInputStream jis = new JarInputStream(new ByteArrayInputStream(bytes)); for (JarEntry je = jis.getNextJarEntry(); je != null; je = jis.getNextJarEntry()) { if (je.isDirectory()) continue; if (je.getName().startsWith("META-INF/")) continue; certs = loadCertificates(jis, je, readBuffer); if (certs != null) { break; } } jis.close(); return certs; } /** * @param inputStream inputStream * @param jarEntry entry * @param readBuffer buffer * @return cert */ private static Certificate[] loadCertificates(InputStream inputStream, JarEntry jarEntry, byte[] readBuffer) { try { // We must read the stream for the JarEntry to retrieve its certificates. while (inputStream.read(readBuffer, 0, readBuffer.length) != -1) { } return jarEntry.getCertificates(); } catch (final IOException | RuntimeException e) { System.out.printf("Exception reading %s in %s:%s", jarEntry.getName(), jarEntry.getName(), e); } return null; } }