Skip to content

Instantly share code, notes, and snippets.

@rwestergren
Last active November 1, 2020 10:30
Show Gist options
  • Star 10 You must be signed in to star a gist
  • Fork 7 You must be signed in to fork a gist
  • Save rwestergren/648cca2c91b1b42b7f40 to your computer and use it in GitHub Desktop.
Save rwestergren/648cca2c91b1b42b7f40 to your computer and use it in GitHub Desktop.
GetAndroidSig
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.WeakReference;
import java.security.cert.CertificateEncodingException;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Main {
private static final Object mSync = new Object();
private static WeakReference<byte[]> mReadBuffer;
public static void main(String[] args) {
if (args.length < 1) {
System.out.println("Usage: java -jar GetAndroidSig.jar <apk/jar>");
System.exit(-1);
}
System.out.println(args[0]);
String mArchiveSourcePath = args[0];
WeakReference<byte[]> readBufferRef;
byte[] readBuffer = null;
synchronized (mSync) {
readBufferRef = mReadBuffer;
if (readBufferRef != null) {
mReadBuffer = null;
readBuffer = readBufferRef.get();
}
if (readBuffer == null) {
readBuffer = new byte[8192];
readBufferRef = new WeakReference<byte[]>(readBuffer);
}
}
try {
JarFile jarFile = new JarFile(mArchiveSourcePath);
java.security.cert.Certificate[] certs = null;
Enumeration entries = jarFile.entries();
while (entries.hasMoreElements()) {
JarEntry je = (JarEntry) entries.nextElement();
if (je.isDirectory()) {
continue;
}
if (je.getName().startsWith("META-INF/")) {
continue;
}
java.security.cert.Certificate[] localCerts = loadCertificates(jarFile, je, readBuffer);
if (false) {
System.out.println("File " + mArchiveSourcePath + " entry " + je.getName()
+ ": certs=" + certs + " ("
+ (certs != null ? certs.length : 0) + ")");
}
if (localCerts == null) {
System.err.println("Package has no certificates at entry "
+ je.getName() + "; ignoring!");
jarFile.close();
return;
} else if (certs == null) {
certs = localCerts;
} else {
// Ensure all certificates match.
for (int i = 0; i < certs.length; i++) {
boolean found = false;
for (int j = 0; j < localCerts.length; j++) {
if (certs[i] != null
&& certs[i].equals(localCerts[j])) {
found = true;
break;
}
}
if (!found || certs.length != localCerts.length) {
System.err.println("Package has mismatched certificates at entry "
+ je.getName() + "; ignoring!");
jarFile.close();
return; // false
}
}
}
}
jarFile.close();
synchronized (mSync) {
mReadBuffer = readBufferRef;
}
if (certs != null && certs.length > 0) {
final int N = certs.length;
for (int i = 0; i < N; i++) {
String charSig = new String(toChars(certs[i].getEncoded()));
System.out.println("Cert#: " + i + " Type:" + certs[i].getType()
+ "\nPublic key: " + certs[i].getPublicKey()
+ "\nHash code: " + certs[i].hashCode()
+ " / 0x" + Integer.toHexString(certs[i].hashCode())
+ "\nTo char: " + charSig);
}
} else {
System.err.println("Package has no certificates; ignoring!");
return;
}
} catch (CertificateEncodingException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException e) {
System.err.println("Exception reading " + mArchiveSourcePath + "\n" + e);
return;
} catch (RuntimeException e) {
System.err.println("Exception reading " + mArchiveSourcePath + "\n" + e);
return;
}
}
private static char[] toChars(byte[] mSignature) {
byte[] sig = mSignature;
final int N = sig.length;
final int N2 = N * 2;
char[] text = new char[N2];
for (int j = 0; j < N; j++) {
byte v = sig[j];
int d = (v >> 4) & 0xf;
text[j * 2] = (char) (d >= 10 ? ('a' + d - 10) : ('0' + d));
d = v & 0xf;
text[j * 2 + 1] = (char) (d >= 10 ? ('a' + d - 10) : ('0' + d));
}
return text;
}
private static java.security.cert.Certificate[] loadCertificates(JarFile jarFile, JarEntry je, byte[] readBuffer) {
try {
// We must read the stream for the JarEntry to retrieve
// its certificates.
InputStream is = jarFile.getInputStream(je);
while (is.read(readBuffer, 0, readBuffer.length) != -1) {
// not using
}
is.close();
return (java.security.cert.Certificate[]) (je != null ? je.getCertificates() : null);
} catch (IOException e) {
System.err.println("Exception reading " + je.getName() + " in "
+ jarFile.getName() + ": " + e);
}
return null;
}
}
Copy link

ghost commented Dec 22, 2015

decent approach, I've had to use a similar approach myself to obtain the signature for an app I was attempting to reverse because they rolled their api to utilize the signature to ensure requests originated from their app

@psychsecurity
Copy link

Awesome job ! I've done this manually once with a lot of pain.

@chuppito
Copy link

chuppito commented Aug 4, 2018

Hello, I got the signature of an application thanks to the tools getandroidsig.
How to be able to put it in file .pk8 and .pem
thank you in advance

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment