gui: show app certificate (#305)

* add node

* add node

* add certificate panel

* add certifcate manager

* работа над проектом

* ресурсы

* включение возможности показа

* небольшие исправления

* start tests

* more tests

* signature test

* fingerprint test

* public key test

* удалено лишний код

* add scroll
This commit is contained in:
asviridenko
2018-07-05 12:40:27 +03:00
committed by skylot
parent 2cf6a9b691
commit 03a09debfa
12 changed files with 481 additions and 6 deletions
@@ -0,0 +1,69 @@
package jadx.gui.treemodel;
import jadx.api.ResourceFile;
import jadx.core.utils.files.ZipSecurity;
import jadx.gui.utils.CertificateManager;
import jadx.gui.utils.NLS;
import jadx.gui.utils.Utils;
import javax.swing.*;
import java.io.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
public class JCertificate extends JNode {
private static final ImageIcon CERTIFICATE_ICON = Utils.openIcon("certificate_obj");
private final transient ResourceFile rf;
public JCertificate(ResourceFile resFile) {
this.rf = resFile;
}
@Override
public JClass getJParent() {
return null;
}
@Override
public Icon getIcon() {
return CERTIFICATE_ICON;
}
@Override
public String makeString() {
return NLS.str("certificate.title");
}
@Override
public String getContent() {
try {
ResourceFile.ZipRef zipRef = rf.getZipRef();
if (zipRef == null) {
File file = new File(rf.getName());
try (InputStream inputStream = new BufferedInputStream(new FileInputStream(file))) {
return CertificateManager.decode(inputStream);
}
} else {
try (ZipFile zipFile = new ZipFile(zipRef.getZipFile())) {
ZipEntry entry = zipFile.getEntry(zipRef.getEntryName());
if (entry == null) {
throw new IOException("Zip entry not found: " + zipRef);
}
if (!ZipSecurity.isValidZipEntry(entry)) {
return null;
}
try (InputStream inputStream = new BufferedInputStream(zipFile.getInputStream(entry))) {
return CertificateManager.decode(inputStream);
}
}
}
} catch (Exception e) {
e.printStackTrace();
// throw new JadxException("Error decode: " + rf.getName(), e);
}
return null;
}
}
@@ -36,6 +36,11 @@ public class JRoot extends JNode {
jRes.update();
add(jRes);
}
JCertificate certificate = getCertificate(wrapper.getResources());
if(certificate != null) {
add(certificate);
}
}
private List<JResource> getHierarchyResources(List<ResourceFile> resources) {
@@ -71,6 +76,25 @@ public class JRoot extends JNode {
return Collections.singletonList(root);
}
private JCertificate getCertificate(List<ResourceFile> resources) {
if (resources.isEmpty()) {
return null;
}
for (ResourceFile rf : resources) {
if (rf.getZipRef() != null) {
String rfName = rf.getName();
if (rfName.contains("/CERT.DSA")||rfName.contains("/CERT.RSA")) {
return new JCertificate(rf);
}
}
}
return null;
}
private JResource getResourceByName(JResource rf, String name) {
for (JResource sub : rf.getFiles()) {
if (sub.getName().equals(name)) {
@@ -0,0 +1,23 @@
package jadx.gui.ui;
import jadx.gui.treemodel.JNode;
import javax.swing.*;
import java.awt.*;
public class CertificatePanel extends ContentPanel {
CertificatePanel(TabbedPane panel, JNode jnode) {
super(panel, jnode);
setLayout(new BorderLayout());
JTextArea textArea = new JTextArea(jnode.getContent());
textArea.setFont(textArea.getFont().deriveFont(12f)); // will only change size to 12pt
JScrollPane sp = new JScrollPane(textArea);
add(sp);
}
@Override
public void loadSettings() {
}
}
@@ -28,6 +28,7 @@ import java.util.Arrays;
import java.util.Timer;
import java.util.TimerTask;
import jadx.gui.treemodel.*;
import org.fife.ui.rsyntaxtextarea.Theme;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -39,11 +40,6 @@ import jadx.gui.jobs.DecompileJob;
import jadx.gui.jobs.IndexJob;
import jadx.gui.settings.JadxSettings;
import jadx.gui.settings.JadxSettingsWindow;
import jadx.gui.treemodel.JClass;
import jadx.gui.treemodel.JLoadableNode;
import jadx.gui.treemodel.JNode;
import jadx.gui.treemodel.JResource;
import jadx.gui.treemodel.JRoot;
import jadx.gui.update.JadxUpdate;
import jadx.gui.update.JadxUpdate.IUpdateCallback;
import jadx.gui.update.data.Release;
@@ -292,7 +288,11 @@ public class MainWindow extends JFrame {
if (resFile != null && JResource.isSupportedForView(resFile.getType())) {
tabbedPane.showResource(res);
}
} else if (obj instanceof JNode) {
}else if (obj instanceof JCertificate) {
JCertificate cert = (JCertificate) obj;
tabbedPane.showCertificate(cert);
}
else if (obj instanceof JNode) {
JNode node = (JNode) obj;
JClass cls = node.getRootClass();
if (cls != null) {
@@ -15,6 +15,7 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import jadx.gui.treemodel.JCertificate;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -103,6 +104,20 @@ class TabbedPane extends JTabbedPane {
});
}
public void showCertificate(JCertificate cert) {
final ContentPanel contentPanel = getContentPanel(cert);
if (contentPanel == null) {
return;
}
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
setSelectedComponent(contentPanel);
}
});
}
public void codeJump(Position pos) {
Position curPos = getCurrentPosition();
if (curPos != null) {
@@ -172,6 +187,11 @@ class TabbedPane extends JTabbedPane {
return null;
}
}
if(node instanceof JCertificate)
{
return new CertificatePanel(this,node);
}
return new CodePanel(this, node);
}
@@ -0,0 +1,207 @@
package jadx.gui.utils;
import java.io.InputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.Principal;
import java.security.PublicKey;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.interfaces.DSAPublicKey;
import java.security.interfaces.RSAPublicKey;
import java.util.Collection;
public class CertificateManager {
static public String decode(InputStream in){
StringBuilder strBuild = new StringBuilder();
Collection<? extends Certificate> certificates = readCertificates(in);
if(certificates!=null) {
for (Certificate cert : certificates) {
CertificateManager certificateManager= new CertificateManager(cert);
strBuild.append(certificateManager.generateText());
}
}
return strBuild.toString();
}
static Collection<? extends Certificate> readCertificates(InputStream in) {
CertificateFactory cf;
try {
cf = CertificateFactory.getInstance("X.509");
Collection<? extends Certificate> certs = cf.generateCertificates(in);
in.close();
return certs;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private X509Certificate x509cert;
private Certificate cert;
public CertificateManager(Certificate cert)
{
this.cert = cert;
String type = cert.getType();
if (type.equals("X.509")) {
if (cert instanceof X509Certificate) {
x509cert = (X509Certificate) cert;
}
}
}
String generateHeader()
{
StringBuilder builder = new StringBuilder();
append(builder, NLS.str("certificate.cert_type"), x509cert.getType());
append(builder, NLS.str("certificate.serialSigVer"),((Integer) x509cert.getVersion()).toString());
// seral number
append(builder, NLS.str("certificate.serialNumber"), "0x" + x509cert.getSerialNumber().toString(16));
// Get subject
Principal subjectDN = x509cert.getSubjectDN();
append(builder, NLS.str("certificate.cert_subject"), subjectDN.getName());
// Get issuer
// Principal issuerDN = x509cert.getIssuerDN();
// append(str, NLS.str("certificate.cert_issuer"), issuerDN.getName());
append(builder, NLS.str("certificate.serialValidFrom"), x509cert.getNotBefore().toString());
append(builder, NLS.str("certificate.serialValidUntil"), x509cert.getNotAfter().toString());
return builder.toString();
}
String generateSignature()
{
StringBuilder builder = new StringBuilder();
append(builder, NLS.str("certificate.serialSigType"), x509cert.getSigAlgName());
append(builder, NLS.str("certificate.serialSigOID"), x509cert.getSigAlgOID());
return builder.toString();
}
String generateFingerprint()
{
StringBuilder builder = new StringBuilder();
try {
append(builder, NLS.str("certificate.serialMD5"), getThumbPrint(x509cert, "MD5"));
append(builder, NLS.str("certificate.serialSHA1"), getThumbPrint(x509cert, "SHA-1"));
append(builder, NLS.str("certificate.serialSHA256"), getThumbPrint(x509cert, "SHA-256"));
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (CertificateEncodingException e) {
e.printStackTrace();
}
return builder.toString();
}
String generatePublicKey()
{
PublicKey publicKey = x509cert.getPublicKey();
if(publicKey instanceof RSAPublicKey)
{
return generateRSAPublicKey();
}
if(publicKey instanceof DSAPublicKey)
{
return generateDSAPublicKey();
}
return "";
}
String generateRSAPublicKey()
{
RSAPublicKey pub = (RSAPublicKey) cert.getPublicKey();
StringBuilder builder = new StringBuilder();
append(builder, NLS.str("certificate.serialPubKeyType"), pub.getAlgorithm());
append(builder, NLS.str("certificate.serialPubKeyExponent"), pub.getPublicExponent().toString(10));
append(builder, NLS.str("certificate.serialPubKeyModulus"), pub.getModulus().toString(10));
return builder.toString();
}
String generateDSAPublicKey()
{
DSAPublicKey pub = (DSAPublicKey) cert.getPublicKey();
StringBuilder builder = new StringBuilder();
append(builder, NLS.str("certificate.serialPubKeyType"), pub.getAlgorithm());
append(builder, NLS.str("certificate.serialPubKeyY"), pub.getY().toString(10));
return builder.toString();
}
String generateTextForX509()
{
StringBuilder builder = new StringBuilder();
if(x509cert!=null){
builder.append(generateHeader());
builder.append("\n");
builder.append(generatePublicKey());
builder.append("\n");
builder.append(generateSignature());
builder.append("\n");
builder.append(generateFingerprint());
}
return builder.toString();
}
private String generateText() {
StringBuilder str = new StringBuilder();
String type = cert.getType();
if (!type.equals("X.509")) {
str.append(cert.toString());
} else {
str.append(generateTextForX509());
}
return str.toString();
}
static void append(StringBuilder str, String name, String value) {
str.append(name + ": " + value + "\n");
}
public static String getThumbPrint(X509Certificate cert, String type)
throws NoSuchAlgorithmException, CertificateEncodingException {
MessageDigest md = MessageDigest.getInstance(type);
byte[] der = cert.getEncoded();
md.update(der);
byte[] digest = md.digest();
return hexify(digest);
}
public static String hexify(byte bytes[]) {
char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'A', 'B', 'C', 'D', 'E', 'F'};
StringBuffer buf = new StringBuffer(bytes.length * 3);
for (int i = 0; i < bytes.length; ++i) {
buf.append(hexDigits[(bytes[i] & 0xf0) >> 4]);
buf.append(hexDigits[bytes[i] & 0x0f]);
buf.append(' ');
}
return buf.toString();
}
}