Share your secrets 1.0 für PHP

Als ich das erste Mal davon las, war ich wirklich beeindruckt, wie einfach und sicher das ist. Aber worum geht es überhaupt? Manchmal möchte man ein Geheimnis auf besondere Weise mit anderen teilen. Stellen Sie sich vor, Sie haben fünf Administratoren in Ihrem Unternehmen. Diese benötigen irgendwie Zugriff auf den Großteil Ihrer Hardware und Anwendungen. Sie müssen ihnen also z. B. Root-Zugriff auf Ihre Unix-Server geben, damit sie diese warten können. Nehmen wir an, Sie haben einen besonderen Server, auf dem Ihr LDAP läuft oder auf dem die privaten Schlüssel Ihres Unternehmens gespeichert sind, und Sie möchten nicht, dass irgendeiner Ihrer Administratoren „unbegrenzten“ Zugriff darauf hat. Was tun Sie? Auch dieser Server muss von jemandem gewartet und genutzt werden, richtig? Warum teilen Sie also nicht das Root-Passwort (das Geheimnis) auf? Sie könnten jedem Ihrer Administratoren einen eindeutigen Anteil (Share) geben und festlegen, dass mindestens zwei Shares nötig sind, um auf den Server zuzugreifen. Das wäre eine einfache Möglichkeit, ein Vier-Augen-Prinzip umzusetzen. Aber wie?
Es gibt einen eleganten Weg, das zu tun. Er heißt Shamir’s Shared Secret. Der berühmte Adi Shamir, der auch dem Rivest-Shamir-Adleman-Kryptosystem (RSA) seinen Namen gab, hat auch diesen kryptographischen Algorithmus entwickelt. Er erlaubt es, ein Geheimnis in Teile (sogenannte Shares) zu zerlegen. Jeder Teil kann an eine Person oder Organisation ausgegeben werden. Das Schöne an diesem Algorithmus ist, dass einige oder alle Teile benötigt werden, um das Geheimnis zu rekonstruieren (der sogenannte Threshold). Um den Algorithmus zu verstehen, braucht man lediglich Grundkenntnisse in Algebra. Es gibt einen schönen Blog-Beitrag von DataGenetics, der diesen Algorithmus anschaulich erklärt.
Wir haben Shamir’s Shared Secret in PHP implementiert. Es ist auf GitHub unter MIT-Lizenz verfügbar.
Installation
Die Installation setzt voraus, dass Sie composer bereits installiert haben. Danach sind nur noch drei kleine Schritte nötig:
# git clone https://github.com/teqneers/shamir.git
# cd shamir/
# PATH_TO/composer.phar install
Verwendung
Der einfachste Weg zum Ver-/Entschlüsseln führt über die Konsole. Das Skript bin/shamir.php bietet Ihnen eine Hilfe an.
Nehmen wir also an, wir möchten Shares für alle unsere Administratoren erstellen. Wir müssen das Passwort „4eyesonly“ verschlüsseln, welches das Root-Passwort für unseren besonderen Server ist.
# bin/shamir.php shamir:share
The secret to share: 4eyesonly
Number of shared secrets to create [3]: 5
Number of shared secrets required [2]: 2
102011l2s5j1f0g4w0z264.
102021z302k0j3;1b4,1;19
10203243h585a1u3m371r3e
102042i3y294e58011m1f5j
102052w464*3i2%2c5o131,
Jeder dieser Shares muss an Ihre Administratoren ausgegeben werden. Ein einzelner Share kann das Geheimnis nicht wiederherstellen. Dazu sind mindestens zwei nötig.
Zwei beliebige der Shares können das Geheimnis wiederherstellen. Wir können dasselbe Skript verwenden, nur mit einem anderen Argument.
# bin/shamir.php shamir:recover
Shared secret [empty to stop]: 10203243h585a1u3m371r3e
Shared secret [empty to stop]: 102011l2s5j1f0g4w0z264.
Shared secret [empty to stop]:
4eyesonly
Natürlich wäre dieses Vorgehen für unser Beispiel nicht sehr hilfreich, weil die Administratoren das Geheimnis in diesem Moment kennen würden. Sie sollten daher vielleicht eine eigene Lösung entwickeln und den Algorithmus in Ihr Authentifizierungsmodul integrieren.
Hier ist der programmatische Weg, um Ihr Geheimnis zu ver-/entschlüsseln.
<?php
require_once __DIR__ . '/../vendor/autoload.php';
use TQShamirSecret;
// create 5 shares with a threshold of 2,
// so you will need a minimum of 2 shares
// to recover the secret.
$shares = Secret::share('4eyesonly ', 5, 2);
// output your shares
var_dump($shares);
// we can use different keys to recover the data,
// but we need at least 2 of them both dump will
// recover the secret and can be used to
// authenticate the 2 admins
var_dump(Secret::recover(array_slice($shares, 0, 2)));
var_dump(Secret::recover(array_slice($shares, 1, 2)));
Probieren Sie es aus und lassen Sie uns wissen, wie es Ihnen gefällt.