-
-
Save alipov/322542a976155760c8dd to your computer and use it in GitHub Desktop.
GetAndroidSig
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment