Sync your WordPress posts to standard.site records on your PDS
at main 73 lines 1.7 kB view raw
1<?php 2declare(strict_types=1); 3/** 4 * Token encryption at rest using libsodium. 5 * 6 * @package Wireservice 7 */ 8 9namespace Wireservice; 10 11if (! defined('ABSPATH')) { 12 exit; 13} 14 15class Encryption 16{ 17 /** 18 * Derive an encryption key from WordPress auth constants. 19 * 20 * @return string 32-byte key. 21 */ 22 private static function get_key(): string 23 { 24 return sodium_crypto_generichash( 25 AUTH_KEY . AUTH_SALT, 26 "", 27 SODIUM_CRYPTO_SECRETBOX_KEYBYTES, 28 ); 29 } 30 31 /** 32 * Encrypt a plaintext string. 33 * 34 * @param string $plaintext The value to encrypt. 35 * @return string Base64-encoded nonce + ciphertext. 36 */ 37 public static function encrypt(string $plaintext): string 38 { 39 $nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES); 40 $ciphertext = sodium_crypto_secretbox($plaintext, $nonce, self::get_key()); 41 42 return base64_encode($nonce . $ciphertext); 43 } 44 45 /** 46 * Decrypt a previously encrypted string. 47 * 48 * Returns false if decryption fails, which also covers the case 49 * where a plaintext (never-encrypted) value is passed in. 50 * 51 * @param string $encoded Base64-encoded nonce + ciphertext. 52 * @return string|false The plaintext or false on failure. 53 */ 54 public static function decrypt(string $encoded): string|false 55 { 56 $decoded = base64_decode($encoded, true); 57 58 if ($decoded === false) { 59 return false; 60 } 61 62 $nonce_length = SODIUM_CRYPTO_SECRETBOX_NONCEBYTES; 63 64 if (strlen($decoded) < $nonce_length + 1) { 65 return false; 66 } 67 68 $nonce = substr($decoded, 0, $nonce_length); 69 $ciphertext = substr($decoded, $nonce_length); 70 71 return sodium_crypto_secretbox_open($ciphertext, $nonce, self::get_key()); 72 } 73}