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

Sign up to get free protection for your applications and to get access to all the features.
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