<?php
/**
 * IBAN encryption at rest.
 *
 * IBANs are personal data under the GDPR, and a Verein's member bank data
 * leaks into every database backup, staging clone and SQL export if stored in
 * plain text. Everything stays on the site's own server — this plugin never
 * transmits member data anywhere — but at-rest encryption keeps a leaked
 * backup from becoming a leaked bank-account list.
 *
 * Uses libsodium (bundled with PHP since 7.2) with a key derived from the
 * site's AUTH_KEY salt. That means: rotate AUTH_KEY and stored IBANs become
 * unreadable — the settings screen warns about this, and the last four
 * characters are kept alongside in plain text so the member list stays
 * identifiable even then.
 */

if ( ! defined( 'ABSPATH' ) ) {
	die;
}

class BSTEW_Crypto {

	private static function key() {
		$salt = defined( 'AUTH_KEY' ) ? AUTH_KEY : wp_salt( 'auth' );
		return sodium_crypto_generichash( 'bst-iban-v1' . $salt, '', SODIUM_CRYPTO_SECRETBOX_KEYBYTES );
	}

	/** @return string Base64 nonce+ciphertext, '' for empty input. */
	public static function encrypt( $plain ) {
		$plain = (string) $plain;
		if ( '' === $plain ) {
			return '';
		}
		$nonce = random_bytes( SODIUM_CRYPTO_SECRETBOX_NONCEBYTES );
		$box   = sodium_crypto_secretbox( $plain, $nonce, self::key() );
		return base64_encode( $nonce . $box ); // phpcs:ignore
	}

	/** @return string Plaintext, or '' when the payload is missing or the key changed. */
	public static function decrypt( $stored ) {
		$raw = base64_decode( (string) $stored, true ); // phpcs:ignore
		if ( false === $raw || strlen( $raw ) <= SODIUM_CRYPTO_SECRETBOX_NONCEBYTES ) {
			return '';
		}
		$nonce = substr( $raw, 0, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES );
		$box   = substr( $raw, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES );
		$plain = sodium_crypto_secretbox_open( $box, $nonce, self::key() );
		return false === $plain ? '' : $plain;
	}

	/** "DE12 •••• 3456" style display form; safe for lists and logs. */
	public static function mask_iban( $iban ) {
		$iban = preg_replace( '/\s+/', '', (string) $iban );
		if ( strlen( $iban ) < 8 ) {
			return $iban;
		}
		return substr( $iban, 0, 4 ) . ' •••• ' . substr( $iban, -4 );
	}
}
