Navigation
 Startseite
 Fachbücher
 Anzeigenmarkt
 Forum
 Webmaster News
 Script Newsletter
 Push Meldungen
 Kontakt
 Script Installation
 Php
 Php Tutorials
 Lernpfade
 Webhoster Vergleich
 Impressum

Community-Bereich
 kostenlos Registrieren
 Anmelden
 Benutzerliste

Script Datenbank
 Script Archiv
 Script Top 20
 Screenshots
 Testberichte

Suche
 

Unsere Php Scripts
 Counter Script
 Umfrage Script
 Bilder Upload Script
 Terminverwaltung
 Simple PHP Forum
 RSS Grabber

Tools und Generatoren
 .htpasswd Generator
 md5 Generator
 base64 Generator
 Markdown to HTML
 Colorpicker
 Unix timestamp Tool
 Unit Test Generator
 TLD Liste
 Webkatalog‑Verzeichnis

Hosterplus.de
Bekommen Sie Speicherplatz (Webspace), Domains und...
https://www.Hosterplus.de
Artfiles.de
Bietet Serviceorientierte Internetdienstleistungen...
https://www.Artfiles.de
 
 
 

PHP ctype_xdigit(): Hexadezimalwerte sicher prüfen

Sie befinden sich: Home > Php Tutorial > PHP ctype_xdigit(): Hexadez...

PHP ctype_xdigit(): Hexadezimalwerte sicher prüfen
Veröffentlicht am:
11.09.2026
Hits / Besucher:
7
Sprache:
  Deutsch
Tutorial Art:
eigenes
Eingetragen von:
Merkliste:
 
Beschreibung

Ein Baukasten lässt Kunden die Akzentfarbe ihrer Seite selbst wählen. Der Wert aus dem Formular landet ungeprüft im Stylesheet, und irgendwann steht dort statt einer Farbe ein Stück fremder Code. Eine Zeile Prüfung hätte gereicht.

Illustration zum Tutorial: PHP ctype_xdigit(): Hexadezimalwerte sicher prüfen

Im Bild passieren nur die Zeichen von 0 bis 9 und A bis F das Gatter, alles andere fällt heraus. Genau das leistet die Funktion.

Was PHP ctype_xdigit() prüft

PHP ctype_xdigit() beantwortet eine einzige Frage: Besteht diese Zeichenkette ausschließlich aus hexadezimalen Ziffern? Gültig sind 0 bis 9 sowie a bis f in beiden Schreibweisen. Alles andere führt zu false, auch ein führendes 0x, ein Doppelkreuz oder ein Leerzeichen.

<?php

var_dump(ctype_xdigit('1A2b3C')); // bool(true)
var_dump(ctype_xdigit('FFFFFF')); // bool(true)
var_dump(ctype_xdigit('GGG')); // bool(false)
var_dump(ctype_xdigit('#ff0000')); // bool(false), das Doppelkreuz stoert
var_dump(ctype_xdigit('0x1A')); // bool(false), das Praefix stoert
var_dump(ctype_xdigit('')); // bool(false), leerer String

Die Funktion prüft ausschließlich den Zeichenvorrat, nicht das Format. Sie sagt nichts darüber, ob der Wert die richtige Länge hat. Diese Trennung ist wichtig, denn in allen folgenden Beispielen kommt eine Längenprüfung dazu.

Die Signatur im Original

Die Beschreibung im Original ist knapp und beantwortet trotzdem die beiden Fragen, die in der Praxis auftauchen:

ctype_xdigit(mixed $text): bool


/* text - the parameter to check, every character is tested
return - returns true if every character is a hexadecimal digit,
otherwise false

Hexadecimal digits are 0-9, a-f and A-F. A plain decimal value like
42 passes as well, because decimal digits are a subset. An empty
string returns false. Example: "1A2b" returns true, while "0x1A"
returns false, since x is not a hexadecimal character. */

Das Beispiel mit dem Präfix ist der Fall, der am häufigsten überrascht: Die in PHP übliche Schreibweise mit 0x besteht die Prüfung nicht.

Hex-Farben aus einem Formular prüfen

Ein Farbwert kommt in zwei Schreibweisen vor, dreistellig als Kurzform und sechsstellig als Langform, jeweils mit oder ohne führendes Doppelkreuz. Die Prüfung besteht deshalb aus drei Schritten: Rand entfernen, Länge prüfen, Zeichenvorrat prüfen.

<?php

function istFarbwert(string $eingabe): bool
{
$wert = ltrim(trim($eingabe), '#');

if (!in_array(strlen($wert), [3, 6], true)) {
return false;
}

return ctype_xdigit($wert);
}

var_dump(istFarbwert('#2b2b2b')); // bool(true)
var_dump(istFarbwert('fff')); // bool(true)
var_dump(istFarbwert('#ff00')); // bool(false), Laenge passt nicht
var_dump(istFarbwert('#GG0000')); // bool(false), keine Hex-Ziffern

Wer PHP ctype_xdigit() ohne die Längenprüfung einsetzt, lässt abc123def durch. Das sind einwandfreie Hex-Ziffern, als Farbwert aber unbrauchbar. Die beiden Prüfungen gehören zusammen.

Token aus der URL abweisen, bevor die Datenbank arbeitet

Bestätigungslinks tragen einen langen Hex-Token in der Adresse. Jeder Klick auf einen manipulierten Link löst eine Datenbankabfrage aus, obwohl der Wert offensichtlich unsinnig ist. Eine Vorprüfung aus Länge und Zeichenvorrat kostet praktisch nichts und hält den Großteil davon ab.

<?php

$token = (string) ($_GET['token'] ?? '');

if (strlen($token) !== 64 || !ctype_xdigit($token)) {
http_response_code(400);
exit('Ungueltiger Bestaetigungslink');
}

/* erst jetzt in die Datenbank */
$stmt = $dbh->prepare('SELECT id FROM anmeldung WHERE token = ?');
$stmt->execute([$token]);

Diese Prüfung ersetzt keine vorbereitete Abfrage, wie sie das Tutorial zu PHP mysqli Prepared Statements beschreibt. Sie spart Last und hält Unsinn früh auf, mehr nicht. Die Absicherung der Abfrage selbst bleibt Aufgabe der Platzhalter.

MAC-Adressen und Prüfsummen

Bei MAC-Adressen stören die Trennzeichen, mal Doppelpunkte, mal Bindestriche. Sie werden vor der Prüfung entfernt, danach zählt nur noch die Länge von zwölf Zeichen.

<?php

function istMacAdresse(string $eingabe): bool
{
$roh = str_replace([':', '-', '.'], '', trim($eingabe));

return strlen($roh) === 12 && ctype_xdigit($roh);
}

var_dump(istMacAdresse('00:1B:44:11:3A:B7')); // bool(true)
var_dump(istMacAdresse('00-1B-44-11-3A-B7')); // bool(true)
var_dump(istMacAdresse('00:1B:44:11:3A')); // bool(false)

Beim Import von Prüfsummen aus CSV-Dateien ist ein anderer Randfall wichtig. Leere Felder und Werte mit Leerzeichen am Rand kommen häufig vor, und PHP ctype_xdigit() liefert bei beiden false. Das ist richtig, muss aber sauber getrennt behandelt werden, sonst wirken gültige Zeilen wie Fehler.

<?php

foreach ($zeilen as $nr => $feld) {
$wert = trim($feld);

if ($wert === '') {
continue; /* leeres Feld ist kein Fehler */
}
if (!ctype_xdigit($wert)) {
echo "Zeile $nr: keine gueltige Pruefsumme\n";
}
}

Die Wache vor hex2bin()

Wer Hex-Strings in Binärdaten umwandelt, kennt das Problem: hex2bin() erzeugt bei ungerader Länge und bei ungültigen Zeichen eine Warnung und gibt false zurück. Im laufenden Betrieb fällt das oft erst weit später auf, wenn irgendwo ein leerer Wert ankommt.

<?php

function sicherHex2Bin(string $hex): ?string
{
if ($hex === '' || strlen($hex) % 2 !== 0) {
return null;
}
if (!ctype_xdigit($hex)) {
return null;
}

return hex2bin($hex);
}

var_dump(sicherHex2Bin('48616c6c6f')); // string(5) "Hallo"
var_dump(sicherHex2Bin('48616c6c6')); // NULL, ungerade Laenge
var_dump(sicherHex2Bin('48616c6cZZ')); // NULL, ungueltiges Zeichen

Die Kombination aus Längenprüfung und PHP ctype_xdigit() fängt beide Fehlerquellen ab, bevor die Umwandlung überhaupt startet.

Der Fallstrick mit Zahlen statt Strings

Dieser Punkt kostet regelmäßig Zeit. Übergibt man eine Ganzzahl statt einer Zeichenkette, prüft PHP historisch nicht deren Ziffern, sondern behandelt den Wert im Bereich von -128 bis 255 als ASCII-Code. ctype_xdigit(65) prüft also das Zeichen A und liefert true, obwohl die Ziffernfolge "65" gemeint war.

<?php

var_dump(ctype_xdigit(65)); // bool(true), geprueft wird das Zeichen "A"
var_dump(ctype_xdigit('65')); // bool(true), geprueft wird die Ziffernfolge
var_dump(ctype_xdigit(300)); // bool(false), ausserhalb des ASCII-Bereichs

/* richtig ist immer der String */
$wert = 65;
var_dump(ctype_xdigit((string) $wert)); // bool(true), eindeutig

Seit PHP 8.1 meldet die Funktion bei Nicht-Strings eine Deprecation. Das ist ein Hinweis, kein Fehler, und der Code läuft weiter. Die Meldung sollte trotzdem ernst genommen werden, denn das alte Verhalten wird irgendwann verschwinden. Die Regel lautet: an PHP ctype_xdigit() geht immer ein String, notfalls mit ausdrücklicher Umwandlung.

Die folgende Übersicht zeigt, in welcher Reihenfolge ein Rohwert die Prüfkette durchläuft.

flowchart TD
  A[Rohwert] --> B[trim und Praefix weg]
  B --> C{Laenge passt}
  C -->|nein| D[abweisen]
  C -->|ja| E{ctype_xdigit}
  E -->|nein| D
  E -->|ja| F[Wert verwenden]

Die Länge steht vor dem Zeichenvorrat, weil sie billiger zu prüfen ist und die meisten fehlerhaften Eingaben schon dort ausscheiden.

Die ctype-Familie im Überblick

PHP ctype_xdigit() ist eines von acht Geschwistern, die alle nach demselben Muster arbeiten. Sie stammen aus der C-Bibliothek und prüfen jeweils einen festen Zeichenvorrat.

Funktion Erlaubter Zeichenvorrat Beispiel mit true
ctype_xdigit 0-9, a-f, A-F "1a2B"
ctype_digit 0-9 "0815"
ctype_alpha a-z, A-Z "Hallo"
ctype_alnum a-z, A-Z, 0-9 "Bild42"
ctype_space Leerzeichen, Tabulator, Umbruch " \t"
ctype_upper A-Z "ABC"
ctype_lower a-z "abc"
ctype_punct druckbare Sonderzeichen ohne Leerraum "!?-"

Häufig gestellt wird die Frage nach dem Unterschied zu is_numeric(). Der ist deutlich: is_numeric('1e3') ergibt true, weil es eine gültige Zahl in wissenschaftlicher Schreibweise ist, ctype_digit('1e3') ergibt false. Auch führende Leerzeichen und Vorzeichen akzeptiert is_numeric(), die ctype-Familie nicht. Wer eine reine Ziffernfolge braucht, etwa für eine Kundennummer, ist mit ctype_digit() besser bedient. Vertiefend dazu passt das Tutorial zu PHP is_int() und der Typprüfung mit Integer.

PHP ctype_xdigit() oder preg_match()?

Dieselbe Aufgabe lässt sich mit einem regulären Ausdruck lösen. Beide Wege haben ihre Berechtigung, und die Entscheidung ist einfacher, als sie aussieht.

<?php

$wert = 'a3f9c1';

/* nur Zeichenvorrat, sehr schnell */
$a = ctype_xdigit($wert);

/* Zeichenvorrat und Laenge in einem Aufruf */
$b = preg_match('/^[0-9a-f]{6}$/i', $wert) === 1;

PHP ctype_xdigit() ist schneller, weil kein Muster kompiliert werden muss, und der Aufruf ist ohne Sonderzeichen lesbar. Sobald aber neben dem Zeichenvorrat auch ein Format geprüft werden soll, erledigt der reguläre Ausdruck beides in einer Zeile. In einer Schleife über viele tausend Werte fällt der Geschwindigkeitsunterschied ins Gewicht, bei einer einzelnen Formularprüfung nicht.

Noch ein Hinweis zur Arbeitsweise: die ctype-Funktionen arbeiten byteweise. Bei Hex-Werten spielt das keine Rolle, weil alle gültigen Zeichen im ASCII-Bereich liegen. Bei Eingaben mit Umlauten oder anderen Mehrbyte-Zeichen ist das anders, dort ist die Familie schlicht das falsche Werkzeug.

Fazit

PHP ctype_xdigit() ist eine kleine Funktion mit einem klaren Zweck: Sie sagt, ob eine Zeichenkette ausschließlich aus Hex-Ziffern besteht. In der Praxis steht sie nie allein, sondern immer zusammen mit einer Längenprüfung, weil erst beide zusammen ein Format ergeben.

Zwei Dinge bleiben hängen. Erstens gehört an die Funktion immer ein String, sonst prüft sie einen ASCII-Code statt der Ziffern. Zweitens ist sie kein Sicherheitswerkzeug, sondern eine Vorprüfung, die Unsinn früh aussortiert und der eigentlichen Absicherung Arbeit abnimmt.

 

Tags:

 

 

Kommentare (0)

Noch keine Kommentare. Sei der Erste!

Melde dich an, um einen Kommentar zu schreiben.
Bücherregal mit drei Büchern: 'PHP 4 - Grundlagen und Profiwissen' von Hanser Verlag, 'Webdesign in a Nutshell' von O'Reilly Verlag, und 'Webgestaltung' von Galileo Computing.