publish-encrypted.php 1.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546
  1. <?php
  2. $message = [
  3. "message" => "Secret!",
  4. "priority" => 5
  5. ];
  6. $plaintext = json_encode($message);
  7. $key = deriveKey("secr3t password", "https://ntfy.sh/mysecret");
  8. $ciphertext = encrypt($plaintext, $key);
  9. file_get_contents('https://ntfy.sh/mysecret', false, stream_context_create([
  10. 'http' => [
  11. 'method' => 'POST', // PUT also works
  12. 'header' =>
  13. "Content-Type: text/plain\r\n" .
  14. "Encryption: jwe",
  15. 'content' => $ciphertext
  16. ]
  17. ]));
  18. function deriveKey($password, $topicUrl)
  19. {
  20. $salt = hex2bin(hash("sha256", $topicUrl));
  21. return openssl_pbkdf2($password, $salt, 32, 50000, "sha256");
  22. }
  23. function encrypt(string $plaintext, string $key): string
  24. {
  25. $encodedHeader = base64url_encode(json_encode(["alg" => "dir", "enc" => "A256GCM"]));
  26. $iv = openssl_random_pseudo_bytes(12); // GCM is used with a 96-bit IV
  27. $aad = $encodedHeader;
  28. $tag = null;
  29. $content = openssl_encrypt($plaintext, "aes-256-gcm", $key, OPENSSL_RAW_DATA, $iv, $tag, $aad);
  30. return
  31. $encodedHeader . "." .
  32. "." . // No content encryption key (CEK) in "dir" mode
  33. base64url_encode($iv) . "." .
  34. base64url_encode($content) . "." .
  35. base64url_encode($tag);
  36. }
  37. function base64url_encode($input)
  38. {
  39. return str_replace('=', '', strtr(base64_encode($input), '+/', '-_'));
  40. }