Skip to content

Instantly share code, notes, and snippets.

@strazzere
Created September 16, 2014 06:40
Show Gist options
  • Save strazzere/5511cab3be4b4ad73906 to your computer and use it in GitHub Desktop.
Save strazzere/5511cab3be4b4ad73906 to your computer and use it in GitHub Desktop.
Leaked Bangle Signer Source
package com.bangcle.signer;
public class LocalStore
{
public static String APK_PATH = "";
public static String KEYSTORE_PATH = "";
public static String KEYSTORE_PWD = "";
public static String KEY_ALIAS = "";
public static String KEY_PWD = "";
public static String DESTINATION = "";
public static void setApkPath(String value)
{
APK_PATH = value;
System.out.println(APK_PATH);
}
public static void setKeystorePath(String value)
{
KEYSTORE_PATH = value;
System.out.println(KEYSTORE_PATH);
}
public static void setKeystorePassword(String value)
{
KEYSTORE_PWD = value;
System.out.println(KEYSTORE_PWD);
}
public static void setKeyAlias(String value)
{
KEY_ALIAS = value;
System.out.println(KEY_ALIAS);
}
public static void setKeyPassword(String value)
{
KEY_PWD = value;
System.out.println(KEY_PWD);
}
public static void setDestinationName(String value)
{
DESTINATION = value;
System.out.println(DESTINATION);
}
}
package com.bangcle.signer;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.util.Enumeration;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
public class main {
protected Shell shell;
private Composite mTopComposite;
private Text mProjectText;
private Composite mErrorComposite;
private Label mUseExistingKeystore;
private Text mKeystore;
private Text mKeystorePassword;
private Label mKeyAliasesLabel;
private Combo mKeyAliases;
private Label mKeyPasswordLabel;
private Text mKeyPassword;
private Text mDestination;
private Label mDestinationMsg;
/**
* Launch the application.
* @param args
*/
public static void main(String[] args) {
try {
main window = new main();
window.open();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Open the window.
*/
public void open() {
Display display = Display.getDefault();
createContents();
shell.open();
shell.layout();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
}
/**
* Create contents of the window.
*/
protected void createContents() {
shell = new Shell();
shell.setSize(600, 400);
shell.setText("Bangcle Signer");
shell.setLayout(new GridLayout());
GridLayout gl = null;
GridData gd = null;
mTopComposite = new Composite(shell, SWT.NONE);
mTopComposite.setLayoutData(new GridData(GridData.FILL_BOTH));
mTopComposite.setLayout(new GridLayout(1, false));
// composite for the project selection.
Composite projectComposite = new Composite(mTopComposite, SWT.NONE);
projectComposite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
projectComposite.setLayout(gl = new GridLayout(3, false));
gl.marginHeight = gl.marginWidth = 0;
Label label = new Label(projectComposite, SWT.NONE);
label.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
gd.horizontalSpan = 3;
label.setText("Select the APK to sign:");
new Label(projectComposite, SWT.NONE).setText("APK:");
mProjectText = new Text(projectComposite, SWT.BORDER);
mProjectText.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
mProjectText.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent e) {
LocalStore.setApkPath(mProjectText.getText().trim());
}
});
final Button browseButton = new Button(projectComposite, SWT.PUSH);
browseButton.setText("Browse...");
browseButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
FileDialog fileDialog;
fileDialog = new FileDialog(browseButton.getShell(),SWT.OPEN);
fileDialog.setText("Load Keystore");
String fileName = fileDialog.open();
if (fileName != null) {
mProjectText.setText(fileName);
}
}
});
Composite composite = new Composite(shell, SWT.NULL);
composite.setLayoutData(new GridData(GridData.FILL_BOTH));
GridLayout gl2 = new GridLayout(3, false);
composite.setLayout(gl2);
GridData gd2;
mUseExistingKeystore = new Label(composite, SWT.NULL);
mUseExistingKeystore.setText("Use existing keystore");
mUseExistingKeystore.setLayoutData(gd2 = new GridData(GridData.FILL_HORIZONTAL));
gd2.horizontalSpan = 3;
new Label(composite, SWT.NONE).setText("Location:");
mKeystore = new Text(composite, SWT.BORDER);
mKeystore.setLayoutData(gd2 = new GridData(GridData.FILL_HORIZONTAL));
final Button browseButton2 = new Button(composite, SWT.PUSH);
browseButton2.setText("Browse...");
browseButton2.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
FileDialog fileDialog;
fileDialog = new FileDialog(browseButton2.getShell(),SWT.OPEN);
fileDialog.setText("Load Keystore");
String fileName = fileDialog.open();
if (fileName != null) {
mKeystore.setText(fileName);
}
}
});
new Label(composite, SWT.NONE).setText("Password:");
mKeystorePassword = new Text(composite, SWT.BORDER | SWT.PASSWORD);
mKeystorePassword.setLayoutData(gd2 = new GridData(GridData.FILL_HORIZONTAL));
new Composite(composite, SWT.NONE).setLayoutData(gd2 = new GridData());
gd2.heightHint = gd2.widthHint = 0;
mKeyAliasesLabel = new Label(composite, SWT.NONE);
mKeyAliasesLabel.setText("Alias:");
mKeyAliases = new Combo(composite, SWT.READ_ONLY);
mKeyAliases.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
mKeyAliasesLabel.setEnabled(false);
mKeyAliases.setEnabled(false);
new Composite(composite, SWT.NONE).setLayoutData(gd = new GridData());
gd.heightHint = 0;
gd.widthHint = 50;
mKeyPasswordLabel = new Label(composite, SWT.NONE);
mKeyPasswordLabel.setText("Password:");
mKeyPassword = new Text(composite, SWT.BORDER | SWT.PASSWORD);
mKeyPassword.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
mKeyPassword.setEnabled(false);
mKeyPasswordLabel.setEnabled(false);
mKeystore.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent e) {
LocalStore.setKeystorePath(mKeystore.getText().trim());
onChange();
}
});
mKeystorePassword.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent e) {
LocalStore.setKeystorePassword(mKeystorePassword.getText());
onChange();
}
});
mKeyAliases.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
LocalStore.setKeyAlias(mKeyAliases.getItem(mKeyAliases.getSelectionIndex()));
// reset the password
mKeyPassword.setText("");
}
});
mKeyPassword.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent e) {
LocalStore.setKeyPassword(mKeyPassword.getText());
}
});
Composite composite3 = new Composite(shell, SWT.NULL);
composite3.setLayoutData(new GridData(GridData.FILL_BOTH));
GridLayout gl3 = new GridLayout(3, false);
composite3.setLayout(gl3);
GridData gd3;
mDestinationMsg = new Label(composite3, SWT.NULL);
mDestinationMsg.setText("Enter destination for the APK file.");
mDestinationMsg.setLayoutData(gd3 = new GridData(GridData.FILL_HORIZONTAL));
gd3.horizontalSpan = 3;
new Label(composite3, SWT.NONE).setText("Destination APK file:");
mDestination = new Text(composite3, SWT.BORDER);
mDestination.setLayoutData(gd3 = new GridData(GridData.FILL_HORIZONTAL));
mDestination.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent e) {
onDestinationChange();
}
});
final Button browseButton3 = new Button(composite3, SWT.PUSH);
browseButton3.setText("Browse...");
new Label(composite3, SWT.NONE);
new Label(composite3, SWT.NONE);
browseButton3.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
FileDialog fileDialog = new FileDialog(browseButton3.getShell(), SWT.SAVE);
fileDialog.setText("Destination file name");
String saveLocation = fileDialog.open();
if (saveLocation != null) {
mDestination.setText(saveLocation);
}
}
});
GridData gd4;
final Button OkButton = new Button(shell, SWT.CENTER);
OkButton.setText("Sign Now");
OkButton.setLayoutData(gd4 = new GridData(GridData.HORIZONTAL_ALIGN_CENTER));
OkButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(final SelectionEvent e)
{
System.out.println("Thread1 = "+Thread.currentThread().getName());
if(LocalStore.APK_PATH.equals("")
|| LocalStore.KEYSTORE_PATH.equals("")
|| LocalStore.KEYSTORE_PWD.equals("")
|| LocalStore.KEY_ALIAS.equals("")
|| LocalStore.DESTINATION.equals(""))
{
Display.getDefault().asyncExec(new Runnable() {
public void run() {
int style = SWT.APPLICATION_MODAL | SWT.YES;
MessageBox messageBox = new MessageBox(shell, style);
messageBox.setText("Error");
messageBox.setMessage("You should fill in all the blanks before signing!");
e.doit = messageBox.open() == SWT.YES;
}
});
return;
}
Thread t = new Thread()
{
@Override
public void run()
{
System.out.println("Thread2 = "+Thread.currentThread().getName());
Runtime rn = Runtime.getRuntime();
Process proc = null;
String exeFile = "cmd /c .\\java1.6.0\\bin\\jarsigner.exe -verbose -keystore "+LocalStore.KEYSTORE_PATH
+" -storepass "+LocalStore.KEYSTORE_PWD
+" -signedjar "+LocalStore.DESTINATION+" "+LocalStore.APK_PATH+" "+LocalStore.KEY_ALIAS;
System.out.println("Sign cmd = "+exeFile);
try {
proc = rn.exec(exeFile);
InputStream stdin = proc.getInputStream();
InputStreamReader isr = new InputStreamReader(stdin);
BufferedReader br = new BufferedReader(isr);
String line = null;
System.out.println("<OUTPUT>");
while ( (line = br.readLine()) != null)
System.out.println(line);
System.out.println("</OUTPUT>");
final int exitVal = proc.waitFor();
System.out.println("Process exitValue: " + exitVal);
Display.getDefault().asyncExec(new Runnable() {
public void run() {
int style = SWT.APPLICATION_MODAL | SWT.YES;
MessageBox messageBox = new MessageBox(shell, style);
messageBox.setText("Sign status");
if(exitVal == 0)
messageBox.setMessage("Sign success!");
else
messageBox.setMessage("Sign fail!");
e.doit = messageBox.open() == SWT.YES;
}
});
} catch (Exception e1) {
e1.printStackTrace();
System.out.println("error = "+e1.getMessage());
}
}
};
t.start();
}
});
}
private void onChange()
{
if(mKeystore.getText().trim().length()>0 && mKeystorePassword.getText().length()>0)
{
try {
// remove the content of the alias combo always and first, in case the
// keystore password is wrong
mKeyAliases.removeAll();
// get the alias list (also used as a keystore password test)
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
FileInputStream fis = new FileInputStream(LocalStore.KEYSTORE_PATH);
keyStore.load(fis, LocalStore.KEYSTORE_PWD.toCharArray());
fis.close();
Enumeration<String> aliases = keyStore.aliases();
int count = 0;
while (aliases.hasMoreElements()) {
String alias = aliases.nextElement();
mKeyAliases.add(alias);
count++;
}
if(count != 0)
{
mKeyAliasesLabel.setEnabled(true);
mKeyAliases.setEnabled(true);
mKeyPassword.setEnabled(true);
mKeyPasswordLabel.setEnabled(true);
mKeyAliases.select(0);
LocalStore.setKeyAlias(mKeyAliases.getItem(0));
}
else
{
mKeyAliasesLabel.setEnabled(false);
mKeyAliases.setEnabled(false);
mKeyPassword.setEnabled(false);
mKeyPasswordLabel.setEnabled(false);
}
// reset the password
mKeyPassword.setText("");
} catch (KeyStoreException e) {
System.out.println(e.getMessage());
} catch (FileNotFoundException e) {
System.out.println(e.getMessage());
} catch (NoSuchAlgorithmException e) {
System.out.println(e.getMessage());
} catch (CertificateException e) {
System.out.println(e.getMessage());
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
else
{
mKeyAliasesLabel.setEnabled(false);
mKeyAliases.setEnabled(false);
mKeyPassword.setEnabled(false);
mKeyPasswordLabel.setEnabled(false);
}
}
private void onDestinationChange()
{
setMessage("");
String path = mDestination.getText().trim();
if (path.length() == 0) {
setMessage("Enter destination for the APK file.");
// reset canFinish in the wizard.
LocalStore.DESTINATION = "";
return;
}
File file = new File(path);
if (file.isDirectory()) {
setMessage("ERROR: Destination is a directory.");
// reset canFinish in the wizard.
LocalStore.DESTINATION = "";
return;
}
File parentFolder = file.getParentFile();
if (parentFolder == null || parentFolder.isDirectory() == false) {
setMessage("ERROR: Not a valid directory.");
// reset canFinish in the wizard.
LocalStore.DESTINATION = "";
return;
}
boolean fileExists = false;
if (file.isFile())
fileExists = true;
else
{
setMessage(path);
}
// no error, set the destination in the wizard.
LocalStore.setDestinationName(mDestination.getText());
// However, we should also test if the file already exists.
if (fileExists) {
setMessage("WARNING: A destination file already exists.");
}
}
private void setMessage(String msg)
{
mDestinationMsg.setText(msg);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment