Skip to content

Commit 0253032

Browse files
committed
[feat] Add apk signature check
1 parent 7635b97 commit 0253032

File tree

2 files changed

+76
-4
lines changed

2 files changed

+76
-4
lines changed

info.plist

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6969,18 +6969,21 @@ Use keyword "avd" to list and start emulator</string>
69696969
<key>variables</key>
69706970
<dict>
69716971
<key>aapt_path</key>
6972-
<string>~/Library/Android/sdk/build-tools/28.0.3/aapt</string>
6972+
<string>~/Library/Android/sdk/build-tools/29.0.2/aapt</string>
69736973
<key>adb_path</key>
69746974
<string>~/Library/Android/sdk/platform-tools/adb</string>
6975+
<key>apksigner_path</key>
6976+
<string>~/Library/Android/sdk/build-tools/29.0.2/apksigner</string>
69756977
<key>config_clipboard</key>
69766978
<string>1</string>
69776979
<key>emulator_path</key>
69786980
<string>~/Library/Android/sdk/emulator/emulator</string>
69796981
</dict>
69806982
<key>variablesdontexport</key>
69816983
<array>
6982-
<string>emulator_path</string>
6984+
<string>apksigner_path</string>
69836985
<string>adb_path</string>
6986+
<string>emulator_path</string>
69846987
<string>aapt_path</string>
69856988
</array>
69866989
<key>version</key>

scripts/show_install_options.py

Lines changed: 71 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
serial = os.getenv('serial')
1414
apkFileOrFolder = pipes.quote(os.getenv('apkFile'))
1515
deviceApi = os.getenv('device_api')
16+
apksigner_path = os.getenv("apksigner_path")
1617

1718
needsTestFlag = False
1819
needsDowngradeFlag = False
@@ -61,6 +62,7 @@ def showApkInstallItems():
6162

6263
arg = wf.args[0].strip()
6364

65+
apk = None
6466
if not aapt_path:
6567
head, tail = os.path.split(apkFileOrFolder)
6668
wf.add_item(title=tail, subtitle=apkFileOrFolder, copytext=tail, arg=apkFileOrFolder, valid=True)
@@ -179,6 +181,9 @@ def showApkInstallItems():
179181
if deviceApi and apk.has_key("max") and deviceApi > apk["maxs"]:
180182
wf.add_item(title="Incompatiable device", subtitle="current device api level is {1}, higher than apk maxSdkVersion {0}, ".format(deviceApi, apk["max"]), icon=ICON_ERROR, valid=False)
181183

184+
185+
return apk
186+
182187
def showFolerInstallItems():
183188
arg = wf.args[0].strip()
184189
apkFilesAll = []
@@ -203,7 +208,7 @@ def main(wf):
203208

204209
arg = wf.args[0].strip()
205210
log.debug(arg)
206-
211+
apk = None
207212
fileCount = 1
208213
if os.path.isdir(apkFileOrFolder):
209214
if os.getenv('focused_app') != None:
@@ -223,7 +228,7 @@ def main(wf):
223228
mod = it.add_modifier('cmd', subtitle='only install apks under root directory', valid=True)
224229
mod.setvar('apkFile', apkFileDirect)
225230
else:
226-
showApkInstallItems()
231+
apk = showApkInstallItems()
227232

228233
if fileCount == 0:
229234
wf.warn_empty(title="No APK files find under current path", subtitle=apkFileOrFolder)
@@ -251,6 +256,70 @@ def main(wf):
251256

252257
wf.setvar("option", installOptions)
253258

259+
# add "-" to apksigner path will disable signature check
260+
if (apksigner_path != None and apksigner_path != "" and (not apksigner_path.startswith("-")) and apk != None):
261+
log.debug("Apksigner path " + apksigner_path)
262+
cmd = "{0} verify -v --print-certs {1}".format(apksigner_path, apkFileOrFolder)
263+
log.debug(cmd)
264+
result = subprocess.check_output(cmd,
265+
stderr=subprocess.STDOUT,
266+
shell=True)
267+
if result:
268+
log.debug(result)
269+
infos = result.rstrip().split('\n')
270+
v1Verified = False
271+
v2Verified = False
272+
v3Verified = False
273+
274+
signer = []
275+
276+
reg = re.compile(r"^Signer #(\d+) certificate (.*):(.*)")
277+
278+
for info in infos:
279+
if info.startswith("Verified using v1 scheme") and info.endswith("true"):
280+
v1Verified = True
281+
elif info.startswith("Verified using v2 scheme") and info.endswith("true"):
282+
v2Verified = True
283+
elif info.startswith("Verified using v3 scheme") and info.endswith("true"):
284+
v3Verified = True
285+
286+
a = reg.search(info)
287+
if a != None and len(a.groups()) == 3:
288+
i = int(a.group(1))
289+
key = a.group(2)
290+
value = a.group(3)
291+
log.debug("KEYKEY " + key + " !!")
292+
if key == "DN":
293+
signer.append({})
294+
signer[i-1]["DN"] = a.group(3)
295+
elif "SHA-256 digest" in key:
296+
log.debug(a.group(3))
297+
signer[i-1]["SHA256"] = a.group(3)
298+
elif "SHA-1 digest" in key:
299+
signer[i-1]["SHA1"] = a.group(3)
300+
elif "MD5 digest" in key:
301+
signer[i-1]["MD5"] = a.group(3)
302+
303+
title = "Signature " + infos[0]
304+
if infos[0] == "Verifies":
305+
title = "Signature verified"
306+
subtitle = "Scheme V1 {0}, V2 {1}, V3 {2}".format(v1Verified, v2Verified, v3Verified)
307+
wf.add_item(title=title, subtitle=subtitle, icon=ICON_INFO, valid=False)
308+
log.debug(signer)
309+
for i in range(len(signer)):
310+
item = signer[i]
311+
312+
sha256 = "SHA-256:{0}".format(item["SHA256"])
313+
sha1 = "SHA-1:{0}".format(item["SHA1"])
314+
md5 = "MD5:{0}".format(item["MD5"])
315+
title = "Signer #{0} {1}".format(i, md5)
316+
if sha256:
317+
it = wf.add_item(title=title, subtitle=item["DN"], icon=ICON_INFO, valid=False)
318+
if sha256:
319+
it.add_modifier('cmd', subtitle=sha256, valid=False)
320+
if sha1:
321+
it.add_modifier('alt', subtitle=sha1, valid=False)
322+
254323
wf.send_feedback()
255324

256325
if __name__ == '__main__':

0 commit comments

Comments
 (0)