crypt,
crypt_r,
crypt_rn,
crypt_ra
—
Hashen von Passphrasen
Crypt Library (libcrypt, -lcrypt)
<crypt.h>
char *
crypt(
const char
*phrase,
const char *setting);
char *
crypt_r(
const char
*phrase,
const char *setting,
struct crypt_data *data);
char *
crypt_rn(
const char
*phrase,
const char *setting,
struct crypt_data *data,
int size);
char
* crypt_ra(
const
char *phrase,
const char *setting,
void **data,
int
*size);
Die Funktionen
crypt,
crypt_r,
crypt_rn
und
crypt_ra führen einen nicht
umkehrbaren »Hash« der
phrase
mit einer »Hash-Methode« zur Speicherung in der
Systempasswortdatenbank (
shadow(5)) durch. Das
Ergebnis dieser Aktion wird »gehashte Passphrase« oder einfach
nur »Hash« genannt. Die Hash-Methoden sind in
crypt(5) beschrieben.
setting steuert, welche Hash-Methode verwandt
werden soll und stellt auch verschiedene Parameter für die
ausgewählte Methode bereit, am wichtigsten ein zufälliges
»salt«, das sicherstellt, dass keine zwei Hashes identisch sind,
selbst falls die Zeichenketten
phrase
identisch sind.
Das Argument
data von
crypt_r ist eine Struktur des Typs
struct crypt_data. Sie hat mindestens die
folgenden Felder:
struct crypt_data {
char output[CRYPT_OUTPUT_SIZE];
char setting[CRYPT_OUTPUT_SIZE];
char input[CRYPT_MAX_PASSPHRASE_SIZE];
char initialized;
};
Wird von
crypt_r erfolgreich zurückgekehrt,
dann wird die gehashte Passphrase in
output
gespeichert. Anwendungsprogrammierer werden ermutigt (es ist aber nicht
verpflichtend), die Felder
input und
setting zu verwenden, um die Zeichenketten zu
speichern, die sie als
input phrase und
setting an
crypt_r übergeben. Dies erleichtert es,
sämtliche sensitiven Daten zu löschen, wenn diese nicht mehr
benötigt werden.
Das Feld
initialized muss auf Null gesetzt
werden, bevor erstmalig ein Objekt
struct
crypt_data in einem Aufruf an
crypt_r()
verwandt wird. Wir empfehlen vor dem ersten Einsatz, das gesamte Objekt mit
Nullen zu überschreiben, nicht nur
initialized und die dokumentierten Felder.
(Natürlich sollte dies erfolgen, bevor Sie etwas in
setting und
input speichern.)
Das Argument
data von
crypt_rn sollte auch auf ein Objekt
struct crypt_data zeigen und
size sollte die Größe dieses
Objektes sein, nach einem Cast auf
int. Wird
dies zusammen mit
crypt_rn verwandt, dann muss
das gesamte Objekt
data (außer den
Feldern
input und
setting) vor dem ersten Einsatz mit Nullen
überschrieben werden; dies ist nicht nur eine Empfehlung, wie bei
crypt_r. Abgesehen davon haben die Felder die
gleichen Zwecke wie bei
crypt_r.
Beim ersten Aufruf von
crypt_ra sollte
data die Adresse einer Variablen
void *, die auf NULL gesetzt ist, sein, und
size sollte die Adresse einer Variablen
int sein, die auf Null gesetzt ist.
crypt_ra wird mittels
malloc(3) ein Objekt
struct crypt_data reservieren und
initialisieren und seine Adresse und Größe in die Variablen
schreiben, auf die
data und
size zeigen. Dies kann in nachfolgenden
Aufrufen wiederverwertet werden. Nachdem die Anwendung mit dem Hashen von
Passwörtern fertig ist, sollte sie das Objekt
struct crypt_data mittels
free(3) freigeben.
Nach erfolgreichem Abschluss liefern
crypt,
crypt_r,
crypt_rn
und
crypt_ra einen Zeiger auf eine Zeichenkette
zurück, die sowohl die gehashte Passphrase als auch die Einstellungen,
die zur Kodierung verwandt wurden, enthält. Diese Zeichenkette kann
direkt als
setting in anderen Aufrufen von
crypt,
crypt_r,
crypt_rn und
crypt_ra und als
prefix in Aufrufen von
crypt_gensalt,
crypt_gensalt_rn und
crypt_gensalt_ra verwandt werden. Sie wird
komplett in ASCII darstellbar sein und wird keine Leerraumzeichen oder die
Zeichen »:«, »;«, »*«,
»!« oder »\« enthalten. Siehe
crypt(5) für weitere Details über
das Format der gehashten Passphrasen.
crypt legt sein Ergebnis in einem statischen
Speicherbereich ab, der bei nachfolgenden Aufrufen von
crypt überschrieben wird. Es ist nicht
sicher,
crypt aus verschiedenen Threads simultan
aufzurufen.
crypt_r,
crypt_rn und
crypt_ra legen ihr Ergebnis in dem Feld
output ihres Arguments
data ab. Es ist sicher, sie aus mehreren
Threads simultan aufzurufen, solange separate
data -Objekte für jeden Thread
verwandt werden.
Im Fehlerfall schreiben
crypt_r,
crypt_rn und
crypt_ra eine
ungültige gehashte Passphrase in das Feld
output ihres Arguments
data und
crypt
schreibt einen ungültigen Hash in seinen statischen Speicherbereich.
Diese Zeichenkette wird kürzer als 13 Zeichen sein und mit einem
»*« beginnen und bei Vergleichen nicht mit
setting übereinstimmen.
Im Fehlerfall liefern
crypt_rn und
crypt_ra einen Nullzeiger zurück.
crypt_r und
crypt
können auch einen Nullzeiger zurückliefern oder sie
können einen Zeiger auf einen ungültigen Hash
zurückliefern, abhängig davon, wie Libcrypt konfiguriert wurde.
(Die Option, einen Zeiger auf einen ungültigen Hash
zurückzuliefern, dient der Kompatibilität zu alten Anwendungen,
die annehmen, dass
crypt keinen Nullzeiger
zurückliefern kann. Siehe
HINWEISE ZUR
PORTABILITÄT weiter unten.)
Alle vier Funktionen setzen
errno beim
Fehlschlag.
EINVAL
-
setting ist
ungültig oder es wurde eine nicht unterstützte Hash-Methode
erbeten.
ERANGE
-
phrase ist zu lang (mehr
als
CRYPT_MAX_PASSPHRASE_SIZE
Zeichen;
einige Hash-Methoden könnten niedrigere Begrenzungen haben).
Nur crypt_rn:
size ist zu klein für die durch
setting erbetene Hash-Methode.
ENOMEM
- Interner Zwischenspeicher konnte nicht reserviert werden.
Nur crypt_ra: Speicher für
data konnte nicht reserviert werden.
-
ENOSYS
oder
EOPNOTSUPP
- Das Hashen der Passphrase wird auf dieser Plattform
überhaupt nicht unterstützt oder die in
setting erbetene Hash-Methode wird nicht
unterstützt. Diese Fehlercodes werden von dieser Libcrypt-Version
nicht verwandt, könnten aber auf anderen Plattformen beobachtet
werden.
crypt ist Teil von POSIX, aber
crypt_r,
crypt_rn
und
crypt_ra kommen in keinem der Standards vor.
POSIX legt keine Hash-Methode fest und verlangt nicht, dass gehashte Passphrasen
zwischen Systemen portierbar sind. In der Praxis sind gehashte Passphrasen
portierbar, solange beide Systeme die verwandte Hash-Methode
unterstützen. Allerdings unterscheidet sich die Gruppe der
unterstützten Hash-Methoden zwischen Systemen deutlich.
Das Verhalten von
crypt bei Fehlern ist nicht gut
standardisiert. Einige Implementierungen können schlicht nicht
fehlschlagen (außer durch Absturz des Programms), andere liefern einen
Nullzeiger oder eine bestimmte Zeichenkette zurück. Die meisten
Implementierungen setzen
errno nicht, andere
wiederum tun dies. POSIX legt fest, dass ein Nullzeiger zurückgeliefert
und
errno gesetzt werden soll, es definiert
aber nur einen möglichen Fehler,
ENOSYS
, falls
crypt überhaupt nicht unterstützt
wird. Einige ältere Anwendungen sind nicht in der Lage, mit durch
crypt zurückgelieferten Nullzeigern
umzugehen. Das oben für diese Implementierung beschriebene Verhalten,
d.h. das Setzen von
errno und dem
Zurückliefern einer ungültigen gehashten Passphrase, die sich
von
setting unterscheidet, wurde
gewählt, um diese Anwendungen zu einem Fehlschlag zu bewegen, wenn ein
Fehler auftritt.
Aufgrund historischer Einschränkungen zum Export von kryptographischer
Software aus den USA ist
crypt eine optionale
POSIX-Komponente. Anwendungen sollten daher darauf vorbereitet sein, dass
crypt nicht verfügbar ist oder zur
Laufzeit einen Fehler zurückliefern (
errno auf
ENOSYS
setzen).
POSIX spezifiziert, dass
crypt in
<unistd.h>
deklariert ist, aber nur falls das Makro
_XOPEN_CRYPT
definiert ist und einen Wert
größer oder gleich Null hat. Da Libcrypt nicht
<unistd.h>
bereitstellt, deklariert es stattdessen
crypt,
crypt_r,
crypt_rn
und
crypt_ra in
<crypt.h> .
Auf einer Minderzahl an Systemen (insbesondere neueren Versionen von Solaris)
verwendet
crypt einen Thread-sicheren statischen
Speicherpuffer, wodurch es sicher ist, es von mehreren Threads aus simultan
aufzurufen, aber nicht verhindert, dass jeder Aufruf innerhalb eines Threads
die Ergebnisse des vorherigen Aufrufs überschreibt.
Im Fehlerfall liefern einige Implementierungen von
crypt einen ungültigen Hash zurück,
der an einem nur-lesbaren Ort gespeichert oder nur einmal initialisiert wird,
was bedeutet, dass es nur sicher ist, dass der Puffer gelöscht wird,
auf den vom Rückgabewert von
crypt gezeigt
wird, wenn kein Fehler auftrat.
struct crypt_data könnte recht
groß sein (32 kB in dieser Implementierung von Libcrypt; mehr als 128
kB in einigen anderen Implementierungen). Dies ist groß genug, so dass
es nicht ratsam sein könnte, dieses auf dem Stack zu reservieren.
Einige neu entwickelte Hash-Methoden benötigen noch mehr
Zwischenspeicher, aber die Schnittstelle
crypt_r
ermöglicht es, die Größe von
struct crypt_data zu ändern, ohne die
Binärkompatibilität zu brechen. Die Schnittstelle
crypt_rn könnte größere
Reservierungen für bestimmte Hash-Methoden berücksichtigen, aber
der Aufrufende von
crypt_rn hat keine
Möglichkeit zu erkennen, wieviel Speicher reserviert werden muss.
crypt_ra erledigt die Reservierung selbst, aber
kann
malloc(3) nur ein einziges Mal aufrufen.
Siehe
attributes (7) für eine
Erläuterung der in diesem Abschnitt verwandten Ausdrücke.
Schnittstelle |
Attribut |
Wert |
crypt |
Multithread-Fähigkeit |
MT-Unsafe race:crypt |
crypt_r , crypt_rn , crypt_ra |
Multithread-Fähigkeit |
MT-Safe |
Eine Rotor-basierende Funktion
crypt erschien in
Version 6 AT&T UNIX. Das
»traditionelle«, DES-basierende
crypt erschien erstmalig in
Version 7 AT&T UNIX.
crypt_r entstammt der GNU-C-Bibliothek. Es gibt
auch eine Funktion
crypt_r unter HP-UX und MKS
Toolkit, allerdings unterscheiden sich deren Prototyp und Semantik.
crypt_rn und
crypt_ra
entstammen dem Openwall-Projekt.
crypt_gensalt(3),
getpass(3),
getpwent(3),
shadow(3),
login(1),
passwd(1),
crypt(5),
passwd(5),
shadow(5),
pam(8)
Die deutsche Übersetzung dieser Handbuchseite wurde von Martin Eberhard
Schauer <
[email protected]> und Helge Kreutzmann
<
[email protected]> erstellt.
Diese Übersetzung ist Freie Dokumentation; lesen Sie die
GNU
General Public License Version 3 oder neuer bezüglich der
Copyright-Bedingungen. Es wird KEINE HAFTUNG übernommen.
Wenn Sie Fehler in der Übersetzung dieser Handbuchseite finden, schicken
Sie bitte eine E-Mail an die Mailingliste der Übersetzer:
[email protected]