Skip to content

Commit

Permalink
Fix GPG verification on Windows and add GPG2
Browse files Browse the repository at this point in the history
1. Use IO.popen to avoid issues with missing escaping in the paths.
2. Remove unused method normalize_path.
3. Try both gpg2 and gpg for signature verification.
4. Use relative path for keyring and delete the key afterwards.

To point 4:

The reason for use relative paths is that there are 3 different flavors of gpg
are used on Windows, which differ in the way how absolute paths are specified:

MINGW: C:\path\to\keyring.gpg
MSYS2: /c/path/to/keyring.gpg
Cygwin: /cygdrive/c/path/to/keyring.gpg

Since there is no reliable way to find out which flavor of gpg is actually
running, it's best to use relative paths only. The downside is, that we can
not reliably say where the file is located in the end, which is why only the
imported key is deleted afterwards, not the whole keyring file.
  • Loading branch information
larskanis committed Feb 4, 2017
1 parent 2538320 commit a91d840
Showing 1 changed file with 16 additions and 14 deletions.
30 changes: 16 additions & 14 deletions lib/mini_portile2/mini_portile.rb
Original file line number Diff line number Diff line change
Expand Up @@ -251,34 +251,36 @@ def files_hashs
end
end

def normalize_path path
path
# path.gsub(File::SEPARATOR, File::ALT_SEPARATOR || File::SEPARATOR)
end
KEYRING_NAME = "mini_portile_keyring.gpg"

def verify_file(file)
if file.has_key?(:gpg)
gpg = file[:gpg]

signature_url = gpg[:signature_url] || "#{file[:url]}.asc"
signature_file = file[:local_path] + ".asc"
# download the signature file
download_file(signature_url, signature_file)

key = Tempfile.new('armored_key')
key.write(gpg[:key])
key.close
key_path = normalize_path(key.path)
gpg_exe = which('gpg2') || which('gpg') || raise("Neither GPG nor GPG2 is installed")

keyring = Tempfile.new('keyring')
keyring.close
keyring_path = normalize_path(keyring.path)
# import the key into our own keyring
gpg_status = IO.popen([gpg_exe, "--status-fd", "1", "--no-default-keyring", "--keyring", KEYRING_NAME, "--import"], "w+") do |io|
io.write gpg[:key]
io.close_write
io.read
end
raise "invalid gpg key provided" unless /\[GNUPG:\] IMPORT_OK \d+ (?<key_id>[0-9a-f]+)/i =~ gpg_status

gpg_status = `gpg --status-fd 1 --no-default-keyring --keyring #{keyring_path} --import #{key_path}`
# verify the signature against our keyring
gpg_status = IO.popen([gpg_exe, "--status-fd", "1", "--no-default-keyring", "--keyring", KEYRING_NAME, "--verify", signature_file, file[:local_path]], &:read)

raise "invalid gpg key provided" unless gpg_status.match(/\[GNUPG:\] IMPORT_OK/)
# remove the key from our keyring
IO.popen([gpg_exe, "--batch", "--yes", "--no-default-keyring", "--keyring", KEYRING_NAME, "--delete-keys", key_id], &:read)

gpg_status = `gpg --status-fd 1 --no-default-keyring --keyring #{keyring_path} --verify #{signature_file} #{file[:local_path]} 2>&1`
raise "unable to delete the imported key" unless $?.exitstatus==0
raise "signature mismatch" unless gpg_status.match(/^\[GNUPG:\] VALIDSIG/)

else
digest = case
when exp=file[:sha256] then Digest::SHA256
Expand Down

0 comments on commit a91d840

Please sign in to comment.