Skip to content
Closed
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
14b3cf3
Initial plan
Copilot Aug 1, 2025
b101797
Implement XOR-based email obfuscation methods (methods 2.7 and 2.8)
Copilot Aug 1, 2025
f226bcf
Fix namespace issues and complete XOR obfuscation implementation
Copilot Aug 1, 2025
3c86028
Remove jQuery dependency from emailobfuscator.js - addresses issue #40
Copilot Aug 1, 2025
81229ae
Add support for mailto links with subject and body parameters - addre…
Copilot Aug 1, 2025
b1194d5
Update README with new XOR methods, security improvements, and jQuery…
Copilot Aug 1, 2025
9e1ba87
Fix XOR JavaScript implementation - unified approach using external J…
Copilot Aug 1, 2025
cfb9232
Fix JavaScript inclusion configuration: show autoload_js setting for …
Copilot Aug 1, 2025
79746cd
Update lib/EmailObfuscator.php
skerbis Aug 1, 2025
d149c95
Update assets/emailobfuscator.js
skerbis Aug 1, 2025
1f0b9fd
Update lib/EmailObfuscator.php
skerbis Aug 1, 2025
d4e8e6f
Update assets/emailobfuscator.js
skerbis Aug 1, 2025
0c10f0f
Update lib/EmailObfuscator.php
skerbis Aug 1, 2025
5623ff8
Update assets/emailobfuscator.js
skerbis Aug 1, 2025
5823579
Update assets/emailobfuscator.js
skerbis Aug 1, 2025
270827b
Update lib/EmailObfuscator.php
skerbis Aug 1, 2025
6d7059f
Update lib/EmailObfuscator.php
skerbis Aug 1, 2025
e7c5d97
Fix JavaScript syntax errors in XOR email deobfuscation function
Copilot Aug 1, 2025
b80b631
Fix base64UrlDecode InvalidCharacterError with proper padding logic a…
Copilot Aug 1, 2025
28898b2
Fix base64UrlDecode InvalidCharacterError with improved binary data h…
Copilot Aug 1, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
test_full_obfuscation.html
101 changes: 87 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,35 +5,70 @@ Das [REDAXO](http://www.redaxo.org)-Addon sorgt dafür, dass alle E-Mailadressen

## Funktionsweise

Durch die Integration des email_obfuscator Addons von RexDude stehen verschiedene Verschleierungsmethoden für E-Mailadressen zur Verfügung:
Durch die Integration des email_obfuscator Addons stehen verschiedene Verschleierungsmethoden für E-Mailadressen zur Verfügung:

1. __ROT13 Einhorn-Markup__: Diese Methode findet alle E-Mailadressen und ersetzt deren `@` durch spezielles Einhorn-Markup: `<span class="unicorn"><span>_at_</span></span>`. Dadurch kann die E-Mailadresse nicht mehr so einfach von Bots ausgelesen werden und sollte ziemlich gut vor Spam geschützt sein. Weiterhin werden auch alle mailto-Links erkannt und verschlüsselt.
Beim Aufruf der Seite werden alle geschützten E-Mailadressen und mailto-Links mittels __JavaScript__ wieder entschlüsselt und in die ursprüngliche Form gebracht. __CSS-Styles__ sorgen dafür, dass die geschützten E-Mailadressen auf der Website richtig angezeigt werden, also mit `@` statt Einhorn. Damit fällt der Wechsel von verschlüsselt nach unverschlüsselt nicht auf, und auch in Umgebungen ohne JavaScript wird eine verschlüsselte Adresse richtig dargestellt.
__Bitte beachten__: Diese Methode benötigt für die Einhorn-Markup Methode __jQuery__ für die JavaScript-Funktionalität!
### Sichere Methoden (empfohlen)

2. __ROT13 JavaScript Verschlüsselung__: Um die Email-Adressen zu schützen, wird die E-Mailadresse durch ein JavaScript ersetzt, das die E-Mailadresse ins Dokument schreibt. Zur Verschleierung wird die Technik "ROT13 Encryption" angewendet.
1. __XOR Verschlüsselung (Standard)__: Diese moderne Methode verwendet XOR-Verschlüsselung mit einem festen Schlüssel, um E-Mailadressen sicher zu verschleiern. Die verschlüsselten Daten werden in `data-*` Attributen gespeichert und automatisch per JavaScript entschlüsselt. Diese Methode ist exponentiell sicherer als die veralteten ROT13-Verfahren und bietet zuverlässigen Schutz vor Spam-Bots.
__Vorteile__: Starke Verschlüsselung, kein jQuery erforderlich, unterstützt mailto-Parameter wie `?subject=Betreff&body=Nachricht`

2. __XOR Verschlüsselung mit dynamischem Schlüssel__: Diese besonders sichere Variante generiert für jede Seite/jeden Artikel einen anderen Verschlüsselungsschlüssel basierend auf der Artikel-ID. Dadurch wird die gleiche E-Mailadresse auf verschiedenen Seiten unterschiedlich verschlüsselt, was die Sicherheit maximiert.
__Vorteile__: Höchste Sicherheitsstufe, kontextabhängige Verschlüsselung, kein jQuery erforderlich, unterstützt mailto-Parameter

### Veraltete Methoden (unsicher, nicht empfohlen)

3. __ROT13 Einhorn-Markup__ ⚠️ __Veraltet, unsicher__: Diese Methode findet alle E-Mailadressen und ersetzt deren `@` durch spezielles Einhorn-Markup: `<span class="unicorn"><span>_at_</span></span>`. ROT13 ist ein einfacher Caesar-Cipher, der von modernen Tools leicht geknackt werden kann.
__Bitte beachten__: Diese Methode benötigt __jQuery__ für die JavaScript-Funktionalität! jQuery wird seit Version 2.0 des Addons nicht mehr benötigt.

4. __ROT13 JavaScript Verschlüsselung__ ⚠️ __Veraltet, unsicher__: Diese Methode ersetzt E-Mailadressen durch JavaScript-Code mit ROT13-Verschlüsselung. ROT13 bietet keinen ausreichenden Schutz mehr gegen moderne Spam-Bots.
__Bitte beachten__: Diese Methode macht alle E-Mailadresse ohne klickbaren Link klickbar!

3. __CSS Methode ohne JavaScript__: Um die Email-Adressen zu schützen, wird die Technik "CSS display:none" angewendet.
5. __CSS Methode ohne JavaScript__: Diese Methode verwendet "CSS display:none" zur Verschleierung und funktioniert ohne JavaScript.
__Bitte beachten__: diese Methode entfernt den mailto-Link und verwandelt Adresse in name[at]domain.tld. Die Adresse ist damit nicht mehr klickbar.

4. __ROT13 JavaScript Verschlüsselung mit CSS Methode__: Um die Email-Adressen zu schützen, werden die Techniken "CSS display:none" und "ROT13 Encryption" angewendet. Die CSS Methode kommt im `<noscript>` Tag zum Einsatz, falls JavaScript im Browser des Besuchers deaktiviert ist.
6. __ROT13 JavaScript Verschlüsselung mit CSS Methode__ ⚠️ __Veraltet, unsicher__: Kombiniert ROT13-Verschlüsselung mit CSS-Fallback für deaktiviertes JavaScript.
__Bitte beachten__: Diese Methode macht alle E-Mailadresse ohne klickbaren Link klickbar!
__Bitte beachten__: diese Methode entfernt bei deaktiviertem JavaScript den mailto-Link und verwandelt Adresse in name[at]domain.tld. Die Adresse ist damit nicht mehr klickbar.

### Unterstützung für mailto-Parameter

Alle Verschlüsselungsmethoden unterstützen jetzt vollständig mailto-Links mit Parametern:
- __Einfache Parameter__: `[email protected]?subject=Anfrage`
- __Mehrere Parameter__: `[email protected]?subject=Hilfe&body=Bitte_kontaktieren_Sie_mich`
- __URL-kodierte Parameter__: `[email protected]?subject=Anfrage%20f%C3%BCr%20ein%20U-Boot`

Die Parameter bleiben nach der Entschlüsselung vollständig erhalten und funktionsfähig.

## Installation

Das Addon ist nach Aktivierung gleich funktionsfähig, und du brauchst keine weiteren Einstellungen vorzunehmen. Die benötigten Styles und Scripte werden automatisch geladen.
Das Addon ist nach Aktivierung gleich funktionsfähig und verwendet standardmäßig die sichere __XOR Verschlüsselung__. Du brauchst keine weiteren Einstellungen vorzunehmen. Die benötigten Styles und Scripte werden automatisch geladen.

⚠️ __Wichtiger Sicherheitshinweis__: Falls du eine ältere Installation aktualisierst, die noch die veralteten ROT13-Methoden verwendet, solltest du in der Konfiguration auf eine der neuen XOR-Methoden wechseln, um die Sicherheit deiner E-Mailadressen zu gewährleisten.

Solltest du das benötigte CSS oder JavaScript manuell einbinden wollen, musst du in der Konfiguration das automatische Laden deaktivieren.

### Keine jQuery-Abhängigkeit mehr

Ab Version 2.0 des Addons wird __kein jQuery mehr benötigt__. Das JavaScript verwendet moderne Vanilla-DOM-APIs und ist mit allen aktuellen Browsern kompatibel. Bestehende Installationen funktionieren weiterhin ohne Änderungen.

### Hinweise zur __ROT13 Einhorn-Markup__ Methode: CSS und JavaScript manuell einbinden

Du kannst die Styles und Scripte auf zwei Arten einbinden: Entweder du lädst die Files, die das Addon bereitstellt, oder du kopierst deren Inhalte in deine bestehenden CSS- und JavaScript-Files.

#### a) Dateien laden
### Automatische JavaScript-Einbindung

Das Addon lädt __automatisch__ das benötigte JavaScript für alle Verschlüsselungsmethoden, die eine clientseitige Entschlüsselung benötigen:

- XOR Verschlüsselung (einfach und dynamisch)
- ROT13 Einhorn-Markup
- ROT13 JavaScript Verschlüsselung
- ROT13 JavaScript mit CSS Fallback

Das JavaScript wird automatisch vor dem schließenden `</body>` Tag eingefügt. Du musst __nichts manuell einbinden__.

### Hinweise zur manuellen Einbindung (optional)

Falls du das automatische Laden deaktivieren möchtest, kannst du die Styles und Scripte manuell einbinden. Du kannst die Files, die das Addon bereitstellt, laden oder deren Inhalte in deine bestehenden CSS- und JavaScript-Files kopieren.

#### a) Dateien manuell laden (falls automatisches Laden deaktiviert)

__CSS__ im `<head>` deiner Website einfügen:

Expand All @@ -59,9 +94,9 @@ __JavaScript__ am besten am Ende deiner Website vorm schließenden `</body>` ein
?>
```

#### b) Inhalte kopieren
#### b) Inhalte in eigene Dateien kopieren (falls automatisches Laden deaktiviert)

Kopiere die Inhalte der CSS-Datei und der JS-Datei jeweils in deine Sourcen:
Falls du das automatische Laden deaktiviert hast, kannst du die Inhalte der CSS- und JS-Datei in deine eigenen Sourcen kopieren:

assets/emailobfuscator.css
assets/emailobfuscator.js
Expand All @@ -70,6 +105,27 @@ Kopiere die Inhalte der CSS-Datei und der JS-Datei jeweils in deine Sourcen:
Bei Variante a) oben ist dies nicht notwendig.


## Sicherheit und Migration

### Warum XOR statt ROT13?

Die neuen XOR-Verschlüsselungsmethoden bieten exponentiell bessere Sicherheit als die veralteten ROT13-Verfahren:

- __ROT13__ ist ein einfacher Caesar-Cipher, der von modernen Tools und Spam-Bots leicht automatisch geknackt werden kann
- __XOR-Verschlüsselung__ mit Base64-URL-Safe-Kodierung ist deutlich komplexer und widerstandsfähiger gegen automatisierte Angriffe
- __Dynamische Schlüssel__ (XOR dynamic) machen die Entschlüsselung ohne Kontext praktisch unmöglich

### Migration von alten Methoden

Wenn du eine bestehende Installation verwendest:

1. Gehe zur Email-Verschlüsselung Konfigurationsseite im REDAXO Backend
2. Wähle __"XOR Verschlüsselung (Sicher, empfohlen)"__ für Standardsicherheit
3. Oder wähle __"XOR Verschlüsselung mit dynamischem Schlüssel (Sehr sicher, empfohlen)"__ für maximale Sicherheit
4. Speichere die Konfiguration

Keine Code-Änderungen, Template-Updates oder jQuery-Installation erforderlich. Alle bestehenden mailto-Links mit Parametern funktionieren sofort korrekt.

## Sonstiges

### Verschlüsselung bestimmter E-Mailadressen verhindern
Expand All @@ -86,4 +142,21 @@ Bei Variante a) oben ist dies nicht notwendig.

Das Addon filtert _alle_ E-Mailadressen im Code anhand eines Musters und verschlüsselt diese. In manchen Situationen ist das nicht unbedingt gewollt, z. B. wenn E-Mailadressen als HTML-Attribute oder in Formularen verwendet werden. Dort werden vom System natürlich die reinen, unverschlüsselten Adressen erwartet, und leider kann das Addon solche Umgebungen nicht eigenständig erkennen.

⚠️ Beachte bitte, dass du in manchen Umgebungen die E-Mailverschlüsselung unterbinden solltest, entweder durch Ausschließen bestimmter Templates oder Artikel in der Konfiguration, oder aber durch ein manuelles Whitelisting von Adressen wie im Abschnitt oben beschrieben.
⚠️ Beachte bitte, dass du in manchen Umgebungen die E-Mailverschlüsselung unterbinden solltest, entweder durch Ausschließen bestimmter Templates oder Artikel in der Konfiguration, oder aber durch ein manuelles Whitelisting von Adressen wie im Abschnitt oben beschrieben.

### Unterstützung für komplexe mailto-Parameter

Das Addon unterstützt jetzt vollständig komplexe mailto-Links mit allen gängigen Parametern:

```html
<!-- Einfache Betreff-Zeile -->
<a href="mailto:[email protected]?subject=Anfrage">Kontakt</a>

<!-- Betreff und Nachricht -->
<a href="mailto:[email protected]?subject=Hilfe%20benötigt&body=Bitte%20kontaktieren%20Sie%20mich">Support</a>

<!-- Mehrere Empfänger und Parameter -->
<a href="mailto:[email protected],[email protected]?subject=Angebot&[email protected]&body=Liebe%20Damen%20und%20Herren">Angebot anfordern</a>
```

Alle Parameter bleiben nach der Verschlüsselung und Entschlüsselung vollständig funktionsfähig.
121 changes: 105 additions & 16 deletions assets/emailobfuscator.js
Original file line number Diff line number Diff line change
@@ -1,34 +1,123 @@
window.onload = function () {
if (typeof jQuery !== 'undefined') {
$(function () {
decryptEmailaddresses();
});
} else {
console.warn('Email obfuscator addon requires jQuery.');
}
};
// Initialize when DOM is ready
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', function() {
decryptEmailaddresses();
deobfuscateXorEmails();
});
} else {
decryptEmailaddresses();
deobfuscateXorEmails();
}

function decryptEmailaddresses() {
// Ersetze E-Mailadressen
$('span.unicorn').each(function () {
$(this).replaceWith('@');
var unicornSpans = document.querySelectorAll('span.unicorn');
Array.prototype.forEach.call(unicornSpans, function(span) {
span.outerHTML = '@';
});

// Ersetze mailto-Links
$('a[href^="javascript:decryptUnicorn"]').each(function () {

var emailLinks = document.querySelectorAll('a[href^="javascript:decryptUnicorn"]');
Array.prototype.forEach.call(emailLinks, function(link) {
// Selektiere Einhorn-Werte
var emails = $(this).attr('href').match(/\((.*)\)/)[1];
var emails = link.href.match(/\((.*)\)/)[1];

emails = emails
// ROT13-Transformation
.replace(/[a-z]/gi, function (s) {
return String.fromCharCode(s.charCodeAt(0) + (s.toLowerCase() < 'n' ? 13 : -13));
})
// Ersetze # durch @
// Ersetze | durch @
.replace(/\|/g, '@');

// Ersetze Einhörner
$(this).attr('href', 'mailto:' + emails);
link.href = 'mailto:' + emails;
});
}

// XOR decryption functions
function base64UrlDecode(str) {
str = (str + "===").slice(0, str.length + (str.length % 4));
return atob(str.replace(/-/g, "+").replace(/_/g, "/"));
}

function xorDecrypt(encrypted, key) {
var result = "";
for (var i = 0; i < encrypted.length; i++) {
result += String.fromCharCode(encrypted.charCodeAt(i) ^ key.charCodeAt(i % key.length));
}
return result;
}

function decryptEmailData(encryptedData, method, context) {
var key;
if (method === "xor-simple") {
key = "EmailObfuscatorKey2024";
} else {
// Generate dynamic key using a simple hash
var baseKey = "EmailObfuscator";
var fullString = baseKey + (context || "");
var hash = 0;
for (var i = 0; i < fullString.length; i++) {
var char = fullString.charCodeAt(i);
hash = ((hash << 5) - hash) + char;
hash = hash >>> 0; // Convert to unsigned 32-bit integer
Copy link
Preview

Copilot AI Aug 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The hash calculation in JavaScript uses hash >>> 0 but the corresponding PHP code uses ($hash << 32) >> 32. These operations are not equivalent and will produce different hash values, causing decryption to fail. The PHP code should use $hash & 0xFFFFFFFF to match the JavaScript behavior.

Copilot uses AI. Check for mistakes.

}
// Convert hash to hex and take first 16 characters
var hashHex = (hash >>> 0).toString(16);
key = (hashHex + hashHex + hashHex + hashHex).substring(0, 16);
}

var decoded = base64UrlDecode(encryptedData);
return xorDecrypt(decoded, key);
}

function deobfuscateXorEmails() {
var obfuscatedElements = document.querySelectorAll(".email-obfuscated");

Array.prototype.forEach.call(obfuscatedElements, function(element) {
var method = element.getAttribute("data-method");
var context = element.getAttribute("data-context") || "";
var encryptedEmail = element.getAttribute("data-email");
var encryptedText = element.getAttribute("data-text");
var encryptedAttributes = element.getAttribute("data-attributes");

try {
var email = decryptEmailData(encryptedEmail, method, context);
var text = decryptEmailData(encryptedText, method, context);
var attributes = encryptedAttributes ? decryptEmailData(encryptedAttributes, method, context) : "";

var link = document.createElement("a");
link.href = "mailto:" + email;
link.textContent = text;

if (attributes) {
// Simple attribute parsing
var attrParts = attributes.split(" ");
Array.prototype.forEach.call(attrParts, function(attr) {
var eqIndex = attr.indexOf("=");
if (eqIndex > 0) {
var attrName = attr.substring(0, eqIndex);
var attrValue = attr.substring(eqIndex + 1).replace(/["\']/g, "");
if (attrName && attrValue && attrName !== "href") {
link.setAttribute(attrName, attrValue);
}
}
// Robust attribute parsing using regex
var attrRegex = /([^\s=]+)\s*=\s*(['"])(.*?)\2|([^\s=]+)\s*=\s*([^\s"']+)/g;
var match;
while ((match = attrRegex.exec(attributes)) !== null) {
var attrName = match[1] || match[4];
var attrValue = match[3] || match[5];
if (attrName && attrValue && attrName !== "href") {
link.setAttribute(attrName, attrValue);
}
}
}

element.parentNode.replaceChild(link, element);
} catch (e) {
console.warn("Failed to deobfuscate email:", e);
}
});
}
8 changes: 5 additions & 3 deletions lang/de_de.lang
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ emailobfuscator_config = Konfiguration
emailobfuscator_config_saved = Konfiguration gespeichert.
emailobfuscator_config_methods = Methoden
emailobfuscator_config_select_method = Verschlüsselungsmethode
emailobfuscator_config_select_method_xor_simple = XOR Verschlüsselung (Sicher, empfohlen)
emailobfuscator_config_select_method_xor_dynamic = XOR Verschlüsselung mit dynamischem Schlüssel (Sehr sicher, empfohlen)
emailobfuscator_config_select_method_css = CSS Methode ohne JavaScript (entfernt Link und verwandelt Adresse in name[at]domain.tld)
emailobfuscator_config_select_method_rot13 = ROT13 JavaScript Verschlüsselung
emailobfuscator_config_select_method_rot13_css = ROT13 JavaScript Verschlüsselung mit CSS Methode falls JavaScript deaktiviert ist
emailobfuscator_config_select_method_unicorn = ROT13 Einhorn-Markup (Standard, benötigt JQuery)
emailobfuscator_config_select_method_rot13 = ROT13 JavaScript Verschlüsselung (Veraltet, unsicher)
emailobfuscator_config_select_method_rot13_css = ROT13 JavaScript Verschlüsselung mit CSS Methode falls JavaScript deaktiviert ist (Veraltet, unsicher)
emailobfuscator_config_select_method_unicorn = ROT13 Einhorn-Markup (Veraltet, unsicher, benötigt JQuery)
emailobfuscator-config-method
emailobfuscator_config_assets = Assets
emailobfuscator_config_load_assets = Scripte und Styles laden
Expand Down
8 changes: 5 additions & 3 deletions lang/en_gb.lang
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ emailobfuscator_config = Configuration
emailobfuscator_config_saved = Configuration has been saved.
emailobfuscator_config_methods = Methods
emailobfuscator_config_select_method = Protection method
emailobfuscator_config_select_method_xor_simple = XOR encryption (Secure, recommended)
emailobfuscator_config_select_method_xor_dynamic = XOR encryption with dynamic key (Very secure, recommended)
emailobfuscator_config_select_method_css = CSS method without JavaScript (removes link and transforms address into name[at]domain.tld)
emailobfuscator_config_select_method_rot13 = ROT13 JavaScript encryption
emailobfuscator_config_select_method_rot13_css = ROT13 JavaScript encryption with CSS method as fallback, in case JavaScript is deactivated
emailobfuscator_config_select_method_unicorn = ROT Unicorn-Markup (standard, needs JQuery)
emailobfuscator_config_select_method_rot13 = ROT13 JavaScript encryption (Deprecated, insecure)
emailobfuscator_config_select_method_rot13_css = ROT13 JavaScript encryption with CSS method as fallback, in case JavaScript is deactivated (Deprecated, insecure)
emailobfuscator_config_select_method_unicorn = ROT Unicorn-Markup (Deprecated, insecure, needs JQuery)
emailobfuscator_config_assets = Assets
emailobfuscator_config_load_assets = Load scripts and styles
emailobfuscator_config_assets_js = Autoload JavaScript
Expand Down
Loading