Search in sources :

Example 1 with ApkSigner

use of com.android.apksig.ApkSigner in project AndResGuard by shwenzhang.

the class ApkSignerTool method sign.

private static void sign(String[] params) throws Exception {
    if (params.length == 0) {
        printUsage(HELP_PAGE_SIGN);
        return;
    }
    File outputApk = null;
    File inputApk = null;
    boolean verbose = false;
    boolean v1SigningEnabled = true;
    boolean v2SigningEnabled = true;
    int minSdkVersion = 1;
    boolean minSdkVersionSpecified = false;
    int maxSdkVersion = Integer.MAX_VALUE;
    List<SignerParams> signers = new ArrayList<>(1);
    SignerParams signerParams = new SignerParams();
    OptionsParser optionsParser = new OptionsParser(params);
    String optionName;
    String optionOriginalForm = null;
    while ((optionName = optionsParser.nextOption()) != null) {
        optionOriginalForm = optionsParser.getOptionOriginalForm();
        if (("help".equals(optionName)) || ("h".equals(optionName))) {
            printUsage(HELP_PAGE_SIGN);
            return;
        } else if ("out".equals(optionName)) {
            outputApk = new File(optionsParser.getRequiredValue("Output file name"));
        } else if ("in".equals(optionName)) {
            inputApk = new File(optionsParser.getRequiredValue("Input file name"));
        } else if ("min-sdk-version".equals(optionName)) {
            minSdkVersion = optionsParser.getRequiredIntValue("Mininimum API Level");
            minSdkVersionSpecified = true;
        } else if ("max-sdk-version".equals(optionName)) {
            maxSdkVersion = optionsParser.getRequiredIntValue("Maximum API Level");
        } else if ("v1-signing-enabled".equals(optionName)) {
            v1SigningEnabled = optionsParser.getOptionalBooleanValue(true);
        } else if ("v2-signing-enabled".equals(optionName)) {
            v2SigningEnabled = optionsParser.getOptionalBooleanValue(true);
        } else if ("next-signer".equals(optionName)) {
            if (!signerParams.isEmpty()) {
                signers.add(signerParams);
                signerParams = new SignerParams();
            }
        } else if ("ks".equals(optionName)) {
            signerParams.keystoreFile = optionsParser.getRequiredValue("KeyStore file");
        } else if ("ks-key-alias".equals(optionName)) {
            signerParams.keystoreKeyAlias = optionsParser.getRequiredValue("KeyStore key alias");
        } else if ("ks-pass".equals(optionName)) {
            signerParams.keystorePasswordSpec = optionsParser.getRequiredValue("KeyStore password");
        } else if ("key-pass".equals(optionName)) {
            signerParams.keyPasswordSpec = optionsParser.getRequiredValue("Key password");
        } else if ("v1-signer-name".equals(optionName)) {
            signerParams.v1SigFileBasename = optionsParser.getRequiredValue("JAR signature file basename");
        } else if ("ks-type".equals(optionName)) {
            signerParams.keystoreType = optionsParser.getRequiredValue("KeyStore type");
        } else if ("ks-provider-name".equals(optionName)) {
            signerParams.keystoreProviderName = optionsParser.getRequiredValue("JCA KeyStore Provider name");
        } else if ("ks-provider-class".equals(optionName)) {
            signerParams.keystoreProviderClass = optionsParser.getRequiredValue("JCA KeyStore Provider class name");
        } else if ("ks-provider-arg".equals(optionName)) {
            signerParams.keystoreProviderArg = optionsParser.getRequiredValue("JCA KeyStore Provider constructor argument");
        } else if ("key".equals(optionName)) {
            signerParams.keyFile = optionsParser.getRequiredValue("Private key file");
        } else if ("cert".equals(optionName)) {
            signerParams.certFile = optionsParser.getRequiredValue("Certificate file");
        } else if (("v".equals(optionName)) || ("verbose".equals(optionName))) {
            verbose = optionsParser.getOptionalBooleanValue(true);
        } else {
            throw new ParameterException("Unsupported option: " + optionOriginalForm + ". See --help for supported" + " options.");
        }
    }
    if (!signerParams.isEmpty()) {
        signers.add(signerParams);
    }
    signerParams = null;
    if (signers.isEmpty()) {
        throw new ParameterException("At least one signer must be specified");
    }
    params = optionsParser.getRemainingParams();
    if (inputApk != null) {
        // parameters.
        if (params.length > 0) {
            throw new ParameterException("Unexpected parameter(s) after " + optionOriginalForm + ": " + params[0]);
        }
    } else {
        // supposed to be the path to input APK.
        if (params.length < 1) {
            throw new ParameterException("Missing input APK");
        } else if (params.length > 1) {
            throw new ParameterException("Unexpected parameter(s) after input APK (" + params[1] + ")");
        }
        inputApk = new File(params[0]);
    }
    if ((minSdkVersionSpecified) && (minSdkVersion > maxSdkVersion)) {
        throw new ParameterException("Min API Level (" + minSdkVersion + ") > max API Level (" + maxSdkVersion + ")");
    }
    List<ApkSigner.SignerConfig> signerConfigs = new ArrayList<>(signers.size());
    int signerNumber = 0;
    try (PasswordRetriever passwordRetriever = new PasswordRetriever()) {
        for (SignerParams signer : signers) {
            signerNumber++;
            signer.name = "signer #" + signerNumber;
            try {
                signer.loadPrivateKeyAndCerts(passwordRetriever);
            } catch (ParameterException e) {
                System.err.println("Failed to load signer \"" + signer.name + "\": " + e.getMessage());
                System.exit(2);
                return;
            } catch (Exception e) {
                System.err.println("Failed to load signer \"" + signer.name + "\"");
                e.printStackTrace();
                System.exit(2);
                return;
            }
            String v1SigBasename;
            if (signer.v1SigFileBasename != null) {
                v1SigBasename = signer.v1SigFileBasename;
            } else if (signer.keystoreKeyAlias != null) {
                v1SigBasename = signer.keystoreKeyAlias;
            } else if (signer.keyFile != null) {
                String keyFileName = new File(signer.keyFile).getName();
                int delimiterIndex = keyFileName.indexOf('.');
                if (delimiterIndex == -1) {
                    v1SigBasename = keyFileName;
                } else {
                    v1SigBasename = keyFileName.substring(0, delimiterIndex);
                }
            } else {
                throw new RuntimeException("Neither KeyStore key alias nor private key file available");
            }
            ApkSigner.SignerConfig signerConfig = new ApkSigner.SignerConfig.Builder(v1SigBasename, signer.privateKey, signer.certs).build();
            signerConfigs.add(signerConfig);
        }
    }
    if (outputApk == null) {
        outputApk = inputApk;
    }
    File tmpOutputApk;
    if (inputApk.getCanonicalPath().equals(outputApk.getCanonicalPath())) {
        tmpOutputApk = File.createTempFile("apksigner", ".apk");
        tmpOutputApk.deleteOnExit();
    } else {
        tmpOutputApk = outputApk;
    }
    ApkSigner.Builder apkSignerBuilder = new ApkSigner.Builder(signerConfigs).setInputApk(inputApk).setOutputApk(tmpOutputApk).setOtherSignersSignaturesPreserved(false).setV1SigningEnabled(v1SigningEnabled).setV2SigningEnabled(v2SigningEnabled);
    if (minSdkVersionSpecified) {
        apkSignerBuilder.setMinSdkVersion(minSdkVersion);
    }
    ApkSigner apkSigner = apkSignerBuilder.build();
    try {
        apkSigner.sign();
    } catch (MinSdkVersionException e) {
        String msg = e.getMessage();
        if (!msg.endsWith(".")) {
            msg += '.';
        }
        throw new MinSdkVersionException("Failed to determine APK's minimum supported platform version" + ". Use --min-sdk-version to override", e);
    }
    if (!tmpOutputApk.getCanonicalPath().equals(outputApk.getCanonicalPath())) {
        Files.move(tmpOutputApk.toPath(), outputApk.toPath(), StandardCopyOption.REPLACE_EXISTING);
    }
    if (verbose) {
        System.out.println("Signed");
    }
}
Also used : ArrayList(java.util.ArrayList) InvalidKeySpecException(java.security.spec.InvalidKeySpecException) KeyStoreException(java.security.KeyStoreException) UnrecoverableKeyException(java.security.UnrecoverableKeyException) MinSdkVersionException(com.android.apksig.apk.MinSdkVersionException) IOException(java.io.IOException) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) InvalidKeyException(java.security.InvalidKeyException) File(java.io.File) ApkSigner(com.android.apksig.ApkSigner) MinSdkVersionException(com.android.apksig.apk.MinSdkVersionException)

Aggregations

ApkSigner (com.android.apksig.ApkSigner)1 MinSdkVersionException (com.android.apksig.apk.MinSdkVersionException)1 File (java.io.File)1 IOException (java.io.IOException)1 InvalidKeyException (java.security.InvalidKeyException)1 KeyStoreException (java.security.KeyStoreException)1 NoSuchAlgorithmException (java.security.NoSuchAlgorithmException)1 UnrecoverableKeyException (java.security.UnrecoverableKeyException)1 InvalidKeySpecException (java.security.spec.InvalidKeySpecException)1 ArrayList (java.util.ArrayList)1