fastlane 2.81.0.beta.20180206010002 → 2.81.0.beta.20180207010002

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: aa7bfc136d7e7c764be87d0d59b96c3a9fc7c146
4
- data.tar.gz: e4ee701b3ec901c15fa264369f2297e6cb099c5d
3
+ metadata.gz: c180f27e03e5bfe73cb720d053f49f8e005c2914
4
+ data.tar.gz: bcec068462054d31c28a287fe270c1c8e12037aa
5
5
  SHA512:
6
- metadata.gz: 07852f80e4fd1e3e3b8d8ea8f5f11fd9c9f889aaff3f028050e8199fc2d0cfdeabb82fbd3461ff5ea47372d4efa13c1780a60804b5b087bc25874bdc64e967d0
7
- data.tar.gz: 7410e0d596e19cc757d860670deb3d6a10591a3c97dfba5f9b82369d0f19a669565356e7b475f5af26bee69906f66b4d2ca26190edf2639fcf11792e46eb876b
6
+ metadata.gz: 456e24304b146f4fd37b5a390bb42e07815aa81a7daea1aba0ea958365f3bbb03a5613ff535beff00361d744623cd5c5acea4010a7c9aa2a499fb8333ac96600
7
+ data.tar.gz: 89766e39865767b651ddb9bc20addb8d54c4005b3a1eb0091a828ff2c49d2fe301b831d47c88da8f67ea6c20be0ff9b599e1b940de3869df715bb2c343684254
@@ -1,5 +1,5 @@
1
1
  module Fastlane
2
- VERSION = '2.81.0.beta.20180206010002'.freeze
2
+ VERSION = '2.81.0.beta.20180207010002'.freeze
3
3
  DESCRIPTION = "The easiest way to automate beta deployments and releases for your iOS and Android apps".freeze
4
4
  MINIMUM_XCODE_RELEASE = "7.0".freeze
5
5
  RUBOCOP_REQUIREMENT = '0.49.1'.freeze
@@ -1,4 +1,5 @@
1
1
  require 'tempfile'
2
+ require 'openssl'
2
3
 
3
4
  require_relative 'helper'
4
5
 
@@ -102,15 +103,12 @@ module FastlaneCore
102
103
  end
103
104
 
104
105
  def self.sha1_fingerprint(path)
105
- result = `openssl x509 -in "#{path}" -inform der -noout -sha1 -fingerprint`
106
- begin
107
- result = result.match(/SHA1 Fingerprint=(.*)/)[1]
108
- result.delete!(':')
109
- return result
110
- rescue
111
- UI.message(result)
112
- UI.user_error!("Error parsing certificate '#{path}'")
113
- end
106
+ file_data = File.read(path.to_s)
107
+ cert = OpenSSL::X509::Certificate.new(file_data)
108
+ return OpenSSL::Digest::SHA1.new(cert.to_der).to_s.upcase
109
+ rescue => error
110
+ UI.error(error)
111
+ UI.user_error!("Error parsing certificate '#{path}'")
114
112
  end
115
113
  end
116
114
  end
@@ -3,9 +3,11 @@ require_relative 'change_password'
3
3
 
4
4
  module Match
5
5
  class Encrypt
6
+ require 'base64'
7
+ require 'openssl'
8
+ require 'securerandom'
6
9
  require 'security'
7
10
  require 'shellwords'
8
- require 'open3'
9
11
 
10
12
  def server_name(git_url)
11
13
  ["match", git_url].join("_")
@@ -46,9 +48,8 @@ module Match
46
48
 
47
49
  def encrypt_repo(path: nil, git_url: nil)
48
50
  iterate(path) do |current|
49
- crypt(path: current,
50
- password: password(git_url),
51
- encrypt: true)
51
+ encrypt(path: current,
52
+ password: password(git_url))
52
53
  UI.success("🔒 Encrypted '#{File.basename(current)}'") if FastlaneCore::Globals.verbose?
53
54
  end
54
55
  UI.success("🔒 Successfully encrypted certificates repo")
@@ -57,9 +58,8 @@ module Match
57
58
  def decrypt_repo(path: nil, git_url: nil, manual_password: nil)
58
59
  iterate(path) do |current|
59
60
  begin
60
- crypt(path: current,
61
- password: manual_password || password(git_url),
62
- encrypt: false)
61
+ decrypt(path: current,
62
+ password: manual_password || password(git_url))
63
63
  rescue
64
64
  UI.error("Couldn't decrypt the repo, please make sure you enter the right password!")
65
65
  UI.user_error!("Invalid password passed via 'MATCH_PASSWORD'") if ENV["MATCH_PASSWORD"]
@@ -81,49 +81,53 @@ module Match
81
81
  end
82
82
  end
83
83
 
84
- def crypt(path: nil, password: nil, encrypt: true)
85
- if password.to_s.strip.length == 0 && encrypt
86
- UI.user_error!("No password supplied")
87
- end
88
-
89
- tmpfile = File.join(Dir.mktmpdir, "temporary")
90
- command = ["openssl aes-256-cbc"]
91
- command << "-k #{password.shellescape}"
92
- command << "-in #{path.shellescape}"
93
- command << "-out #{tmpfile.shellescape}"
94
- command << "-a"
95
- command << "-d" unless encrypt
96
-
97
- _out, err, st = Open3.capture3(command.join(' '))
98
- success = st.success?
99
-
100
- unless err.to_s.empty?
101
- # to show an error message if something goes wrong
102
- if FastlaneCore::Globals.verbose?
103
- UI.error("`openssl` failed with an error:")
104
- UI.error(err)
105
- end
106
-
107
- # Ubuntu `openssl` does not fail on failure
108
- # but at least outputs an error message -
109
- # so we use that as indication of failure
110
- success = false
111
- end
112
-
113
- UI.crash!("Error decrypting '#{path}'") unless success
84
+ # We encrypt with MD5 because that was the most common default value in older fastlane versions which used the local OpenSSL installation
85
+ # A more secure key and IV generation is needed in the future
86
+ # IV should be randomly generated and provided unencrypted
87
+ # salt should be randomly generated and provided unencrypted (like in the current implementation)
88
+ # key should be generated with OpenSSL::KDF::pbkdf2_hmac with properly chosen parameters
89
+ # Short explanation about salt and IV: https://stackoverflow.com/a/1950674/6324550
90
+ def encrypt(path: nil, password: nil)
91
+ UI.user_error!("No password supplied") if password.to_s.strip.length == 0
92
+
93
+ data_to_encrypt = File.read(path)
94
+ salt = SecureRandom.random_bytes(8)
95
+
96
+ cipher = OpenSSL::Cipher.new('AES-256-CBC')
97
+ cipher.encrypt
98
+ cipher.pkcs5_keyivgen(password, salt, 1, "MD5")
99
+ encrypted_data = "Salted__" + salt + cipher.update(data_to_encrypt) + cipher.final
100
+
101
+ File.write(path, Base64.encode64(encrypted_data))
102
+ rescue FastlaneCore::Interface::FastlaneError
103
+ raise
104
+ rescue => error
105
+ UI.error(error.to_s)
106
+ UI.crash!("Error encrypting '#{path}'")
107
+ end
114
108
 
115
- # On non-Mac systems (more specific Ubuntu Linux) it might take some time for the file to actually be there (see #11182).
116
- # To try to circumvent this flakyness (in tests), we wait a bit until the file appears (max 2s) (usually only 0.1 is actually waited)
117
- unless FastlaneCore::Helper.mac?
118
- count = 0
119
- # sleep until file exists or 20*0.1s (=2s) passed
120
- until File.exist?(tmpfile) || count == 20
121
- sleep(0.1)
122
- count += 1
123
- end
109
+ # The encryption parameters in this implementations reflect the old behaviour which depended on the users' local OpenSSL version
110
+ # 1.0.x OpenSSL and earlier versions use MD5, 1.1.0c and newer uses SHA256, we try both before giving an error
111
+ def decrypt(path: nil, password: nil, hash_algorithm: "MD5")
112
+ stored_data = Base64.decode64(File.read(path))
113
+ salt = stored_data[8..15]
114
+ data_to_decrypt = stored_data[16..-1]
115
+
116
+ decipher = OpenSSL::Cipher.new('AES-256-CBC')
117
+ decipher.decrypt
118
+ decipher.pkcs5_keyivgen(password, salt, 1, hash_algorithm)
119
+
120
+ decrypted_data = decipher.update(data_to_decrypt) + decipher.final
121
+
122
+ File.write(path, decrypted_data)
123
+ rescue => error
124
+ fallback_hash_algorithm = "SHA256"
125
+ if hash_algorithm != fallback_hash_algorithm
126
+ decrypt(path, password, fallback_hash_algorithm)
127
+ else
128
+ UI.error(error.to_s)
129
+ UI.crash!("Error decrypting '#{path}'")
124
130
  end
125
-
126
- FileUtils.mv(tmpfile, path)
127
131
  end
128
132
  end
129
133
  end
@@ -1,4 +1,5 @@
1
1
  require 'fastlane_core/keychain_importer'
2
+ require 'openssl'
2
3
  require_relative 'module'
3
4
 
4
5
  module Match
@@ -31,15 +32,11 @@ module Match
31
32
  end
32
33
 
33
34
  def self.get_cert_info(cer_certificate_path)
34
- command = "openssl x509 -inform der -in #{cer_certificate_path.shellescape} -subject -dates -noout"
35
- command << " &" # start in separate process
36
- output = Helper.backticks(command, print: FastlaneCore::Globals.verbose?)
35
+ cert = OpenSSL::X509::Certificate.new(File.read(cer_certificate_path))
37
36
 
38
37
  # openssl output:
39
- # subject= /UID={User ID}/CN={Certificate Name}/OU={Certificate User}/O={Organisation}/C={Country}\n
40
- # notBefore={Start datetime}\n
41
- # notAfter={End datetime}
42
- cert_info = output.gsub(/\s*subject=\s*/, "").tr("/", "\n")
38
+ # subject= /UID={User ID}/CN={Certificate Name}/OU={Certificate User}/O={Organisation}/C={Country}
39
+ cert_info = cert.subject.to_s.gsub(/\s*subject=\s*/, "").tr("/", "\n")
43
40
  out_array = cert_info.split("\n")
44
41
  openssl_keys_to_readable_keys = {
45
42
  'UID' => 'User ID',
@@ -54,6 +51,8 @@ module Match
54
51
  return out_array.map { |x| x.split(/=+/) if x.include?("=") }
55
52
  .compact
56
53
  .map { |k, v| [openssl_keys_to_readable_keys.fetch(k, k), v] }
54
+ .append([openssl_keys_to_readable_keys.fetch("notBefore"), cert.not_before])
55
+ .append([openssl_keys_to_readable_keys.fetch("notAfter"), cert.not_after])
57
56
  rescue => ex
58
57
  UI.error(ex)
59
58
  return {}
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fastlane
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.81.0.beta.20180206010002
4
+ version: 2.81.0.beta.20180207010002
5
5
  platform: ruby
6
6
  authors:
7
7
  - Fumiya Nakamura
@@ -25,7 +25,7 @@ authors:
25
25
  autorequire:
26
26
  bindir: bin
27
27
  cert_chain: []
28
- date: 2018-02-06 00:00:00.000000000 Z
28
+ date: 2018-02-07 00:00:00.000000000 Z
29
29
  dependencies:
30
30
  - !ruby/object:Gem::Dependency
31
31
  name: slack-notifier