Package: release.debian.org Severity: normal User: release.debian.org@packages.debian.org Usertags: unblock Please unblock package: android-platform-tools-apksig This is the next upstream release, which only fixes the eToken/HSM issues as described in #859541. Upstream still doesn't have release tags, hence the version string. I took this opportunity to include the bash-completion to the package as well, for completeness. Attached is the debdiff.
diff --git a/debian/README.source b/debian/README.source
new file mode 100644
index 0000000..7d97b6e
--- /dev/null
+++ b/debian/README.source
@@ -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 <hans@eds.org>, Tue, 4 Apr 2017 22:36:21 +0200
diff --git a/debian/changelog b/debian/changelog
index eb91c32..268c27a 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+android-platform-tools-apksig (0.5+git168~g10c9d71-1) unstable; urgency=medium
+
+ * New upstream release (Closes: #859541)
+
+ -- Hans-Christoph Steiner <hans@eds.org> 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 --git a/debian/control b/debian/control
index 3c9f8a8..ed6ca44 100644
--- a/debian/control
+++ b/debian/control
@@ -13,8 +13,7 @@ Build-Depends: antlr3,
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 --git a/debian/rules b/debian/rules
index f4911e3..d2d284a 100755
--- a/debian/rules
+++ b/debian/rules
@@ -9,7 +9,7 @@ export CLASSPATH=/usr/share/java/apksig.jar
%:
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 --git a/src/apksigner/java/com/android/apksigner/ApkSignerTool.java b/src/apksigner/java/com/android/apksigner/ApkSignerTool.java
index 06b5603..e64fec3 100644
--- a/src/apksigner/java/com/android/apksigner/ApkSignerTool.java
+++ b/src/apksigner/java/com/android/apksigner/ApkSignerTool.java
@@ -41,6 +41,7 @@ import java.security.NoSuchAlgorithmException;
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 @@ public class ApkSignerTool {
int maxSdkVersion = Integer.MAX_VALUE;
List<SignerParams> signers = new ArrayList<>(1);
SignerParams signerParams = new SignerParams();
+ List<ProviderInstallSpec> providers = new ArrayList<>();
+ ProviderInstallSpec providerParams = new ProviderInstallSpec();
OptionsParser optionsParser = new OptionsParser(params);
String optionName;
String optionOriginalForm = null;
@@ -179,6 +182,20 @@ public class ApkSignerTool {
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 @@ public class ApkSignerTool {
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 @@ public class ApkSignerTool {
+ ")");
}
+ // Install additional JCA Providers
+ for (ProviderInstallSpec providerInstallSpec : providers) {
+ providerInstallSpec.installProvider();
+ }
+
List<ApkSigner.SignerConfig> signerConfigs = new ArrayList<>(signers.size());
int signerNumber = 0;
try (PasswordRetriever passwordRetriever = new PasswordRetriever()) {
@@ -531,6 +557,46 @@ public class ApkSignerTool {
}
}
+ 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 @@ public class ApkSignerTool {
}
// 2. Load the KeyStore
- List<char[]> keystorePasswords = null;
- if ("NONE".equals(keystoreFile)) {
- ks.load(null);
- } else {
+ List<char[]> 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 @@ public class ApkSignerTool {
}
}
+ /**
+ * 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<char[]> 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 --git a/src/apksigner/java/com/android/apksigner/help_sign.txt b/src/apksigner/java/com/android/apksigner/help_sign.txt
index ad865fe..11014e0 100644
--- a/src/apksigner/java/com/android/apksigner/help_sign.txt
+++ b/src/apksigner/java/com/android/apksigner/help_sign.txt
@@ -134,6 +134,25 @@ file in X.509 format (see --key and --cert).
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 @@ $ apksigner sign --key release.pk8 --cert release.x509.pem app.apk
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
Attachment:
signature.asc
Description: OpenPGP digital signature