diff -Nru android-platform-tools-apksig-0.5+git165~g42d07eb/debian/changelog android-platform-tools-apksig-0.5+git168~g10c9d71/debian/changelog --- android-platform-tools-apksig-0.5+git165~g42d07eb/debian/changelog 2017-03-10 12:58:11.000000000 +0000 +++ android-platform-tools-apksig-0.5+git168~g10c9d71/debian/changelog 2017-04-04 21:16:47.000000000 +0000 @@ -1,3 +1,15 @@ +android-platform-tools-apksig (0.5+git168~g10c9d71-1~yakkety) yakkety; urgency=medium + + * Backport to yakkety + + -- Hans-Christoph Steiner Tue, 04 Apr 2017 23:16:17 +0200 + +android-platform-tools-apksig (0.5+git168~g10c9d71-1) unstable; urgency=medium + + * New upstream release (Closes: #859541) + + -- Hans-Christoph Steiner Tue, 04 Apr 2017 21:25:56 +0200 + android-platform-tools-apksig (0.5+git165~g42d07eb-1) unstable; urgency=medium * New upstream release (Closes: #857027) diff -Nru android-platform-tools-apksig-0.5+git165~g42d07eb/debian/control android-platform-tools-apksig-0.5+git168~g10c9d71/debian/control --- android-platform-tools-apksig-0.5+git165~g42d07eb/debian/control 2017-03-10 12:58:11.000000000 +0000 +++ android-platform-tools-apksig-0.5+git168~g10c9d71/debian/control 2017-04-04 21:14:42.000000000 +0000 @@ -6,15 +6,14 @@ Build-Depends: antlr3, bash-completion, debhelper (>= 10), - default-jdk-headless | default-jdk (>= 1:1.6), + default-jdk-headless (>= 2:1.8) | default-jdk (>= 2:1.8) | openjdk-8-jdk, gradle-debian-helper, groovy, javahelper, junit4, maven-debian-helper, maven-repo-helper, - pandoc, - proguard + pandoc Standards-Version: 3.9.8 Vcs-Browser: https://anonscm.debian.org/cgit/android-tools/android-platform-tools-apksig.git Vcs-Git: https://anonscm.debian.org/git/android-tools/android-platform-tools-apksig.git diff -Nru android-platform-tools-apksig-0.5+git165~g42d07eb/debian/README.source android-platform-tools-apksig-0.5+git168~g10c9d71/debian/README.source --- android-platform-tools-apksig-0.5+git165~g42d07eb/debian/README.source 1970-01-01 00:00:00.000000000 +0000 +++ android-platform-tools-apksig-0.5+git168~g10c9d71/debian/README.source 2017-04-04 20:36:21.000000000 +0000 @@ -0,0 +1,25 @@ + +This package is normally built as part of the whole Android SDK and +ends up being included in the "build-tools" package. So the release +tags will match all of the various android-platform-* packages. To +make this extra confusing, they also publish a standalone JAR library +of this project with a separate versioning scheme, matching the Gradle +Android Plugin versions. + +The source for this can some from two places: + +* https://android.googlesource.com/platform/tools/apksig.git +* https://jcenter.bintray.com/com/android/tools/build/apksig/2.5.0-alpha-preview-01/apksig-2.5.0-alpha-preview-01-sources.jar + +This package started from the git repo, but Google never tags releases +there with rational tags. The release versions never show up in the +git tags. But using `diff` or `meld`, it is easy to see which +released source jar matches which git revision: + + unzip apksig-2.5.0-alpha-preview-01-sources.jar + meld /path/to/android-platform-tools-apksig/src/main/java/com/ com/ + +The source JAR does not include the gradle build files, but this +package only uses the .java files anyway. + + -- Hans-Christoph Steiner , Tue, 4 Apr 2017 22:36:21 +0200 diff -Nru android-platform-tools-apksig-0.5+git165~g42d07eb/debian/rules android-platform-tools-apksig-0.5+git168~g10c9d71/debian/rules --- android-platform-tools-apksig-0.5+git165~g42d07eb/debian/rules 2017-03-10 12:58:11.000000000 +0000 +++ android-platform-tools-apksig-0.5+git168~g10c9d71/debian/rules 2017-04-04 19:51:33.000000000 +0000 @@ -9,7 +9,7 @@ %: dh $@ --with maven_repo_helper,javahelper,bash-completion --buildsystem=gradle -tarball_name = 42d07eb +tarball_name = 10c9d71d48ff2db01a2d1f157651036494f569f7 override_dh_auto_build: debian/apksigner.1 dh_auto_build diff -Nru android-platform-tools-apksig-0.5+git165~g42d07eb/src/apksigner/java/com/android/apksigner/ApkSignerTool.java android-platform-tools-apksig-0.5+git168~g10c9d71/src/apksigner/java/com/android/apksigner/ApkSignerTool.java --- android-platform-tools-apksig-0.5+git165~g42d07eb/src/apksigner/java/com/android/apksigner/ApkSignerTool.java 2017-03-10 13:07:33.000000000 +0000 +++ android-platform-tools-apksig-0.5+git168~g10c9d71/src/apksigner/java/com/android/apksigner/ApkSignerTool.java 2017-04-04 20:00:59.000000000 +0000 @@ -41,6 +41,7 @@ import java.security.PrivateKey; import java.security.Provider; import java.security.PublicKey; +import java.security.Security; import java.security.UnrecoverableKeyException; import java.security.cert.Certificate; import java.security.cert.CertificateFactory; @@ -122,6 +123,8 @@ int maxSdkVersion = Integer.MAX_VALUE; List signers = new ArrayList<>(1); SignerParams signerParams = new SignerParams(); + List providers = new ArrayList<>(); + ProviderInstallSpec providerParams = new ProviderInstallSpec(); OptionsParser optionsParser = new OptionsParser(params); String optionName; String optionOriginalForm = null; @@ -179,6 +182,20 @@ signerParams.certFile = optionsParser.getRequiredValue("Certificate file"); } else if (("v".equals(optionName)) || ("verbose".equals(optionName))) { verbose = optionsParser.getOptionalBooleanValue(true); + } else if ("next-provider".equals(optionName)) { + if (!providerParams.isEmpty()) { + providers.add(providerParams); + providerParams = new ProviderInstallSpec(); + } + } else if ("provider-class".equals(optionName)) { + providerParams.className = + optionsParser.getRequiredValue("JCA Provider class name"); + } else if ("provider-arg".equals(optionName)) { + providerParams.constructorParam = + optionsParser.getRequiredValue("JCA Provider constructor argument"); + } else if ("provider-pos".equals(optionName)) { + providerParams.position = + optionsParser.getRequiredIntValue("JCA Provider position"); } else { throw new ParameterException( "Unsupported option: " + optionOriginalForm + ". See --help for supported" @@ -189,6 +206,10 @@ signers.add(signerParams); } signerParams = null; + if (!providerParams.isEmpty()) { + providers.add(providerParams); + } + providerParams = null; if (signers.isEmpty()) { throw new ParameterException("At least one signer must be specified"); @@ -219,6 +240,11 @@ + ")"); } + // Install additional JCA Providers + for (ProviderInstallSpec providerInstallSpec : providers) { + providerInstallSpec.installProvider(); + } + List signerConfigs = new ArrayList<>(signers.size()); int signerNumber = 0; try (PasswordRetriever passwordRetriever = new PasswordRetriever()) { @@ -531,6 +557,46 @@ } } + private static class ProviderInstallSpec { + String className; + String constructorParam; + Integer position; + + private boolean isEmpty() { + return (className == null) && (constructorParam == null) && (position == null); + } + + private void installProvider() throws Exception { + if (className == null) { + throw new ParameterException( + "JCA Provider class name (--provider-class) must be specified"); + } + + Class providerClass = Class.forName(className); + if (!Provider.class.isAssignableFrom(providerClass)) { + throw new ParameterException( + "JCA Provider class " + providerClass + " not subclass of " + + Provider.class.getName()); + } + Provider provider; + if (constructorParam != null) { + // Single-arg Provider constructor + provider = + (Provider) providerClass.getConstructor(String.class) + .newInstance(constructorParam); + } else { + // No-arg Provider constructor + provider = (Provider) providerClass.getConstructor().newInstance(); + } + + if (position == null) { + Security.addProvider(provider); + } else { + Security.insertProviderAt(provider, position); + } + } + } + private static class SignerParams { String name; @@ -623,17 +689,18 @@ } // 2. Load the KeyStore - List keystorePasswords = null; - if ("NONE".equals(keystoreFile)) { - ks.load(null); - } else { + List keystorePasswords; + { String keystorePasswordSpec = (this.keystorePasswordSpec != null) ? this.keystorePasswordSpec : PasswordRetriever.SPEC_STDIN; keystorePasswords = passwordRetriever.getPasswords( keystorePasswordSpec, "Keystore password for " + name); - loadKeyStoreFromFile(ks, keystoreFile, keystorePasswords); + loadKeyStoreFromFile( + ks, + "NONE".equals(keystoreFile) ? null : keystoreFile, + keystorePasswords); } // 3. Load the PrivateKey and cert chain from KeyStore @@ -725,13 +792,23 @@ } } + /** + * Loads the password-protected keystore from storage. + * + * @param file file backing the keystore or {@code null} if the keystore is not file-backed, + * for example, a PKCS #11 KeyStore. + */ private static void loadKeyStoreFromFile(KeyStore ks, String file, List passwords) throws Exception { Exception lastFailure = null; for (char[] password : passwords) { try { - try (FileInputStream in = new FileInputStream(file)) { - ks.load(in, password); + if (file != null) { + try (FileInputStream in = new FileInputStream(file)) { + ks.load(in, password); + } + } else { + ks.load(null, password); } return; } catch (Exception e) { diff -Nru android-platform-tools-apksig-0.5+git165~g42d07eb/src/apksigner/java/com/android/apksigner/help_sign.txt android-platform-tools-apksig-0.5+git168~g10c9d71/src/apksigner/java/com/android/apksigner/help_sign.txt --- android-platform-tools-apksig-0.5+git165~g42d07eb/src/apksigner/java/com/android/apksigner/help_sign.txt 2017-03-10 13:07:33.000000000 +0000 +++ android-platform-tools-apksig-0.5+git168~g10c9d71/src/apksigner/java/com/android/apksigner/help_sign.txt 2017-04-04 20:00:59.000000000 +0000 @@ -134,6 +134,25 @@ must be in X.509 PEM or DER format. + JCA PROVIDER INSTALLATION OPTIONS +These options enable you to install additional Java Crypto Architecture (JCA) +Providers, such PKCS #11 providers. Use --next-provider to delimit options of +different providers. Providers are installed in the order in which they appear +on the command-line. + +--provider-class Fully-qualified class name of the JCA Provider. + +--provider-arg Value to pass into the constructor of the JCA Provider + class specified by --provider-class. The value is passed + into the constructor as java.lang.String. By default, the + no-arg provider's constructor is used. + +--provider-pos Position / priority at which to install this provider in + the JCA provider list. By default, the provider is + installed as the lowest priority provider. + See java.security.Security.insertProviderAt. + + EXAMPLES 1. Sign an APK, in-place, using the one and only key in keystore release.jks: @@ -148,3 +167,7 @@ 4. Sign an APK using two keys: $ apksigner sign --ks release.jks --next-signer --ks magic.jks app.apk + +5. Sign an APK using PKCS #11 JCA Provider: +$ apksigner sign --provider-class sun.security.pkcs11.SunPKCS11 \ + --provider-arg token.cfg --ks NONE --ks-type PKCS11 app.apk