Skip to content

Commit 0f4079d

Browse files
committed
fix: add padded message
1 parent 6e4c65a commit 0f4079d

File tree

5 files changed

+39
-24
lines changed

5 files changed

+39
-24
lines changed

lib/web_push_elixir.ex

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,15 @@ defmodule WebPushElixir do
2020
|> :binary.part(0, length)
2121
end
2222

23-
defp encrypt(
24-
message,
25-
auth,
26-
p256dh,
27-
vapid_public_key,
28-
vapid_private_key
29-
) do
23+
defp encrypt(message, p256dh, auth) do
3024
client_public_key = url_decode(p256dh)
3125
client_auth_secret = url_decode(auth)
3226

3327
salt = :crypto.strong_rand_bytes(16)
3428

35-
shared_secret = :crypto.compute_key(:ecdh, client_public_key, vapid_private_key, :prime256v1)
29+
{local_public_key, local_private_key} = :crypto.generate_key(:ecdh, :prime256v1)
30+
31+
shared_secret = :crypto.compute_key(:ecdh, client_public_key, local_private_key, :prime256v1)
3632

3733
pseudo_random_key =
3834
hmac_based_key_derivation_function(
@@ -45,7 +41,7 @@ defmodule WebPushElixir do
4541
context =
4642
<<0, byte_size(client_public_key)::unsigned-big-integer-size(16)>> <>
4743
client_public_key <>
48-
<<byte_size(vapid_public_key)::unsigned-big-integer-size(16)>> <> vapid_public_key
44+
<<byte_size(local_public_key)::unsigned-big-integer-size(16)>> <> local_public_key
4945

5046
content_encryption_key_info = "Content-Encoding: aesgcm" <> <<0>> <> "P-256" <> context
5147

@@ -60,17 +56,19 @@ defmodule WebPushElixir do
6056
12
6157
)
6258

59+
padded_message = <<0::unsigned-big-integer-size(16)>> <> :binary.copy(<<0>>, 0) <> message
60+
6361
{cipher_text, cipher_tag} =
6462
:crypto.crypto_one_time_aead(
6563
:aes_128_gcm,
6664
content_encryption_key,
6765
nonce,
68-
message,
69-
"",
66+
padded_message,
67+
<<>>,
7068
true
7169
)
7270

73-
%{ciphertext: cipher_text <> cipher_tag, salt: salt}
71+
%{ciphertext: cipher_text <> cipher_tag, salt: salt, local_public_key: local_public_key}
7472
end
7573

7674
defp sign_json_web_token(endpoint, vapid_public_key, vapid_private_key) do
@@ -100,15 +98,18 @@ defmodule WebPushElixir do
10098
%{endpoint: endpoint, keys: %{auth: auth, p256dh: p256dh}} =
10199
Jason.decode!(subscription, keys: :atoms)
102100

103-
encrypted = encrypt(message, auth, p256dh, vapid_public_key, vapid_private_key)
101+
encrypted = encrypt(message, p256dh, auth)
104102

105103
signed_json_web_token =
106104
sign_json_web_token(endpoint, vapid_public_key, vapid_private_key)
107105

108106
HTTPoison.post(endpoint, encrypted.ciphertext, %{
109107
"Authorization" => "WebPush #{signed_json_web_token}",
110108
"Content-Encoding" => "aesgcm",
111-
"Crypto-Key" => "p256ecdsa=#{url_encode(vapid_public_key)}",
109+
"Content-Length" => "#{byte_size(encrypted.ciphertext)}",
110+
"Content-Type" => "application/octet-stream",
111+
"Crypto-Key" =>
112+
"dh=#{url_encode(encrypted.local_public_key)};p256ecdsa=#{url_encode(vapid_public_key)}",
112113
"Encryption" => "salt=#{url_encode(encrypted.salt)}",
113114
"TTL" => "60"
114115
})

lib/web_push_elixir/main.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
navigator.serviceWorker
2-
.register('/web-push-elixir/service-worker.js')
2+
.register('/service-worker.js')
33
.then(registration => {
44
console.log('Service worker successfully registered.');
55
})
@@ -20,7 +20,7 @@ button.addEventListener('click', event => {
2020

2121
registration.pushManager.subscribe({
2222
userVisibleOnly: true,
23-
applicationServerKey: "some_public_key"
23+
applicationServerKey: 'some_public_key'
2424
}).then(pushSubscription => {
2525
console.log('Received PushSubscription: ', JSON.stringify(pushSubscription));
2626
});

lib/web_push_elixir/mock_server.ex

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ defmodule WebPushElixir.MockServer do
44
plug(:match)
55
plug(:dispatch)
66

7-
post "/some-endpoint" do
7+
post "/some-push-service" do
88
conn
99
|> Plug.Conn.send_resp(200, "ok")
1010
end
@@ -27,13 +27,13 @@ defmodule WebPushElixir.MockServer do
2727
|> Plug.Conn.send_file(200, "./lib/web_push_elixir/main.js")
2828
end
2929

30-
get "/web-push-elixir/service-worker.js" do
30+
get "/service-worker.js" do
3131
conn
3232
|> put_resp_header("content-type", "application/x-javascript")
3333
|> Plug.Conn.send_file(200, "./lib/web_push_elixir/service-worker.js")
3434
end
3535

36-
get "/service-worker.js" do
36+
get "/web-push-elixir/service-worker.js" do
3737
conn
3838
|> put_resp_header("content-type", "application/x-javascript")
3939
|> Plug.Conn.send_file(200, "./lib/web_push_elixir/service-worker.js")

test/generate_vapid_keys_test.exs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ defmodule GenerateVapidKeysTest do
33

44
test "it should generate" do
55
assert %{
6-
vapid_public_key: <<_public_key::binary>>,
7-
vapid_private_key: <<_private_key::binary>>,
6+
vapid_public_key: <<_vapid_public_key::binary>>,
7+
vapid_private_key: <<_vapid_private_key::binary>>,
88
vapid_subject: "mailto:admin@email.com"
99
} = Mix.Tasks.Generate.Vapid.Keys.run([])
1010
end

test/web_push_elixir_test.exs

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
defmodule WebPushElixirTest do
22
use ExUnit.Case
33

4-
@subscription ~c"{\"endpoint\":\"http://localhost:4040/some-endpoint\",\"keys\":{\"p256dh\":\"BIPUL12DLfytvTajnryr2PRdAgXS3HGKiLqndGcJGabyhHheJYlNGCeXl1dn18gSJ1WAkAPIxr4gK0_dQds4yiI=\",\"auth\":\"FPssNDTKnInHVndSTdbKFw==\"}}"
4+
@subscription ~c"{\"endpoint\":\"http://localhost:4040/some-push-service\",\"keys\":{\"p256dh\":\"BIPUL12DLfytvTajnryr2PRdAgXS3HGKiLqndGcJGabyhHheJYlNGCeXl1dn18gSJ1WAkAPIxr4gK0_dQds4yiI=\",\"auth\":\"FPssNDTKnInHVndSTdbKFw==\"}}"
55

66
test "it should send notification" do
77
%{
@@ -21,7 +21,9 @@ defmodule WebPushElixirTest do
2121
assert [
2222
{"Authorization", "WebPush " <> <<_jwt::binary>>},
2323
{"Content-Encoding", "aesgcm"},
24-
{"Crypto-Key", "p256ecdsa=" <> <<_vapid_public_key::binary>>},
24+
{"Content-Length", <<_content_length::binary>>},
25+
{"Content-Type", "application/octet-stream"},
26+
{"Crypto-Key", <<_crypto_keys::binary>>},
2527
{"Encryption", "salt=" <> <<_salt::binary>>},
2628
{"TTL", "60"}
2729
] = response.request.headers
@@ -58,14 +60,26 @@ defmodule WebPushElixirTest do
5860

5961
assert [
6062
{"cache-control", "max-age=0, private, must-revalidate"},
61-
{"content-length", "903"},
63+
{"content-length", "887"},
6264
{"content-type", "application/x-javascript"},
6365
{"date", <<_date::binary>>},
6466
{"server", "Cowboy"}
6567
] = response.headers
6668
end
6769

6870
test "it should have service worker headers" do
71+
{:ok, response} = HTTPoison.get(~c"http://localhost:4040/service-worker.js")
72+
73+
assert [
74+
{"cache-control", "max-age=0, private, must-revalidate"},
75+
{"content-length", "262"},
76+
{"content-type", "application/x-javascript"},
77+
{"date", <<_date::binary>>},
78+
{"server", "Cowboy"}
79+
] = response.headers
80+
end
81+
82+
test "it should have static service worker headers" do
6983
{:ok, response} = HTTPoison.get(~c"http://localhost:4040/web-push-elixir/service-worker.js")
7084

7185
assert [

0 commit comments

Comments
 (0)