Mac OS uses LibreSSL. Getting OpenSSL can be done with brew:
brew install openssl
After which, an alias can be used for openssl commands:
ls -lah $(echo /opt/homebrew/Cellar/openssl@*/*/bin/openssl)
alias openssl=/opt/homebrew/Cellar/openssl@1.1/1.1.1s/bin/openssl
Recipient generates a keypair:
openssl genpkey -algorithm X25519 -outform DER -out private.key
openssl pkey -inform DER -in private.key -outform DER -pubout -out public.key
Sender generates a keypair:
openssl genpkey -algorithm X25519 -outform DER -out sender.private.key
openssl pkey -inform DER -in sender.private.key -outform DER -pubout -out sender.public.key
Sender generates a shared secret with the recipient:
openssl pkeyutl -derive -keyform DER -inkey sender.private.key -peerform DER -peerkey public.key -out shared.key
Sender packs an encrypted message for the recipient including their public key:
openssl base64 -A -in sender.public.key -out message.enc
echo 'hello world' | openssl enc -aes-256-cbc -pbkdf2 -kfile shared.key -in - -out /dev/stdout | openssl base64 -A -in - >> message.enc
Recipient derives the shared secret:
head -n1 message.enc | openssl base64 -d -in - -out from.public.key
openssl pkeyutl -derive -keyform DER -inkey private.key -peerform DER -peerkey from.public.key -out shared2.key
Recipient decrypts the message:
tail -n1 message.enc | openssl base64 -d -in - | openssl enc -d -aes-256-cbc -pbkdf2 -kfile shared2.key -in - -out /dev/stdout