Search in sources :

Example 1 with ApkVerifier

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

the class ApkSignerTool method verify.

private static void verify(String[] params) throws Exception {
    if (params.length == 0) {
        printUsage(HELP_PAGE_VERIFY);
        return;
    }
    File inputApk = null;
    int minSdkVersion = 1;
    boolean minSdkVersionSpecified = false;
    int maxSdkVersion = Integer.MAX_VALUE;
    boolean maxSdkVersionSpecified = false;
    boolean printCerts = false;
    boolean verbose = false;
    boolean warningsTreatedAsErrors = false;
    OptionsParser optionsParser = new OptionsParser(params);
    String optionName;
    String optionOriginalForm = null;
    while ((optionName = optionsParser.nextOption()) != null) {
        optionOriginalForm = optionsParser.getOptionOriginalForm();
        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");
            maxSdkVersionSpecified = true;
        } else if ("print-certs".equals(optionName)) {
            printCerts = optionsParser.getOptionalBooleanValue(true);
        } else if (("v".equals(optionName)) || ("verbose".equals(optionName))) {
            verbose = optionsParser.getOptionalBooleanValue(true);
        } else if ("Werr".equals(optionName)) {
            warningsTreatedAsErrors = optionsParser.getOptionalBooleanValue(true);
        } else if (("help".equals(optionName)) || ("h".equals(optionName))) {
            printUsage(HELP_PAGE_VERIFY);
            return;
        } else if ("in".equals(optionName)) {
            inputApk = new File(optionsParser.getRequiredValue("Input APK file"));
        } else {
            throw new ParameterException("Unsupported option: " + optionOriginalForm + ". See --help for supported" + " options.");
        }
    }
    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 input APK.
        if (params.length < 1) {
            throw new ParameterException("Missing APK");
        } else if (params.length > 1) {
            throw new ParameterException("Unexpected parameter(s) after APK (" + params[1] + ")");
        }
        inputApk = new File(params[0]);
    }
    if ((minSdkVersionSpecified) && (maxSdkVersionSpecified) && (minSdkVersion > maxSdkVersion)) {
        throw new ParameterException("Min API Level (" + minSdkVersion + ") > max API Level (" + maxSdkVersion + ")");
    }
    ApkVerifier.Builder apkVerifierBuilder = new ApkVerifier.Builder(inputApk);
    if (minSdkVersionSpecified) {
        apkVerifierBuilder.setMinCheckedPlatformVersion(minSdkVersion);
    }
    if (maxSdkVersionSpecified) {
        apkVerifierBuilder.setMaxCheckedPlatformVersion(maxSdkVersion);
    }
    ApkVerifier apkVerifier = apkVerifierBuilder.build();
    ApkVerifier.Result result;
    try {
        result = apkVerifier.verify();
    } 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);
    }
    boolean verified = result.isVerified();
    boolean warningsEncountered = false;
    if (verified) {
        List<X509Certificate> signerCerts = result.getSignerCertificates();
        if (verbose) {
            System.out.println("Verifies");
            System.out.println("Verified using v1 scheme (JAR signing): " + result.isVerifiedUsingV1Scheme());
            System.out.println("Verified using v2 scheme (APK Signature Scheme v2): " + result.isVerifiedUsingV2Scheme());
            System.out.println("Number of signers: " + signerCerts.size());
        }
        if (printCerts) {
            int signerNumber = 0;
            MessageDigest sha256 = MessageDigest.getInstance("SHA-256");
            MessageDigest sha1 = MessageDigest.getInstance("SHA-1");
            MessageDigest md5 = MessageDigest.getInstance("MD5");
            for (X509Certificate signerCert : signerCerts) {
                signerNumber++;
                System.out.println("Signer #" + signerNumber + " certificate DN" + ": " + signerCert.getSubjectDN());
                byte[] encodedCert = signerCert.getEncoded();
                System.out.println("Signer #" + signerNumber + " certificate SHA-256 digest: " + HexEncoding.encode(sha256.digest(encodedCert)));
                System.out.println("Signer #" + signerNumber + " certificate SHA-1 digest: " + HexEncoding.encode(sha1.digest(encodedCert)));
                System.out.println("Signer #" + signerNumber + " certificate MD5 digest: " + HexEncoding.encode(md5.digest(encodedCert)));
                if (verbose) {
                    PublicKey publicKey = signerCert.getPublicKey();
                    System.out.println("Signer #" + signerNumber + " key algorithm: " + publicKey.getAlgorithm());
                    int keySize = -1;
                    if (publicKey instanceof RSAKey) {
                        keySize = ((RSAKey) publicKey).getModulus().bitLength();
                    } else if (publicKey instanceof ECKey) {
                        keySize = ((ECKey) publicKey).getParams().getOrder().bitLength();
                    } else if (publicKey instanceof DSAKey) {
                        // DSA parameters may be inherited from the certificate. We
                        // don't handle this case at the moment.
                        DSAParams dsaParams = ((DSAKey) publicKey).getParams();
                        if (dsaParams != null) {
                            keySize = dsaParams.getP().bitLength();
                        }
                    }
                    System.out.println("Signer #" + signerNumber + " key size (bits): " + ((keySize != -1) ? String.valueOf(keySize) : "n/a"));
                    byte[] encodedKey = publicKey.getEncoded();
                    System.out.println("Signer #" + signerNumber + " public key SHA-256 digest: " + HexEncoding.encode(sha256.digest(encodedKey)));
                    System.out.println("Signer #" + signerNumber + " public key SHA-1 digest: " + HexEncoding.encode(sha1.digest(encodedKey)));
                    System.out.println("Signer #" + signerNumber + " public key MD5 digest: " + HexEncoding.encode(md5.digest(encodedKey)));
                }
            }
        }
    } else {
        System.err.println("DOES NOT VERIFY");
    }
    for (ApkVerifier.IssueWithParams error : result.getErrors()) {
        System.err.println("ERROR: " + error);
    }
    // false positive -- this resource is not opened here
    @SuppressWarnings("resource") PrintStream warningsOut = (warningsTreatedAsErrors) ? System.err : System.out;
    for (ApkVerifier.IssueWithParams warning : result.getWarnings()) {
        warningsEncountered = true;
        warningsOut.println("WARNING: " + warning);
    }
    for (ApkVerifier.Result.V1SchemeSignerInfo signer : result.getV1SchemeSigners()) {
        String signerName = signer.getName();
        for (ApkVerifier.IssueWithParams error : signer.getErrors()) {
            System.err.println("ERROR: JAR signer " + signerName + ": " + error);
        }
        for (ApkVerifier.IssueWithParams warning : signer.getWarnings()) {
            warningsEncountered = true;
            warningsOut.println("WARNING: JAR signer " + signerName + ": " + warning);
        }
    }
    for (ApkVerifier.Result.V2SchemeSignerInfo signer : result.getV2SchemeSigners()) {
        String signerName = "signer #" + (signer.getIndex() + 1);
        for (ApkVerifier.IssueWithParams error : signer.getErrors()) {
            System.err.println("ERROR: APK Signature Scheme v2 " + signerName + ": " + error);
        }
        for (ApkVerifier.IssueWithParams warning : signer.getWarnings()) {
            warningsEncountered = true;
            warningsOut.println("WARNING: APK Signature Scheme v2 " + signerName + ": " + warning);
        }
    }
    if (!verified) {
        System.exit(1);
        return;
    }
    if ((warningsTreatedAsErrors) && (warningsEncountered)) {
        System.exit(1);
        return;
    }
}
Also used : RSAKey(java.security.interfaces.RSAKey) ECKey(java.security.interfaces.ECKey) DSAParams(java.security.interfaces.DSAParams) DSAKey(java.security.interfaces.DSAKey) MessageDigest(java.security.MessageDigest) MinSdkVersionException(com.android.apksig.apk.MinSdkVersionException) PrintStream(java.io.PrintStream) PublicKey(java.security.PublicKey) X509Certificate(java.security.cert.X509Certificate) ApkVerifier(com.android.apksig.ApkVerifier) File(java.io.File)

Aggregations

ApkVerifier (com.android.apksig.ApkVerifier)1 MinSdkVersionException (com.android.apksig.apk.MinSdkVersionException)1 File (java.io.File)1 PrintStream (java.io.PrintStream)1 MessageDigest (java.security.MessageDigest)1 PublicKey (java.security.PublicKey)1 X509Certificate (java.security.cert.X509Certificate)1 DSAKey (java.security.interfaces.DSAKey)1 DSAParams (java.security.interfaces.DSAParams)1 ECKey (java.security.interfaces.ECKey)1 RSAKey (java.security.interfaces.RSAKey)1