Share your advanced knowledge/code with the community.
tj1010
 
Posts: 175
Joined: Wed May 27, 2015 1:36 pm

Re: How to sign a release APK

by tj1010 Wed Dec 14, 2016 2:16 am

Image
A quick multi-threaded GUI signer tool that will build with the demo version of purebasic. Not tested on Linux or OSX but you can just add forward slash support. It needs to be ran as admin because of modern Windows file system sandboxing.

UPDATE 6/11/17:
  • Added UI for -dname so no more manual CLI stuff
  • You can now save field values across sessions by checking bottom-left checkbox
Code: Select all
;Android .apk signer

;get paths for JDK and SB
Global path$
Global jdk$
sb$=GetEnvironmentVariable("HOMEDRIVE")+GetEnvironmentVariable("HOMEPATH")+"\AppData\Roaming\SpiderBasic\"
If FileSize(sb$)=-2
  ReadFile(0,sb$+"SpiderBasic.prefs")
  While Eof(0)=0
    line$=ReadString(0)
    If StringField(line$,1," ")="JDK" : jdk$=Mid(line$,FindString(line$,":\")-1,9999999) : EndIf
    If StringField(line$,1," ")="Path" : path$=Left(StringField(line$,3," "),FindString(StringField(line$,3," "),"\Ex")) : EndIf
  Wend
  CloseFile(0)
  If Len(jdk$)=0 : MessageRequester("Error","JDK Path not set in  SB") : End : EndIf
  If Len(path$)=0 : MessageRequester("Error","SB Path not set in  SB prefs file") : End : EndIf
Else
  MessageRequester("Error","SB AppData folder missing") : End
EndIf

Declare buildit(*val)
Declare loadvalues()

Global Window_0, Button_0, String_0, String_2, String_3, String_4, String_4_Copy1, String_3_Copy1, String_2_Copy1, String_2_Copy1_Copy1, String_3_Copy1_Copy1, String_4_Copy1_Copy1, Editor_0, Button_2, Checkbox_0


Procedure OpenWindow_0(x = 0, y = 0, width = 600, height = 400)
  Window_0 = OpenWindow(#PB_Any, x, y, width, height, "APK Sign Tool", #PB_Window_SystemMenu)
  SetWindowColor(Window_0, RGB(72,72,72))
  Button_0 = ButtonGadget(#PB_Any, 510, 0, 90, 25, "Browse")
  String_0 = StringGadget(#PB_Any, 0, 0, 510, 25, ".APK")
  SetGadgetColor(String_0, #PB_Gadget_FrontColor,RGB(255,255,255))
  SetGadgetColor(String_0, #PB_Gadget_BackColor,RGB(0,0,0))
  String_2 = StringGadget(#PB_Any, 0, 40, 190, 25, "Password")
  SetGadgetColor(String_2, #PB_Gadget_FrontColor,RGB(255,255,255))
  SetGadgetColor(String_2, #PB_Gadget_BackColor,RGB(0,0,0))
  String_3 = StringGadget(#PB_Any, 195, 40, 200, 25, "KeyStore Alias")
  SetGadgetColor(String_3, #PB_Gadget_FrontColor,RGB(255,255,255))
  SetGadgetColor(String_3, #PB_Gadget_BackColor,RGB(0,0,0))
  String_4 = StringGadget(#PB_Any, 400, 40, 200, 25, "First Name")
  SetGadgetColor(String_4, #PB_Gadget_FrontColor,RGB(255,255,255))
  SetGadgetColor(String_4, #PB_Gadget_BackColor,RGB(0,0,0))
  String_4_Copy1 = StringGadget(#PB_Any, 400, 70, 200, 25, "Organization")
  SetGadgetColor(String_4_Copy1, #PB_Gadget_FrontColor,RGB(255,255,255))
  SetGadgetColor(String_4_Copy1, #PB_Gadget_BackColor,RGB(0,0,0))
  String_3_Copy1 = StringGadget(#PB_Any, 195, 70, 200, 25, "Organization Unit")
  SetGadgetColor(String_3_Copy1, #PB_Gadget_FrontColor,RGB(255,255,255))
  SetGadgetColor(String_3_Copy1, #PB_Gadget_BackColor,RGB(0,0,0))
  String_2_Copy1 = StringGadget(#PB_Any, 0, 70, 190, 25, "Last Name")
  SetGadgetColor(String_2_Copy1, #PB_Gadget_FrontColor,RGB(255,255,255))
  SetGadgetColor(String_2_Copy1, #PB_Gadget_BackColor,RGB(0,0,0))
  String_2_Copy1_Copy1 = StringGadget(#PB_Any, 0, 100, 190, 25, "Town")
  SetGadgetColor(String_2_Copy1_Copy1, #PB_Gadget_FrontColor,RGB(255,255,255))
  SetGadgetColor(String_2_Copy1_Copy1, #PB_Gadget_BackColor,RGB(0,0,0))
  String_3_Copy1_Copy1 = StringGadget(#PB_Any, 195, 100, 200, 25, "State")
  SetGadgetColor(String_3_Copy1_Copy1, #PB_Gadget_FrontColor,RGB(255,255,255))
  SetGadgetColor(String_3_Copy1_Copy1, #PB_Gadget_BackColor,RGB(0,0,0))
  String_4_Copy1_Copy1 = StringGadget(#PB_Any, 400, 100, 200, 25, "Country")
  SetGadgetColor(String_4_Copy1_Copy1, #PB_Gadget_FrontColor,RGB(255,255,255))
  SetGadgetColor(String_4_Copy1_Copy1, #PB_Gadget_BackColor,RGB(0,0,0))
  Editor_0 = EditorGadget(#PB_Any, 0, 130, 600, 240)
  SetGadgetColor(Editor_0, #PB_Gadget_FrontColor,RGB(255,255,255))
  SetGadgetColor(Editor_0, #PB_Gadget_BackColor,RGB(0,0,0))
  DisableGadget(Editor_0,1)
  Button_2 = ButtonGadget(#PB_Any, 430, 375, 170, 25, "Sign")
  Checkbox_0 = CheckBoxGadget(#PB_Any, 10, 372, 230, 20, "Remember Fields?")
  loadvalues()
EndProcedure

Procedure Window_0_Events(event)
  Select event
    Case #PB_Event_CloseWindow
      ProcedureReturn #False
     
    Case #PB_Event_Menu
      Select EventMenu()
      EndSelect
     
    Case #PB_Event_Gadget
      Select EventGadget()
        Case Button_0;browse button
          If EventType()=#PB_EventType_LeftClick
            file$=OpenFileRequester("Path to APK File","","*.apk",0)
            If Len(file$)>0 : SetGadgetText(String_0,file$) : EndIf
          EndIf
        Case Button_2;signs
          If EventType()=#PB_EventType_LeftClick
            If GetGadgetText(String_0)<>".APK" And Len(GetGadgetText(String_0))>0
              CreateThread(@buildit(),1)
            EndIf
          EndIf
        Case Checkbox_0
          If EventType()=#PB_EventType_LeftClick
            If GetGadgetState(Checkbox_0)=#PB_Checkbox_Unchecked
              If FileSize("apksigner.txt")>0 : DeleteFile("apksigner.txt") : EndIf
            EndIf
          EndIf
      EndSelect
  EndSelect
  ProcedureReturn #True
EndProcedure

OpenWindow_0()
Repeat : If Not Window_0_Events(WaitWindowEvent()) : Break : EndIf : ForEver
If GetGadgetState(Checkbox_0)=#PB_Checkbox_Checked
  If FileSize("apksigner.txt")>0 : DeleteFile("apksigner.txt") : EndIf
  If CreateFile(0,"apksigner.txt")
    WriteStringN(0,"path:"+Trim(GetGadgetText(String_0)))
    WriteStringN(0,"password:"+Trim(GetGadgetText(String_2)))
    WriteStringN(0,"alias:"+Trim(GetGadgetText(String_3)))
    WriteStringN(0,"first:"+Trim(GetGadgetText(String_4)))
    WriteStringN(0,"org:"+Trim(GetGadgetText(String_4_Copy1)))
    WriteStringN(0,"orgu:"+Trim(GetGadgetText(String_3_Copy1)))
    WriteStringN(0,"last:"+Trim(GetGadgetText(String_2_Copy1)))
    WriteStringN(0,"town:"+Trim(GetGadgetText(String_2_Copy1_Copy1)))
    WriteStringN(0,"state:"+Trim(GetGadgetText(String_3_Copy1_Copy1)))
    WriteStringN(0,"country:"+Trim(GetGadgetText(String_4_Copy1_Copy1)))
    CloseFile(0)
  EndIf
EndIf
End

Procedure buildit(*val)
  DisableGadget(Button_2,1)
  ctool=RunProgram(jdk$+"bin\keytool.exe","-genkeypair -sigalg SHA256withRSA -v -keystore my-release-key.keystore -keyalg RSA -dname "+Chr(34)+"CN="+Trim(GetGadgetText(String_4))+" "+Trim(GetGadgetText(String_2_Copy1))+", OU="+Trim(GetGadgetText(String_3_Copy1))+", O="+Trim(GetGadgetText(String_4_Copy1))+", L="+Trim(GetGadgetText(String_2_Copy1_Copy1))+", S="+Trim(GetGadgetText(String_3_Copy1_Copy1))+", C="+Trim(GetGadgetText(String_4_Copy1_Copy1))+Chr(34)+" -keypass "+Trim(GetGadgetText(String_2))+" -storepass "+Trim(GetGadgetText(String_2))+" -keysize 2048 -validity 10000 -alias "+Trim(GetGadgetText(String_3)),GetCurrentDirectory(),#PB_Program_Wait)
  ctool=RunProgram(jdk$+"bin\jarsigner.exe","-verbose -tsa http://timestamp.digicert.com -sigalg SHA256withRSA -digestalg SHA1 -keystore my-release-key.keystore "+Chr(34)+Trim(GetGadgetText(String_0))+Chr(34)+" "+Trim(GetGadgetText(String_3))+" -storepass "+Trim(GetGadgetText(String_2)),GetCurrentDirectory(),#PB_Program_Read|#PB_Program_Connect|#PB_Program_Open)
  If IsProgram(ctool)
    While ProgramRunning(ctool)
      If AvailableProgramOutput(ctool)
        AddGadgetItem(Editor_0,-1,ReadProgramString(ctool) + Chr(13))
      EndIf
    Wend
    CloseProgram(ctool)
  EndIf
  ctool=RunProgram(path$+"Android\android\sdk\build-tools\23.0.2\zipalign.exe","4 "+Chr(34)+apk$+Chr(34)+" "+RemoveString(apk$,".apk")+"_signed.apk",GetCurrentDirectory(),#PB_Program_Read|#PB_Program_Connect|#PB_Program_Open)
  If IsProgram(ctool)
    While ProgramRunning(ctool)
      If AvailableProgramOutput(ctool)
        AddGadgetItem(Editor_0,-1,ReadProgramString(ctool) + Chr(13))
      EndIf
    Wend
    CloseProgram(ctool)
  EndIf
  DisableGadget(Button_2,0)
EndProcedure

Procedure loadvalues()
  Protected line$
  If FileSize("apksigner.txt")>0
    If OpenFile(0,"apksigner.txt")
      While Eof(0)=0
        line$=Trim(ReadString(0))
        If Mid(line$,1,5)="path:" : SetGadgetText(String_0,Mid(line$,6,999)) : EndIf
        If Mid(line$,1,9)="password:" : SetGadgetText(String_2,Mid(line$,10,999)) : EndIf
        If Mid(line$,1,6)="alias:" : SetGadgetText(String_3,Mid(line$,7,999)) : EndIf
        If Mid(line$,1,6)="first:" : SetGadgetText(String_4,Mid(line$,7,999)) : EndIf
        If Mid(line$,1,4)="org:" : SetGadgetText(String_4_Copy1,Mid(line$,5,999)) : EndIf
        If Mid(line$,1,5)="orgu:" : SetGadgetText(String_3_Copy1,Mid(line$,6,999)) : EndIf
        If Mid(line$,1,5)="last:" : SetGadgetText(String_2_Copy1,Mid(line$,6,999)) : EndIf
        If Mid(line$,1,5)="town:" : SetGadgetText(String_2_Copy1_Copy1,Mid(line$,6,999)) : EndIf
        If Mid(line$,1,6)="state:" : SetGadgetText(String_3_Copy1_Copy1,Mid(line$,7,999)) : EndIf
        If Mid(line$,1,8)="country:" : SetGadgetText(String_4_Copy1_Copy1,Mid(line$,6,999)) : EndIf
        SetGadgetState(Checkbox_0,#PB_Checkbox_Checked)
      Wend
      CloseFile(0)
    EndIf
  EndIf
EndProcedure
Last edited by tj1010 on Mon Jun 12, 2017 2:56 pm, edited 7 times in total.
IdeasVacuum
 
Posts: 134
Joined: Tue Feb 25, 2014 1:27 pm

Re: How to sign a release APK

by IdeasVacuum Fri Jun 09, 2017 2:26 pm

Rings wrote:should such a tip not been included in the IDE an been automated ?


I think that would be really really useful - needs to be optional though!
IdeasVacuum
 
Posts: 134
Joined: Tue Feb 25, 2014 1:27 pm

Re: How to sign a release APK

by IdeasVacuum Fri Jun 09, 2017 2:43 pm

tj1010, just trying out your App Signer (PB5.6), I hit a problem.
After inputting a KeyStore Password and hitting 'Sign', a command window pops up and requests the Password but does not let me edit/paste it.
I assume this is because there are rules regarding password length, acceptable characters etc?
IdeasVacuum
 
Posts: 134
Joined: Tue Feb 25, 2014 1:27 pm

Re: How to sign a release APK

by IdeasVacuum Fri Jun 09, 2017 3:35 pm

Here is an interesting looking signer app: APK Signer from Hai Bison

Image
IdeasVacuum
 
Posts: 134
Joined: Tue Feb 25, 2014 1:27 pm

Re: How to sign a release APK

by IdeasVacuum Sat Jun 10, 2017 10:01 am

Well, apk-signer seems to work well enough but it is a pitta to use! However, it does seem to cover more ground than tj1010's signer, requesting developer's name and location for example, similar to Windows OS digital signature info.
tj1010
 
Posts: 175
Joined: Wed May 27, 2015 1:36 pm

Re: How to sign a release APK

by tj1010 Sun Jun 11, 2017 1:40 pm

IdeasVacuum wrote:Well, apk-signer seems to work well enough but it is a pitta to use! However, it does seem to cover more ground than tj1010's signer, requesting developer's name and location for example, similar to Windows OS digital signature info.


My tool no longer requires manual CLI input(I just had to add -dname fields in UI). It already did everything the mentioned tool does. That just set -dname with UI fields so no CLI popup and input.

FYI if the container already exists keytool just gracefully fails and jarsigner just uses existing container. You can delete containers using the -delete command with keytool.

I've read the full Oracle docs and this is about all there is to do with Android APK signing. I guess I could improve UI/UX later but it's efficient now. There is also v2 signing with 7.0+ but 7.0+ still has legacy support.
IdeasVacuum
 
Posts: 134
Joined: Tue Feb 25, 2014 1:27 pm

Re: How to sign a release APK

by IdeasVacuum Mon Jun 12, 2017 10:59 am

Looks great tj1010!
Line 126 :
Code: Select all
  ctool=RunProgram(jdk$+"bin\jarsigner.exe","-verbose -tsa http://timestamp.digicert.com -sigalg SHA256withRSA -digestalg SHA1 -keystore my-release-key.keystore "+Chr(34)+Trim(GetGadgetText(String_0))+Chr(34)+" "+Trim(GetGadgetText(String_3)+" -storepass "+Trim(GetGadgetText(String_2)),GetCurrentDirectory(),#PB_Program_Read|#PB_Program_Connect|#PB_Program_Open)

[COMPILER] Line 126: Trim(): Incorrect number of parameters.
tj1010
 
Posts: 175
Joined: Wed May 27, 2015 1:36 pm

Re: How to sign a release APK

by tj1010 Mon Jun 12, 2017 2:57 pm

IdeasVacuum wrote:Looks great tj1010!
Line 126 :
Code: Select all
  ctool=RunProgram(jdk$+"bin\jarsigner.exe","-verbose -tsa http://timestamp.digicert.com -sigalg SHA256withRSA -digestalg SHA1 -keystore my-release-key.keystore "+Chr(34)+Trim(GetGadgetText(String_0))+Chr(34)+" "+Trim(GetGadgetText(String_3)+" -storepass "+Trim(GetGadgetText(String_2)),GetCurrentDirectory(),#PB_Program_Read|#PB_Program_Connect|#PB_Program_Open)

[COMPILER] Line 126: Trim(): Incorrect number of parameters.


fixed

I don't know about anyone else, but when I use -list command I get a .keystore missing error even though the keystore exists and I get error on duplicate -genkeypair and success on -delete. This doesn't effect this tool, but I was thinking of making a keystore manager using CLI output instead of just remembering from sessions. It's likely a environment variable error even though I have a unmodified install..
Return to Tricks 'n' Tips

Who is online

Users browsing this forum: No registered users and 1 guest