E2E example in PHP and Python
This commit is contained in:
parent
99e6c0ff97
commit
67da1e4922
5 changed files with 113 additions and 117 deletions
46
examples/publish-php/publish-encrypted.php
Normal file
46
examples/publish-php/publish-encrypted.php
Normal file
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
|
||||
$message = [
|
||||
"message" => "Secret!",
|
||||
"priority" => 5
|
||||
];
|
||||
$plaintext = json_encode($message);
|
||||
$key = deriveKey("secr3t password", "https://ntfy.sh/mysecret");
|
||||
$ciphertext = encrypt($plaintext, $key);
|
||||
|
||||
file_get_contents('https://ntfy.sh/mysecret', false, stream_context_create([
|
||||
'http' => [
|
||||
'method' => 'POST', // PUT also works
|
||||
'header' =>
|
||||
"Content-Type: text/plain\r\n" .
|
||||
"Encryption: jwe",
|
||||
'content' => $ciphertext
|
||||
]
|
||||
]));
|
||||
|
||||
function deriveKey($password, $topicUrl)
|
||||
{
|
||||
$salt = hex2bin(hash("sha256", $topicUrl));
|
||||
return openssl_pbkdf2($password, $salt, 32, 50000, "sha256");
|
||||
}
|
||||
|
||||
function encrypt(string $plaintext, string $key): string
|
||||
{
|
||||
$encodedHeader = base64url_encode(json_encode(["alg" => "dir", "enc" => "A256GCM"]));
|
||||
$iv = openssl_random_pseudo_bytes(12); // GCM is used with a 96-bit IV
|
||||
$aad = $encodedHeader;
|
||||
$tag = null;
|
||||
$content = openssl_encrypt($plaintext, "aes-256-gcm", $key, OPENSSL_RAW_DATA, $iv, $tag, $aad);
|
||||
return
|
||||
$encodedHeader . "." .
|
||||
"." . // No content encryption key (CEK) in "dir" mode
|
||||
base64url_encode($iv) . "." .
|
||||
base64url_encode($content) . "." .
|
||||
base64url_encode($tag);
|
||||
}
|
||||
|
||||
function base64url_encode($input)
|
||||
{
|
||||
return str_replace('=', '', strtr(base64_encode($input), '+/', '-_'));
|
||||
}
|
||||
|
42
examples/publish-python/publish-encrypted.py
Executable file
42
examples/publish-python/publish-encrypted.py
Executable file
|
@ -0,0 +1,42 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import requests
|
||||
|
||||
import json
|
||||
from base64 import b64encode, urlsafe_b64encode, b64decode
|
||||
from Crypto.Cipher import AES
|
||||
from Crypto.Random import get_random_bytes
|
||||
from Crypto.Protocol.KDF import PBKDF2
|
||||
from Crypto.Hash import SHA256
|
||||
from Crypto.Random import get_random_bytes
|
||||
|
||||
def derive_key(password, topic_url):
|
||||
salt = SHA256.new(data=topic_url.encode('utf-8')).digest()
|
||||
return PBKDF2(password, salt, 32, count=50000, hmac_hash_module=SHA256)
|
||||
|
||||
def encrypt(plaintext, key):
|
||||
encoded_header = b64urlencode('{"alg":"dir","enc":"A256GCM"}'.encode('utf-8'))
|
||||
iv = get_random_bytes(12) # GCM is used with a 96-bit IV
|
||||
aad = encoded_header
|
||||
cipher = AES.new(key, AES.MODE_GCM, nonce=iv)
|
||||
cipher.update(aad.encode('utf-8'))
|
||||
ciphertext, tag = cipher.encrypt_and_digest(plaintext.encode('utf-8'))
|
||||
return "{header}..{iv}.{ciphertext}.{tag}".format(
|
||||
header = encoded_header,
|
||||
iv = b64urlencode(iv),
|
||||
ciphertext = b64urlencode(ciphertext),
|
||||
tag = b64urlencode(tag)
|
||||
)
|
||||
|
||||
def b64urlencode(b):
|
||||
return urlsafe_b64encode(b).decode('utf-8').replace("=", "")
|
||||
|
||||
key = derive_key("secr3t password", "https://ntfy.sh/mysecret")
|
||||
ciphertext = encrypt('{"message":"Python says hi","tags":["secret"]}', key)
|
||||
|
||||
resp = requests.post("https://ntfy.sh/mysecret",
|
||||
data=ciphertext,
|
||||
headers={
|
||||
"Encryption": "jwe"
|
||||
})
|
||||
resp.raise_for_status()
|
2
examples/publish-python/requirements.txt
Normal file
2
examples/publish-python/requirements.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
requests
|
||||
pycryptodome
|
Loading…
Add table
Add a link
Reference in a new issue