Skip to content

Commit

Permalink
add signature verification with gpg_ex
Browse files Browse the repository at this point in the history
  • Loading branch information
sheerlox committed Nov 26, 2023
1 parent 9ff18c0 commit 2a047ed
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 9 deletions.
41 changes: 32 additions & 9 deletions lib/nodelix/node_downloader.ex
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ defmodule Nodelix.NodeDownloader do
@checksums_signature_base_url "https://nodejs.org/dist/v$version/SHASUMS256.txt.sig"

@signing_keys_list_url "https://raw.githubusercontent.com/nodejs/release-keys/main/keys.list"
@signing_keys_dir_url "https://raw.githubusercontent.com/nodejs/release-keys/main/keys"
@signing_key_base_url "https://raw.githubusercontent.com/nodejs/release-keys/main/keys/$key_id.asc"

Check warning on line 10 in lib/nodelix/node_downloader.ex

View workflow job for this annotation

GitHub Actions / Build and test

module attribute @signing_key_base_url was set but never used

require Logger

Expand All @@ -22,9 +22,7 @@ defmodule Nodelix.NodeDownloader do
- [X] fetch checksums file signature (https://nodejs.org/dist/v20.10.0/SHASUMS256.txt.sig)
- [X] fetch Node.js signing keys list (https://raw.githubusercontent.com/nodejs/release-keys/main/keys.list)
- [X] fetch keys (https://raw.githubusercontent.com/nodejs/release-keys/main/keys/4ED778F539E3634C779C87C6D7062848A1AB005C.asc)
- [ ] convert keys to PEM (https://stackoverflow.com/questions/10966256/erlang-importing-gpg-public-key)
- [ ] check signature of the checksums file with each key until there's a match
- [ ] match the hash for the archive filename
- [X] verify signature of the checksums file
- [ ] check integrity of the downloaded archive
- [ ] decompress archive (delete destination first, see https://github.com/phoenixframework/tailwind/pull/67)
"""
Expand Down Expand Up @@ -71,21 +69,46 @@ defmodule Nodelix.NodeDownloader do
def install(archive_base_url \\ @default_archive_base_url) do
fetch_archive(archive_base_url)
fetch_checksums_and_signature()
_signing_keys = fetch_signing_keys()
%{checksums: checksums_path, signature: signature_path} = paths()

verify_signature!(checksums_path, signature_path)

Logger.debug("Signature ok!")
end

defp fetch_signing_keys() do
Logger.debug("Downloading signing keys from #{@signing_keys_list_url}")
defp verify_signature!(file_path, signature_path) do
Logger.debug("Downloading signing keys list from #{@signing_keys_list_url}")

signing_key_ids =
@signing_keys_list_url
|> HttpUtils.fetch_body!()
|> String.trim()
|> String.split("\n")

Enum.map(signing_key_ids, fn key_id ->
HttpUtils.fetch_body!("#{@signing_keys_dir_url}/#{key_id}.asc")
Logger.debug("Using GPG to retrieve signing keys")

%{path: keystore_path} = keystore = GPGex.Keystore.get_keystore_temp()

signing_key_ids
|> Enum.map(fn key_id ->
GPGex.cmd!(["--recv-keys", key_id], keystore: keystore)
end)

case GPGex.cmd(
[
"--verify",
signature_path,
file_path
],
keystore: keystore
) do
{:ok, _, _} ->
File.rm_rf!(keystore_path)
:ok

{:error, _, _, _} ->
raise "invalid signature"
end
end

defp fetch_archive(archive_base_url) do
Expand Down
1 change: 1 addition & 0 deletions mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ defmodule Nodelix.MixProject do

defp deps do
[
{:gpg_ex, "1.0.0-alpha.3"},
{:castore, "~> 1.0"},
{:ex_doc, ">= 0.0.0", only: :dev, runtime: false}
]
Expand Down
2 changes: 2 additions & 0 deletions mix.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
%{
"castore": {:hex, :castore, "1.0.4", "ff4d0fb2e6411c0479b1d965a814ea6d00e51eb2f58697446e9c41a97d940b28", [:mix], [], "hexpm", "9418c1b8144e11656f0be99943db4caf04612e3eaecefb5dae9a2a87565584f8"},
"earmark_parser": {:hex, :earmark_parser, "1.4.38", "b42252eddf63bda05554ba8be93a1262dc0920c721f1aaf989f5de0f73a2e367", [:mix], [], "hexpm", "2cd0907795aaef0c7e8442e376633c5b3bd6edc8dbbdc539b22f095501c1cdb6"},
"elixir_uuid": {:hex, :elixir_uuid, "1.2.1", "dce506597acb7e6b0daeaff52ff6a9043f5919a4c3315abb4143f0b00378c097", [:mix], [], "hexpm", "f7eba2ea6c3555cea09706492716b0d87397b88946e6380898c2889d68585752"},
"ex_doc": {:hex, :ex_doc, "0.30.9", "d691453495c47434c0f2052b08dd91cc32bc4e1a218f86884563448ee2502dd2", [:mix], [{:earmark_parser, "~> 1.4.31", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "d7aaaf21e95dc5cddabf89063327e96867d00013963eadf2c6ad135506a8bc10"},
"gpg_ex": {:hex, :gpg_ex, "1.0.0-alpha.3", "d5860bb91b8c833441770f38707ad0556074ab5772f8e1dfc71ddedf7cae9e78", [:mix], [{:elixir_uuid, "~> 1.2", [hex: :elixir_uuid, repo: "hexpm", optional: false]}], "hexpm", "748d4283f0a62836afa07d27944f54c29cd6f02bd238ab1f72534f5273745630"},
"makeup": {:hex, :makeup, "1.1.1", "fa0bc768698053b2b3869fa8a62616501ff9d11a562f3ce39580d60860c3a55e", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "5dc62fbdd0de44de194898b6710692490be74baa02d9d108bc29f007783b0b48"},
"makeup_elixir": {:hex, :makeup_elixir, "0.16.1", "cc9e3ca312f1cfeccc572b37a09980287e243648108384b97ff2b76e505c3555", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "e127a341ad1b209bd80f7bd1620a15693a9908ed780c3b763bccf7d200c767c6"},
"makeup_erlang": {:hex, :makeup_erlang, "0.1.2", "ad87296a092a46e03b7e9b0be7631ddcf64c790fa68a9ef5323b6cbb36affc72", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "f3f5a1ca93ce6e092d92b6d9c049bcda58a3b617a8d888f8e7231c85630e8108"},
Expand Down

0 comments on commit 2a047ed

Please sign in to comment.