Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Äquivalent für mysql.encrypt in postgresql?

14 views
Skip to first unread message

Magnus Warker

unread,
Oct 2, 2017, 12:05:22 PM10/2/17
to
Hallo,

ich möchte eine postfix-Installation von mysql nach postgresql
überführen. In der postfix-Konfiguration ist SHA512 für die Passwörter
eingestellt. Einen neuen Benutzer mit Passwort anlegen funktioniert mit
mysql so:

INSERT INTO user (...,password,...)
VALUES (...,encrypt('MyPassword'), ...);

Scheinbar verschlüsselt die Funktion encrypt ohne weitere Parameter nach
dem SHA512-Algorithmus.

In postgresql gibt es die Funktion encrypt nicht.
Wie macht man das Gleiche da?

Danke
Magnus

Tim Landscheidt

unread,
Oct 2, 2017, 1:22:44 PM10/2/17
to
Du kannst das Modul pgcrypto aus dem Paket
postgresql-contrib (Name je nach Distribution unterschied-
lich) installieren und dessen Funktion digest() benutzen
(vgl. https://www.postgresql.org/docs/current/static/pgcrypto.html):

| postgres=# CREATE EXTENSION pgcrypto;
| CREATE EXTENSION
| postgres=# SELECT digest('Test', 'sha512');
| digest
| ------------------------------------------------------------------------------------------------------------------------------------
| \xc6ee9e33cf5c6715a1d148fd73f7318884b41adcb916021e2bc0e800a5c5dd97f5142178f6ae88c8fdd98e1afb0ce4c8d2c54b5f37b30b7da1997bb33b0b8a31
| (1 Zeile)

| postgres=#

die zumindest das gleiche Ergebnis wie sha512sum(1) produ-
ziert:

| [tim@passepartout ~]$ echo -n Test | sha512sum
| c6ee9e33cf5c6715a1d148fd73f7318884b41adcb916021e2bc0e800a5c5dd97f5142178f6ae88c8fdd98e1afb0ce4c8d2c54b5f37b30b7da1997bb33b0b8a31 -
| [tim@passepartout ~]$

Wenn möglich, würde ich mir dieses zusätzliche Zahnrädchen
aber sparen und den Hash auf Anwendungsseite berechnen (ob
das in Deinem Fall möglich ist, weißt Du besser als
ich :-)).

Tim

Magnus Warker

unread,
Oct 2, 2017, 4:26:34 PM10/2/17
to
Hallo Tim!

On 10/02/2017 07:22 PM, Tim Landscheidt wrote:
> | postgres=# SELECT digest('Test', 'sha512');
> | digest
> | ------------------------------------------------------------------------------------------------------------------------------------
> | \xc6ee9e33cf5c6715a1d148fd73f7318884b41adcb916021e2bc0e800a5c5dd97f5142178f6ae88c8fdd98e1afb0ce4c8d2c54b5f37b30b7da1997bb33b0b8a31

Das scheint zumindest von der Länge des Ergebnisses nicht ganz das
Gleiche zu liefern:

$mysql> select encrypt('Test');
V3I2M26dxF9YE

Wie kann man den Unterschied erklären?

Danke
Magnus

Tim Landscheidt

unread,
Oct 2, 2017, 7:21:58 PM10/2/17
to
Magnus Warker <war...@mailinator.com> wrote:

>> | postgres=# SELECT digest('Test', 'sha512');
>> | digest
>> | ------------------------------------------------------------------------------------------------------------------------------------
>> | \xc6ee9e33cf5c6715a1d148fd73f7318884b41adcb916021e2bc0e800a5c5dd97f5142178f6ae88c8fdd98e1afb0ce4c8d2c54b5f37b30b7da1997bb33b0b8a31

> Das scheint zumindest von der Länge des Ergebnisses nicht
> ganz das Gleiche zu liefern:

> $mysql> select encrypt('Test');
> V3I2M26dxF9YE

> Wie kann man den Unterschied erklären?

Wenn ich
https://dev.mysql.com/doc/refman/5.5/en/encryption-functions.html#function_encrypt
richtig verstehe, berechnet encrypt() nicht wie von Dir an-
gedeutet den SHA512-Hash des Argumentes, sondern ruft intern
crypt(3) mit einem zufälligen Salt auf.

Du könntest dafür pgcryptos crypt()- und gen_salt()-Funktio-
nen benutzen wie unter
https://www.postgresql.org/docs/current/static/pgcrypto.html#AEN183437
erläutert. (Was ein Salt ist, erklärt
https://en.wikipedia.org/wiki/Salt_(cryptography) recht
gut.)

Tim

Magnus Warker

unread,
Oct 3, 2017, 8:59:28 AM10/3/17
to
Hi Tim!

On 10/03/2017 01:21 AM, Tim Landscheidt wrote:
> Magnus Warker <war...@mailinator.com> wrote:

> Wenn ich
> https://dev.mysql.com/doc/refman/5.5/en/encryption-functions.html#function_encrypt
> richtig verstehe, berechnet encrypt() nicht wie von Dir an-
> gedeutet den SHA512-Hash des Argumentes, sondern ruft intern
> crypt(3) mit einem zufälligen Salt auf.

Dass mysql's encrypt intern die Systemfunktion crypt aufruft, wusste
ich, aber mir war nicht klar, welchen Algorithmus diese verwendet.
Jetzt, nach erneutem Blick in die man-Page, vermute ich DES.

Wie auch immer, auf SHA512 kam ich, weil in meinem IMAP-Server (dovecot)
folgendes konfiguriert ist:

default_pass_scheme = SHA512-CRYPT

Wenn mysql's encrypt nicht SHA512 verwendet, dann hätte hier die
Authentifizierung ja nie funktionieren dürfen. Hat sie aber.
Das ist jetzt natürlich spezifisch für diesen IMAP-Server, aber
vielleicht kennt diesen hier ja jemand und kann das Rätsel aufklären?

> Du könntest dafür pgcryptos crypt()- und gen_salt()-Funktio-
> nen benutzen wie unter
> https://www.postgresql.org/docs/current/static/pgcrypto.html#AEN183437
> erläutert. (Was ein Salt ist, erklärt
> https://en.wikipedia.org/wiki/Salt_(cryptography) recht
> gut.)

Danke! Es sieht für mich so aus, als ob man gen_salt mit dem Parameter
'des' aufrufen muss, um ein Ergebnis zu erhalten, das dem von encrypt
ähnelt (13 Zeichen lang):

select crypt('Test',gen_salt('des'));

crypt
---------------
mzOfZZMYbxQ9I
(1 row)

BTW: Ich wollte dazu eine Funktion "pwd" definieren, aber die liefert
wieder längere Ergebnisse:


CREATE OR REPLACE FUNCTION pwd(TEXT) returns text AS $$
SELECT crypt($1,gen_salt('des'));
$$ LANGUAGE SQL STRICT IMMUTABLE;

select pwd('Test');
pwd
------------------------------------
$1$CWUXc873$3LzSMuI/p90rSrDUuwvK4.
(1 row)

Warum liefert diese Funktion nicht Strings gleicher Länge wie oben?

Danke
Magnus



Magnus Warker

unread,
Oct 6, 2017, 3:22:01 AM10/6/17
to
Hallo,

das letzte Problem mit der Funktion ist gelöst, war mein Fehler, reden
wir nicht mehr darüber.

Ich bin jetzt soweit, dass ich mit

doveadm pw -s SHA512-CRYPT

Passwort-Hashes erstellen kann, mit denen auch die Authentifizierung
mit dovecot funktioniert.

Was nach wie vor nicht funktioniert, ist die Authentifizierung mit den
mit pgsql erzeugten Hashes:

digest('Passwort','sha512')

Es fällt auf, dass die mit doveadm erstellten Hashes mit "$6" beginnen,
die mit der digest-Funktion jedoch nicht (beginnen mit "\x").

Was ist falsch an den mit digest erzeugten Hashes?

Danke
Magnus

Peter J. Holzer

unread,
Oct 6, 2017, 4:12:21 AM10/6/17
to
Nichts ist falsch daran, es ist nur etwas anderes.

digest('Passwort','sha512') berechnet den SHA-512 Hash von 'Passwort'.
Das Ergebnis ist ein 512 Bit (64 Byte) langes bytea (ungefähr äquivalent
zu binary in MySQL orde blob in Oracle).

Die SHA-512-Variante von crypt(3) berechnet nicht einfach den SHA-512
Hash das Passworts. Sie verwendet den SHA-512-Algorithmus nur als
Baustein, um das Passwort und das Salt miteinander zu kombinieren (und
das nicht nur einmal, sondern oft. Wenn Du den von Dir angestoßenen
Thread in dcoulm gelesen hast (und Dich nicht nur über die Antworten,
die Dir nicht gefallen haben, beklagt), dann ist Dir wahrscheinlich der
Parameter "rounds" aufgefallen, den mindestens eine Person erwähnt hat).

Das hat mehrerere Gründe:

* Man soll nicht auf den ersten Blick erkennen, dass zwei Benutzer das
gleiche Passwort haben. SHA-512('Passwort') ist immer
aaf6a7d781d14ad069bf26988cbda52043197c14f3a9762778a7ba9d31bebce0bfbb27368e39c18471dc611731877cd4796b80c660ff9be2d0d63eaa649c4c1d,
wenn zwei oder mehr User dieses (dumme) Passwort gewählt haben, muss
ich es nur einmal knacken. Ein zufälliges Salt verhindert das.
* Man soll nicht Passwort-Hashes "auf Vorrat" berechnen können. Es gibt
bei SHA512-crypt soweit ich sehe 2^128 verschiedene Salts, man müsste
also für jedes Passwort 2^128 Hashes berechnen, um eine Rainbow-Table
erstellen zu können. Das ist offensichtlich unmöglich.
* Das Überprüfen eines Passworts soll spürbar Zeit brauchen.
Hash-Algorithmen wie SHA-512 sollen schnell sein: Man will sie
verwenden können, um Hashes großer Datenmengen in kurzer Zeit zu
berechnen (denke an Daten, die über eine Gigabit-, 10-Gigabit- oder
gar 100 Gigabit-Leitung geschickt werden). Passwörter sind kurz, und
werden selten überprüft (wenn wer Millionen Passwörter pro Sekunde
überprüfen will, führt er meistens nichts Gutes im Schilde). Also will
man für ein Passwort SHA-512 oft aufrufen. Wenn möglich mit variabler
Anzahl der Runden, damit man die Geschwindigkeit an die
Geschwindigkeit des Prozessors (und die Wichtigkeit des Passworts)
anpassen kann.

hp


--
_ | Peter J. Holzer | Fluch der elektronischen Textverarbeitung:
|_|_) | | Man feilt solange an seinen Text um, bis
| | | h...@hjp.at | die Satzbestandteile des Satzes nicht mehr
__/ | http://www.hjp.at/ | zusammenpaßt. -- Ralph Babel

Magnus Warker

unread,
Oct 6, 2017, 6:41:07 AM10/6/17
to
Hallo Peter!

On 06.10.2017 10:12, Peter J. Holzer wrote:

>> Was ist falsch an den mit digest erzeugten Hashes?

> Nichts ist falsch daran, es ist nur etwas anderes.

Danke für die ausführliche Erklärung der beiden Varianten!

Variante 1: einmalige Hash-Berechnung

> digest('Passwort','sha512') berechnet den SHA-512 Hash von 'Passwort'.
> Das Ergebnis ist ein 512 Bit (64 Byte) langes bytea (ungefähr äquivalent
> zu binary in MySQL orde blob in Oracle).

Variante 2: wiederholte Hash-Berechnung

> Die SHA-512-Variante von crypt(3) berechnet nicht einfach den SHA-512
> Hash das Passworts. Sie verwendet den SHA-512-Algorithmus nur als
> Baustein, um das Passwort und das Salt miteinander zu kombinieren (und
> das nicht nur einmal, sondern oft.

Verstehe ich das richtig, dass doveadm pw -s SHA512-CRYPT die zweite
Variante anwendet? Es ergibt zumindest für das gleiche Passwort immer
einen anderen Hash, im Gegensatz zur digest-Funktion.

Nach Deiner Schilderung ist die Verwendung der digest-Funktion mit
Nachteilen Verbunden, u. a. weil man für ein Passwort immer den selben
Hash erhält. Das leuchtet mir ein. Aber warum funktioniert die
Authentifizierung mit dovecot damit gar nicht?

Warum beginnen diese Hashs immer mit "$6"?

Und last but not least:
Wie kann man die SHA-512-Variante von crypt(3) innerhalb von postgresql
mit SQL durchführen?

Danke
Magnus

Peter J. Holzer

unread,
Oct 6, 2017, 9:36:17 AM10/6/17
to
On 2017-10-06 10:39, Magnus Warker <war...@mailinator.com> wrote:
> On 06.10.2017 10:12, Peter J. Holzer wrote:
>
>>> Was ist falsch an den mit digest erzeugten Hashes?
>
>> Nichts ist falsch daran, es ist nur etwas anderes.
>
> Danke für die ausführliche Erklärung der beiden Varianten!
>
> Variante 1: einmalige Hash-Berechnung
>
>> digest('Passwort','sha512') berechnet den SHA-512 Hash von 'Passwort'.
>> Das Ergebnis ist ein 512 Bit (64 Byte) langes bytea (ungefähr äquivalent
>> zu binary in MySQL orde blob in Oracle).
>
> Variante 2: wiederholte Hash-Berechnung
>
>> Die SHA-512-Variante von crypt(3) berechnet nicht einfach den SHA-512
>> Hash das Passworts. Sie verwendet den SHA-512-Algorithmus nur als
>> Baustein, um das Passwort und das Salt miteinander zu kombinieren (und
>> das nicht nur einmal, sondern oft.
>
> Verstehe ich das richtig, dass doveadm pw -s SHA512-CRYPT die zweite
> Variante anwendet?

Ja.

> Nach Deiner Schilderung ist die Verwendung der digest-Funktion mit
> Nachteilen Verbunden, u. a. weil man für ein Passwort immer den selben
> Hash erhält. Das leuchtet mir ein. Aber warum funktioniert die
> Authentifizierung mit dovecot damit gar nicht?

Vermutlich weil das niemand in dovecot implementiert hat. Warum sollte
man? Niemand, der auch nur den Hauch einer Ahnung hat, würde das
verwenden wollen, und denen, die keine Ahnung haben, sollte man besser
nicht die Kanone geben, mit der sie sich den Fuß bis zur Schulter
wegschießen können.


> Warum beginnen diese Hashs immer mit "$6"?

Weil crypt auf diese Weise verschiedene Hash-Verfahren markiert. Wenn
der Hash die Form $6$...$.... hat, ist es SHA512, das Salt steht
zwischen den $ Zeichen und das Ergebnis dahinter. $1$ ist das gleiche
mit MD5. Wie man leicht erraten kann, gibt es zwischen $1$ und $6$ noch
ein paar Varianten ;-). Wenn der Hash nicht mit $ anfängt und genau 13
Zeichen lang ist, ist es der Original-DES-crypt-Algorithmus (in dem Fall
sind die ersten 2 Zeichen das Salt).


> Und last but not least:
> Wie kann man die SHA-512-Variante von crypt(3) innerhalb von postgresql
> mit SQL durchführen?

Soweit ich sehe, gar nicht. MD5-crypt funktioniert:

hjp=> SELECT crypt('Passwort', '$1$1234');
crypt
--------------------------------
$1$1234$AkPzNRcIp0tMvFgqZRe.30
(1 row)

aber SH512-crypt nicht:

hjp=> SELECT crypt('Passwort', '$6$1234');
crypt
---------------
$6z9eEMYcYaBM
(1 row)

Wenn Dein Dovecot aber mit DES-Hashes zufrieden war, ist es vielleicht
auch mit MD5-Hashes zufrieden?

Magnus Warker

unread,
Oct 6, 2017, 12:58:13 PM10/6/17
to
On 10/06/2017 03:36 PM, Peter J. Holzer wrote:
> On 2017-10-06 10:39, Magnus Warker <war...@mailinator.com> wrote:
>> On 06.10.2017 10:12, Peter J. Holzer wrote:

>> Wie kann man die SHA-512-Variante von crypt(3) innerhalb von postgresql
>> mit SQL durchführen?
>
> Soweit ich sehe, gar nicht.

In der pgcrypto-Doku steht:

crypt()
Calculates a crypt(3)-style hash of password.

[https://www.postgresql.org/docs/8.3/static/pgcrypto.html]

Warum geht das damit nicht? "crypt(3)-style" müsste doch genau das o. g.
Verfahren meinen, oder?

(Habe aber selbst schon gemerkt, dass gen_salt('sha512') es nicht tut.)

> MD5-crypt funktioniert:

Ist aber schwach...

> Wenn Dein Dovecot aber mit DES-Hashes zufrieden war, ist es vielleicht
> auch mit MD5-Hashes zufrieden?

Du meinst, weil mysql's encrypt DES-Hashes erzeugt und es damit
funktioniert hat?

Das wäre im pgsql dies:

crypt('new password', gen_salt('md5'));

Nun, ich dachte, wenn ich schon die DB wechsle und dadurch die Hashes
anfasse, könnte ich auch einen deutlich stärkeren nehmen...

Magnus

Peter J. Holzer

unread,
Oct 6, 2017, 2:58:24 PM10/6/17
to
On 2017-10-06 16:59, Magnus Warker <war...@mailinator.com> wrote:
> On 10/06/2017 03:36 PM, Peter J. Holzer wrote:
>> On 2017-10-06 10:39, Magnus Warker <war...@mailinator.com> wrote:
>>> Wie kann man die SHA-512-Variante von crypt(3) innerhalb von postgresql
>>> mit SQL durchführen?
>>
>> Soweit ich sehe, gar nicht.
>
> In der pgcrypto-Doku steht:
>
> crypt()
> Calculates a crypt(3)-style hash of password.
>
> [https://www.postgresql.org/docs/8.3/static/pgcrypto.html]
>
> Warum geht das damit nicht? "crypt(3)-style" müsste doch genau das o. g.
> Verfahren meinen, oder?

Ja, darauf bin ich beim ersten Lesen auch reingefallen. Aber da steht
eben "crypt(3)-style" und nicht "ruft die crypt(3)-Funktion des
Betriebssystems auf". D.h., die pgcrypto-Entwickler haben das
nachprogrammiert und dabei nicht alle Methoden implementiert, die ein
modernes Linux kennt (dafür gibt welche, die mein Debian nicht kennt).
Kannst ja als Feature-Request einwerfen, dass sie die Methoden 5 und 6
(SHA256 und SHA512) implementieren sollen.


> (Habe aber selbst schon gemerkt, dass gen_salt('sha512') es nicht tut.)
>
>> MD5-crypt funktioniert:
>
> Ist aber schwach...

Stark genug für fast jede Anwendung, würde ich sagen. Wie bereits
ausgeführt, ruft crypt(3) nicht einfach nur die zugrundeliegende
Hash-Funktion auf, sondern verwendet ein Salt und mehrere Runden. Die
Angriffsverfahren gegen MD5 sind m.W. alle *nicht* auf MD5-crypt
anwendbar. Achte lieber darauf, dass Deine User vernünftige Passwörter
verwenden - das bringt mit Sicherheit einen größeren Gewinn als der
Unterschied zwischen MD5-crypt und SHA512-crypt.


>> Wenn Dein Dovecot aber mit DES-Hashes zufrieden war, ist es vielleicht
>> auch mit MD5-Hashes zufrieden?
>
> Du meinst, weil mysql's encrypt DES-Hashes erzeugt und es damit
> funktioniert hat?

Ja.


> Das wäre im pgsql dies:
>
> crypt('new password', gen_salt('md5'));

Ja.


> Nun, ich dachte, wenn ich schon die DB wechsle und dadurch die Hashes
> anfasse, könnte ich auch einen deutlich stärkeren nehmen...

Bis vor kurzem wusstest Du ja nicht mal, dass Du DES und nicht SHA-512
verwendest. Und im Vergleich zu DES ist MD5 deutlich stärker (schon
deshalb, weil man Passwörter über 8 Zeichen Länge verwenden kann).
0 new messages