resignios 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,58 @@
1
+ require 'rubygems'
2
+ require 'commander/import'
3
+
4
+ require 'colored2'
5
+ require 'version'
6
+ require_relative 'resign'
7
+
8
+ module Sigh
9
+ class CommandsGenerator
10
+
11
+ def self.start
12
+ self.new.run
13
+ end
14
+
15
+ def run
16
+ program :name, 'resignios'
17
+ program :version, Resignios::VERSION
18
+ program :description, 'ios resign tool.'
19
+
20
+ command :ipa do |c|
21
+ c.syntax = 'resignios ipa'
22
+ c.description = 'Resigns an existing ipa file with the given provisioning profile'
23
+ c.option '-i', '--signing_identity STRING', String, 'The signing identity to use. Must match the one defined in the provisioning profile.'
24
+ c.option '-x', '--version_number STRING', String, 'Version number to force binary and all nested binaries to use. Changes both CFBundleShortVersionString and CFBundleIdentifier.'
25
+ c.option '-p', '--provisioning_profile PATH', String, '(or BUNDLE_ID=PATH) The path to the provisioning profile which should be used. '\
26
+ 'Can be provided multiple times if the application contains nested applications and app extensions, which need their own provisioning profile. '\
27
+ 'The path may be prefixed with a identifier in order to determine which provisioning profile should be used on which app.',
28
+ &multiple_values_option_proc(c, "provisioning_profile", &proc { |value| value.split('=', 2) })
29
+ c.option '-d', '--display_name STRING', String, 'Display name to use'
30
+ c.option '-e', '--entitlements PATH', String, 'The path to the entitlements file to use.'
31
+ c.option '--short_version STRING', String, 'Short version string to force binary and all nested binaries to use (CFBundleShortVersionString).'
32
+ c.option '--bundle_version STRING', String, 'Bundle version to force binary and all nested binaries to use (CFBundleVersion).'
33
+ c.option '--use_app_entitlements', 'Extract app bundle codesigning entitlements and combine with entitlements from new provisionin profile.'
34
+ c.option '-g', '--new_bundle_id STRING', String, 'New application bundle ID (CFBundleIdentifier)'
35
+ c.option '--remove_plugins', 'Remove new Application plugins'
36
+ c.option '--keychain_path STRING', String, 'Path to the keychain that /usr/bin/codesign should use'
37
+ c.option '-o', '--output_path STRING', String, 'Output IPA Path.'
38
+ c.action do |args, options|
39
+ Sigh::Resign.new.run(options, args)
40
+ end
41
+ end
42
+
43
+ default_command :ipa
44
+ end
45
+
46
+ def multiple_values_option_proc(command, name)
47
+ proc do |value|
48
+ value = yield(value) if block_given?
49
+ option = command.proxy_options.find { |opt| opt[0] == name } || []
50
+ values = option[1] || []
51
+ values << value
52
+
53
+ command.proxy_options.delete option
54
+ command.proxy_options << [name, values]
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,194 @@
1
+ require 'shellwords'
2
+
3
+ module Sigh
4
+ class Resign
5
+ def run(options, args)
6
+ # get the command line inputs and parse those into the vars we need...
7
+ ipa, signing_identity, provisioning_profiles, entitlements, version, display_name, short_version, bundle_version, new_bundle_id, use_app_entitlements, remove_plugins, keychain_path, output_path = get_inputs(options, args)
8
+ # ... then invoke our programmatic interface with these vars
9
+ unless resign(ipa, signing_identity, provisioning_profiles, entitlements, version, display_name, short_version, bundle_version, new_bundle_id, use_app_entitlements, remove_plugins, keychain_path, output_path)
10
+ puts "Failed to re-sign .ipa".red
11
+ end
12
+ end
13
+
14
+ def find_resign_path
15
+ File.expand_path('../../assets/resign.sh', __FILE__)
16
+ end
17
+
18
+ def resign(ipa, signing_identity, provisioning_profiles, entitlements, version, display_name, short_version, bundle_version, new_bundle_id, use_app_entitlements, remove_plugins, keychain_path, output_path)
19
+ resign_path = find_resign_path
20
+ signing_identity = find_signing_identity(signing_identity)
21
+
22
+ unless provisioning_profiles.kind_of?(Enumerable)
23
+ provisioning_profiles = [provisioning_profiles]
24
+ end
25
+
26
+ # validate that we have valid values for all these params, we don't need to check signing_identity because `find_signing_identity` will only ever return a valid value
27
+ validate_params(resign_path, ipa, provisioning_profiles)
28
+ entitlements = "-e #{entitlements.shellescape}" if entitlements
29
+
30
+ provisioning_options = create_provisioning_options(provisioning_profiles)
31
+ version = "-n #{version}" if version
32
+ display_name = "-d #{display_name.shellescape}" if display_name
33
+ short_version = "--short-version #{short_version}" if short_version
34
+ bundle_version = "--bundle-version #{bundle_version}" if bundle_version
35
+ verbose = "-v" if $verbose
36
+ bundle_id = "-b '#{new_bundle_id}'" if new_bundle_id
37
+ use_app_entitlements_flag = "--use-app-entitlements" if use_app_entitlements
38
+ remove_plugins_flag = "--remove-plugins" if remove_plugins
39
+ specific_keychain = "--keychain-path #{keychain_path.shellescape}" if keychain_path
40
+
41
+ command = [
42
+ resign_path.shellescape,
43
+ ipa.shellescape,
44
+ signing_identity.shellescape,
45
+ provisioning_options, # we are aleady shellescaping this above, when we create the provisioning_options from the provisioning_profiles
46
+ entitlements,
47
+ version,
48
+ display_name,
49
+ short_version,
50
+ bundle_version,
51
+ use_app_entitlements_flag,
52
+ remove_plugins_flag,
53
+ verbose,
54
+ bundle_id,
55
+ output_path || ipa.shellescape,
56
+ specific_keychain
57
+ ].join(' ')
58
+
59
+ puts command.magenta
60
+ puts `#{command}`
61
+
62
+ if $?.to_i == 0
63
+ puts "Successfully signed #{ipa}!"
64
+ true
65
+ else
66
+ puts "Something went wrong while code signing #{ipa}".red
67
+ false
68
+ end
69
+ end
70
+
71
+ def find_signing_identity(signing_identity)
72
+ until (signing_identity = sha1_for_signing_identity(signing_identity))
73
+ puts "Couldn't find signing identity '#{signing_identity}'.".red
74
+ signing_identity = ask_for_signing_identity
75
+ end
76
+
77
+ signing_identity
78
+ end
79
+
80
+ def sha1_for_signing_identity(signing_identity)
81
+ identities = installed_identities
82
+ return signing_identity if identities.keys.include?(signing_identity)
83
+ identities.key(signing_identity)
84
+ end
85
+
86
+ def create_provisioning_options(provisioning_profiles)
87
+ # provisioning_profiles is passed either a hash (to be able to resign extensions/nested apps):
88
+ # (in that case the underlying resign.sh expects values given as "-p at.fastlane=/folder/mobile.mobileprovision -p at.fastlane.today=/folder/mobile.mobileprovision")
89
+ # {
90
+ # "at.fastlane" => "/folder/mobile.mobileprovision",
91
+ # "at.fastlane.today" => "/folder/mobile.mobileprovision"
92
+ # }
93
+ # or an array
94
+ # (resign.sh also takes "-p /folder/mobile.mobileprovision" as a param)
95
+ # [
96
+ # "/folder/mobile.mobileprovision"
97
+ # ]
98
+ provisioning_profiles.map do |app_id, app_id_prov|
99
+ if app_id_prov
100
+ app_id_prov = File.expand_path(app_id_prov)
101
+ else
102
+ app_id = File.expand_path(app_id)
103
+ end
104
+ "-p #{[app_id, app_id_prov].compact.map(&:shellescape).join('=')}"
105
+ end.join(' ')
106
+ end
107
+
108
+ def validate_params(resign_path, ipa, provisioning_profiles)
109
+ validate_resign_path(resign_path)
110
+ validate_ipa_file(ipa)
111
+ provisioning_profiles.each { |fst, snd| validate_provisioning_file(snd || fst) }
112
+ end
113
+
114
+ def validate_resign_path(resign_path)
115
+ puts 'Could not find resign.sh file. Please try re-installing the gem'.red unless File.exist?(resign_path)
116
+ end
117
+
118
+ def validate_ipa_file(ipa)
119
+ puts "ipa file could not be found or is not an ipa file (#{ipa})".red unless File.exist?(ipa) && ipa.end_with?('.ipa')
120
+ end
121
+
122
+ def validate_provisioning_file(provisioning_profile)
123
+ unless File.exist?(provisioning_profile) && provisioning_profile.end_with?('.mobileprovision')
124
+ puts "Provisioning profile file could not be found or is not a .mobileprovision file (#{provisioning_profile})".red
125
+ end
126
+ end
127
+
128
+ def get_inputs(options, args)
129
+ ipa = args.first || self.input('Path to ipa file: ')
130
+ signing_identity = options.signing_identity || ask_for_signing_identity
131
+ provisioning_profiles = options.provisioning_profile || self.input('Path to provisioning file: ')
132
+ entitlements = options.entitlements || nil
133
+ version = options.version_number || nil
134
+ display_name = options.display_name || nil
135
+ short_version = options.short_version || nil
136
+ bundle_version = options.bundle_version || nil
137
+ new_bundle_id = options.new_bundle_id || nil
138
+ use_app_entitlements = options.use_app_entitlements || nil
139
+ remove_plugins = options.remove_plugins || (options.provisioning_profile.nil? ? true : false)
140
+ keychain_path = options.keychain_path || nil
141
+ output_path = options.output_path || ask_for_output_ipa_path
142
+
143
+ if options.provisioning_name
144
+ puts "The provisioning_name (-n) option is not applicable to resign. You should use provisioning_profile (-p) instead".yellow
145
+ end
146
+
147
+ return ipa, signing_identity, provisioning_profiles, entitlements, version, display_name, short_version, bundle_version, new_bundle_id, use_app_entitlements, remove_plugins, keychain_path, output_path
148
+ end
149
+
150
+ def ask_for_signing_identity
151
+ descriptions = []
152
+ installed_identities.group_by { |sha1, name| name }.each do |name, identities|
153
+ descriptions << name
154
+ # Show SHA-1 for homonymous identities
155
+ descriptions += identities.map do |sha1, _|
156
+ "\t#{sha1}"
157
+ end
158
+ end
159
+ puts "Available identities: \n\t#{descriptions.join("\n\t")}\n"
160
+ self.input('Signing Identity: ')
161
+ end
162
+
163
+ # Hash of available signing identities
164
+ def installed_identities
165
+ available = `security find-identity -v -p codesigning`
166
+ ids = {}
167
+ available.split("\n").each do |current|
168
+ begin
169
+ sha1 = current.match(/[a-zA-Z0-9]{40}/).to_s
170
+ name = current.match(/.*\"(.*)\"/)[1]
171
+ ids[sha1] = name
172
+ rescue
173
+ nil
174
+ end # the last line does not match
175
+ end
176
+
177
+ ids
178
+ end
179
+
180
+ def ask_for_output_ipa_path
181
+ output_path = self.input('Output path to ipa file: ')
182
+ unless output_path.end_with?('.ipa')
183
+ puts "Output path to ipa file error.".yellow
184
+ return nil
185
+ end
186
+ output_path
187
+ end
188
+
189
+ def input(message)
190
+ print "#{message}".red
191
+ STDIN.gets.chomp.strip
192
+ end
193
+ end
194
+ end
@@ -0,0 +1,31 @@
1
+
2
+ module ResignTool
3
+ class Command
4
+ class Cert < Command
5
+ self.summary = "列出本机安装的所有证书信息"
6
+ self.description = '列出本机安装的所有证书信息'
7
+ self.command = "cert"
8
+ self.abstract_command = false
9
+ self.arguments = [
10
+ ]
11
+ def self.options
12
+ [
13
+ ["--valid", "输出有效证书"],
14
+ ["--codesigning", "只输出用于iOS签名的证书信息"]
15
+ ]
16
+ end
17
+ def initialize(argv)
18
+ @valid = argv.flag?("valid", true)
19
+ @codesigning = argv.flag?("codesigning", false)
20
+ super
21
+ end
22
+ def validate!
23
+ super
24
+ end
25
+ def run
26
+ command = 'security find-identity' << (@valid ? ' -v' : '') << (@codesigning ? ' -p codesigning' : '')
27
+ exec "#{command}"
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,80 @@
1
+ module ResignTool
2
+ class Command
3
+ class Provisioning < Command
4
+ self.summary = '展示和清除本机安装的描述文件'
5
+ self.description = '展示和清除本机安装的描述文件'
6
+ self.command = 'provisioning'
7
+ self.arguments = [
8
+ CLAide::Argument.new('Provisioning Profiles Path', false)
9
+ ]
10
+ def self.options
11
+ [
12
+ ["--list", "列出本机安装的所有描述文件"],
13
+ ["--clean", "清除本机已安装的所有描述文件"]
14
+ ]
15
+ end
16
+
17
+ def initialize(argv)
18
+ @list = argv.flag?("list", true)
19
+ @clean = argv.flag?("clean", false)
20
+
21
+ @profile_path = argv.shift_argument || "~/Library/MobileDevice/Provisioning\ Profiles/"
22
+ super
23
+ end
24
+
25
+ def validate!
26
+ super
27
+ end
28
+
29
+ def run
30
+ @profile_path = File.expand_path(@profile_path)
31
+ if !File.exist?(@profile_path)
32
+ puts "没有找到`mobile provision`的安装路径, #{@profile_path}"
33
+ return
34
+ end
35
+
36
+ if @clean
37
+ clean_pp
38
+ else
39
+ find_pp
40
+ end
41
+ end
42
+
43
+ private
44
+ def clean_pp
45
+ FileUtils.chdir(@profile_path)
46
+
47
+ Dir.glob("*.mobileprovision").each do |file|
48
+ FileUtils.rm_rf(file)
49
+ end
50
+ puts "mobileprovision files clean success"
51
+ end
52
+
53
+ def find_pp
54
+ FileUtils.chdir(@profile_path)
55
+
56
+ index = 0
57
+ Dir.glob("*.mobileprovision").each do |file|
58
+ name = print_pp_info("Name", file)
59
+ identifier = print_pp_info("Entitlements:application-identifier", file)
60
+ uuid = print_pp_info("UUID", file) || ''
61
+ team_name = print_pp_info("TeamName", file) || ''
62
+ create_date = print_pp_info("CreationDate", file) || ''
63
+ expiration_date = print_pp_info("ExpirationDate", file) || ''
64
+
65
+ puts "#{index += 1})".red " #{name}".green
66
+ puts " application-identifier: ".yellow "#{identifier}".green
67
+ puts " UUID: ".yellow "#{uuid}".green
68
+ puts " TeamName: ".yellow "#{team_name}".green
69
+ puts " CreationDate: ".yellow "#{create_date}".green
70
+ puts " ExpirationDate: ".yellow "#{expiration_date}".green
71
+ end
72
+ end
73
+
74
+ def print_pp_info(name, file)
75
+ command = "/usr/libexec/PlistBuddy -c 'Print :#{name}' /dev/stdin <<< $(security cms -D -u 11 -i #{file})"
76
+ `#{command}`.lines.to_a.first.strip! || ''
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,33 @@
1
+ require 'claide'
2
+ require 'colored2'
3
+ require 'version'
4
+
5
+ module ResignTool
6
+ class Command < CLAide::Command
7
+ self.summary = "iOS重签名"
8
+ self.description = 'ipa包重签名信息查看,证书、描述文件等'
9
+ self.command = "resigntool"
10
+ self.abstract_command = true
11
+ def self.options
12
+ [
13
+ ["--version", "Show sign tool version"]
14
+ ]
15
+ end
16
+ def initialize(argv)
17
+ @version = argv.flag?("version", false)
18
+ super
19
+ end
20
+ def validate!
21
+ if @version
22
+ puts "#{Resignios::VERSION}"
23
+ return
24
+ end
25
+ super
26
+ end
27
+ def run
28
+ end
29
+ end
30
+ end
31
+
32
+ require_relative 'command/cert'
33
+ require_relative 'command/provisioning'
data/lib/version.rb ADDED
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Resignios
4
+ VERSION = "0.1.1"
5
+ end
metadata ADDED
@@ -0,0 +1,121 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: resignios
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Cary
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-09-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: claide
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 1.0.2
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '2.0'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: 1.0.2
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '2.0'
33
+ - !ruby/object:Gem::Dependency
34
+ name: colored2
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '3.1'
40
+ type: :runtime
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '3.1'
47
+ - !ruby/object:Gem::Dependency
48
+ name: commander
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ - !ruby/object:Gem::Dependency
62
+ name: shellwords
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ type: :runtime
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ description: iOS重签名工具,基于fastlane sigh命令做了些许修改
76
+ email:
77
+ - guojiashuang@live.com
78
+ executables:
79
+ - resigntool
80
+ - resign
81
+ - resignios
82
+ extensions: []
83
+ extra_rdoc_files: []
84
+ files:
85
+ - CHANGELOG.md
86
+ - LICENSE.txt
87
+ - README.md
88
+ - bin/resign
89
+ - bin/resignios
90
+ - bin/resigntool
91
+ - lib/assets/resign.sh
92
+ - lib/resign/commands_generator.rb
93
+ - lib/resign/resign.rb
94
+ - lib/tool/command/cert.rb
95
+ - lib/tool/command/provisioning.rb
96
+ - lib/tool/resigntool.rb
97
+ - lib/version.rb
98
+ homepage: https://github.com/CaryGo/resignios
99
+ licenses:
100
+ - MIT
101
+ metadata: {}
102
+ post_install_message:
103
+ rdoc_options: []
104
+ require_paths:
105
+ - lib
106
+ required_ruby_version: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: 2.6.0
111
+ required_rubygems_version: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - ">="
114
+ - !ruby/object:Gem::Version
115
+ version: '0'
116
+ requirements: []
117
+ rubygems_version: 3.1.2
118
+ signing_key:
119
+ specification_version: 4
120
+ summary: iOS重签名工具,基于fastlane sigh命令做了些许修改
121
+ test_files: []