Skip to content

Commit

Permalink
parse all certificates
Browse files Browse the repository at this point in the history
  • Loading branch information
hsiafan committed Dec 5, 2017
1 parent d1c79dc commit 58e69aa
Show file tree
Hide file tree
Showing 7 changed files with 52 additions and 35 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Apk-parser has been submitted to maven central repo. With maven, you can add apk
<dependency>
<groupId>net.dongliu</groupId>
<artifactId>apk-parser</artifactId>
<version>2.4.1</version>
<version>2.4.2</version>
</dependency>
```
From version 2.0, apk-parser requires java7. The last version support java6 is 1.7.4.
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<artifactId>apk-parser</artifactId>
<name>apk-parser</name>
<packaging>jar</packaging>
<version>2.4.1</version>
<version>2.4.2</version>
<url>https://github.com/xiaxiaocao/apk-parser</url>
<developers>
<developer>
Expand Down
42 changes: 27 additions & 15 deletions src/main/java/net/dongliu/apk/parser/AbstractApkFile.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public abstract class AbstractApkFile implements Closeable {
private ApkMeta apkMeta;
private List<IconPath> iconPaths;

private List<CertificateMeta> certificateMetaList;
private Map<String, List<CertificateMeta>> certificateMetaMap;

private static final Locale DEFAULT_LOCALE = Locale.US;

Expand Down Expand Up @@ -74,27 +74,40 @@ public Set<Locale> getLocales() throws IOException {
}

/**
* get the apk's certificates.
* Get the apk's certificate meta. If have multi signature, return the certificate the first signature used.
*/
public List<CertificateMeta> getCertificateMetaList() throws IOException,
CertificateException {
if (this.certificateMetaList == null) {
parseCertificate();
if (certificateMetaMap == null) {
parseCertificates();
}
return this.certificateMetaList;
if (certificateMetaMap.isEmpty()) {
throw new ParserException("ApkFile certificate not found");
}
return certificateMetaMap.values().iterator().next();
}

protected abstract byte[] getCertificateData() throws IOException;
/**
* Get the apk's all certificates.
* For each entry, the key is certificate file path in apk file, the value is the certificates info of the certificate file.
*/
public Map<String, List<CertificateMeta>> getAllCertificateMetas() throws IOException, CertificateException {
if (certificateMetaMap == null) {
parseCertificates();
}
return this.certificateMetaMap;
}

private void parseCertificate() throws IOException, CertificateException {
protected abstract Map<String, byte[]> getAllCertificateData() throws IOException;

byte[] data = getCertificateData();
if (data == null) {
throw new ParserException("ApkFile certificate not found");
private void parseCertificates() throws IOException, CertificateException {
Map<String, byte[]> dataMap = getAllCertificateData();
certificateMetaMap = new LinkedHashMap<>();
for (Map.Entry<String, byte[]> entry : dataMap.entrySet()) {
CertificateParser parser = new CertificateParser(entry.getValue());
parser.parse();
certificateMetaMap.put(entry.getKey(), parser.getCertificateMetas());
}
CertificateParser parser = new CertificateParser(data);
parser.parse();
this.certificateMetaList = parser.getCertificateMetas();
}

private void parseManifest() throws IOException {
Expand Down Expand Up @@ -257,9 +270,8 @@ private void parseResourceTable() throws IOException {

@Override
public void close() throws IOException {
this.certificateMetaList = null;
this.certificateMetaMap = null;
this.resourceTable = null;
this.certificateMetaList = null;
this.iconPaths = null;
}

Expand Down
17 changes: 8 additions & 9 deletions src/main/java/net/dongliu/apk/parser/ApkFile.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;
Expand Down Expand Up @@ -36,23 +38,20 @@ public ApkFile(String filePath) throws IOException {
}

@Override
protected byte[] getCertificateData() throws IOException {
ZipEntry entry = null;
protected Map<String, byte[]> getAllCertificateData() throws IOException {
Enumeration<? extends ZipEntry> enu = zf.entries();
Map<String, byte[]> map = new LinkedHashMap<>();
while (enu.hasMoreElements()) {
ZipEntry ne = enu.nextElement();
if (ne.isDirectory()) {
continue;
}
if (ne.getName().toUpperCase().endsWith(".RSA") || ne.getName().toUpperCase().endsWith(".DSA")) {
entry = ne;
break;
String name = ne.getName().toUpperCase();
if (name.endsWith(".RSA") || name.endsWith(".DSA")) {
map.put(name, Utils.toByteArray(zf.getInputStream(ne)));
}
}
if (entry == null) {
return null;
}
return Utils.toByteArray(zf.getInputStream(entry));
return map;
}

@Override
Expand Down
12 changes: 8 additions & 4 deletions src/main/java/net/dongliu/apk/parser/ByteArrayApkFile.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

Expand All @@ -25,17 +27,19 @@ public ByteArrayApkFile(byte[] apkData) {
}

@Override
protected byte[] getCertificateData() throws IOException {
protected Map<String, byte[]> getAllCertificateData() throws IOException {
Map<String, byte[]> map = new LinkedHashMap<>();
try (InputStream in = new ByteArrayInputStream(apkData);
ZipInputStream zis = new ZipInputStream(in)) {
ZipEntry entry;
while ((entry = zis.getNextEntry()) != null) {
if (entry.getName().toUpperCase().endsWith(".RSA") || entry.getName().toUpperCase().endsWith(".DSA")) {
return Utils.toByteArray(zis);
String name = entry.getName();
if (name.toUpperCase().endsWith(".RSA") || name.toUpperCase().endsWith(".DSA")) {
map.put(name, Utils.toByteArray(zis));
}
}
}
return null;
return map;
}

@Override
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/net/dongliu/apk/parser/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
public class Main {
public static void main(String[] args) throws IOException, CertificateException {
try (ApkFile apkFile = new ApkFile(args[0])) {
System.out.println(apkFile.getApkMeta());
System.out.println(apkFile.getAllCertificateMetas());
}
}
}
10 changes: 6 additions & 4 deletions src/main/java/net/dongliu/apk/parser/bean/CertificateMeta.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package net.dongliu.apk.parser.bean;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
Expand All @@ -19,7 +20,7 @@ public class CertificateMeta {
* An OID is represented by a set of non-negative whole numbers separated by periods.
* For example, the string "1.2.840.10040.4.3" identifies the SHA-1 with DSA signature algorithm defined in
* <a href="http://www.ietf.org/rfc/rfc3279.txt">
* RFC 3279: Algorithms and Identifiers for the Internet X.509 Public Key Infrastructure Certificate and CRL Profile
* RFC 3279: Algorithms and Identifiers for the Internet X.509 Public Key Infrastructure Certificate and CRL Profile
* </a>.
*/
private String signAlgorithmOID;
Expand Down Expand Up @@ -108,9 +109,10 @@ public void setSignAlgorithmOID(String signAlgorithmOID) {

@Override
public String toString() {
return "signAlgorithm:\t" + signAlgorithm + '\n' +
"certBase64Md5:\t" + certBase64Md5 + '\n' +
"certMd5:\t" + certMd5;
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return "{signAlgorithm=" + signAlgorithm + ", " +
"certBase64Md5=" + certBase64Md5 + ", " +
"startDate=" + df.format(startDate) + "," + "endDate=" + df.format(endDate) + "}";
}
}

0 comments on commit 58e69aa

Please sign in to comment.