2016-08-03 37 views
1

Ich muss eine GET-Zeichenfolge an eine E-Mail übergeben, damit ein Benutzer auf bestimmte Buchungsdetails zugreifen kann. , d. H. /bookingconformation.php? BookingID = 123.Verständnis der Verschlüsselung mit base64 und mcrypt

Ich versuche, das BookingID mit base64 (bearbeiten und mcrypt) (in der Hoffnung, zu verschlüsseln, dass es fast unmöglich sein wird, zu erraten, und Zugriff auf andere Benutzern Buchung Details (obwohl die Buchungsdaten sind nicht wirklich zu empfindlich!)). Dies ist so, dass nur der vorgesehene Benutzer auf die Buchungsbestätigung zugreifen kann.

Ich verwende Code, der hauptsächlich hier (stackOverflow) gefunden wird, da ich weit entfernt von einem Verschlüsselungsexperten bin !!

Ich habe ein paar Probleme. Der Code ich benutze ist unten und darunter ist die Liste der Probleme i

/** 
    * a basic encryption for things like IDs, so links can be created and emailed to i.e booking details 
    * @param int/str $x what is to be encrypted 
    * @ENCRYPTION_KET str the encyption key 
    * @return encrypted string 
    */ 
    public static function basicEncrypt($x, $ENCRYPTION_KET) { 
     $key = pack('H*', $ENCRYPTION_KET); 
     $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC); 
     $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND); 
     $ciphertext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $x, MCRYPT_MODE_CBC, $iv); 
     $ciphertext = $iv . $ciphertext; 
     $ciphertext_base64 = base64_encode($ciphertext); 
     $encrypted_x = urlencode($ciphertext_base64); 
     return $encrypted_x; 
    } 

    /** 
    * a basic de-cryption for things like IDs, so links can be created and emailed to i.e booking details 
    * @param str $x what is to be de-crypted 
    * @ENCRYPTION_KET str the encyption key 
    * @return decrypted string 
    */ 
    public static function basicDecrypt($x, $ENCRYPTION_KET) {  
     $x = urldecode($x);  
     $ciphertext_dec = base64_decode($x);   
     $key = pack('H*', $ENCRYPTION_KET); 
     $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC); 
     $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND); 
     $iv_dec = substr($ciphertext_dec, 0, $iv_size); 
     $ciphertext_dec = substr($ciphertext_dec, $iv_size); 
     $de_crypted_x = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $ciphertext_dec, MCRYPT_MODE_CBC, $iv_dec); 
     return $de_crypted_x;  
    } 

Ausgabe 1 habe: mit basicEncrypt() gibt eine andere Verschlüsselungskette jedes Mal, wenn ich es verwenden (dh für die gleiche bookingID von 123). Solange es zu den gleichen zu entschlüsselt, ist es egal, wenn die Verschlüsselungszeichenfolge jedes Mal anders ist. Kann mir jemand mitteilen, ob das jedes Mal eine andere Zeichenkette zurückgeben soll und ich wäre auch dankbar, wenn eine (leicht verständliche) Erklärung gegeben werden könnte, warum das so ist?

Problem 2: Der obige Code die meiste Zeit funktioniert .... (vielleicht 80%) aber auch andere Zeiten es nicht auf die richtige Antwort nicht entschlüsseln ... Ich verstehe nicht, warum :-(wenn. jeder kann lassen sie mich wissen, was ich falsch mache, so dass es zu 100% der Zeit arbeitet, würde ich sehr dankbar

Ausgabe 3: (mögliche Ausgabe) ich bin mit urlencode() und urldecode(). Ich habe viel auf StackOverflow gelesen und kann nicht herausfinden, ob ich das verwenden sollte oder nicht! Ich vermute, Problem 2 kann dadurch verursacht werden, aber kann nicht gesehen, um den richtigen Weg von dann zu tun dies und URL-Sicherheit. Ich habe versucht, unter den urlencode mit etwas Ähnliches wie das Ersetzen (hier gefunden), aber dies führt dann die über 0% der Zeit

function base64_url_encode($input) { 
return strtr($input, '+/=', '-_,'); 
} 

function base64_url_decode($input) { 
return strtr($input, '-_,', '+/='); 
} 

auch arbeiten, ist die Methode, die ich zu erlauben, bin mit der Benutzer, um ihre Buchungsdetails zu sehen OK/ratsam? (Wie erwähnt, sind die Daten nicht wirklich sensibel, es enthält nur den Benutzernamen, Buchung REF und was gebucht wurde. ID muss angezeigt werden, wenn der Benutzer für die (Hotel-) Buchung auftaucht.

Jede Hilfe, die mir erlaubt zu verstehen, was ich mache (und Verschlüsselung) ein wenig besser ist sehr geschätzt oder noch mehr geschätzt, wenn jemand darauf hinweisen kann (so dass ich korrigieren kann) die Fehler in meiner Methode wäre großartig! !

Vielen Dank für

an diesem :-) Ford sucht
+0

@CharlotteDunois basee64_decode entschlüsselt nicht (wie Sie wissen) ... dekodiert. Ford: Issue1 ist kein Problem .. ein zufälliger "Initialisierungsvektor" wird jedes Mal verwendet ... resultierend in unterschiedlichen crypttext –

+0

@BradKent und anderenPostern, ich sehe jetzt, was es anders ist ... einfach wirklich, aber ich tat es nicht Finde es heraus, bis es darauf hingewiesen wurde :-) – Ford

+1

Du könntest dein Leben viel einfacher machen, wenn du [defuse/php-encryption] benutzt hast (https://github.com/defuse/php-encryption). –

Antwort

1

Wenn jemand mich wissen lassen kann, ob dies eine andere Zeichenfolge jedes Mal zurückgeben sollte und ... warum ist das?

Das Verschlüsselungsergebnis wird durch den Verschlüsselungsschlüssel, den Klartext und den Initialisierungsvektor (iv) bestimmt. Die iv wird zufällig jedes Mal, wenn als Ergebnis dieser Linie verschlüsseln gebaut:

$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND); 

So das Ergebnis ist auch jedes Mal anders.

Der obige Code die meiste Zeit funktioniert .... (vielleicht 80%) aber auch andere Zeiten entschlüsseln nicht auf die richtige Antwort

Ich weiß nicht, was das ist. URL-Codierung/Decodierung sollte ausreichend sein; Ich glaube nicht, dass Base64-Kodierung benötigt wird. Achten Sie darauf, es in der richtigen Reihenfolge zu tun: zuerst verschlüsseln und dann beim Schreiben verschlüsseln. Decodiere zuerst und entschlüssele dann beim Lesen.

Ich versuche, das BookingID mit base64 (in der Hoffnung, zu verschlüsseln, dass es fast unmöglich sein wird, Details zu erraten, und anderen Nutzer Zugang buchen ... ist die Methode, die ich dem Benutzer zu erlauben, bin mit zu sehen ihre Buchungsdetails OK

Ein besserer Ansatz wäre eine Authentifizierung erforderlich ist. Sie können die Buchungsnummer unverschlüsselt, lassen aber den Benutzer durch die Forderung Benutzername & Pass schützen, bevor Sie die Buchungsdetails zeigen

i zustimmen Authentifizierung ist besser, aber ich brauche auch für nicht-registrierte Benutzer

Ich würde verwenden, um einen verschlüsselten Hash zu ermöglichen, und umfassen sowohl die Buchungsnummer und den Hash in der URL. Es wird dann leicht zu wissen sein, wenn ein Benutzer versucht, auf die Buchung eines anderen zuzugreifen.

Einstellen der URL:

//hash will always be the same for the same booking id, but impossible to guess 
$hash = hash_hmac('sha256',$bookingID,$SECRET_KEY); 

//url includes both the booking id and the hash 
$url = "http://example.com/confirm.php?id=$bookingID&sig=$hash"; 

Vor der Buchung Details zeigt, stellen Sie sicher, dass der Hash korrekt ist:

if(!isset($_GET['id'],$_GET['sig'])){ 
    http_response_code(400); //tells the browser that the request is malformed 
    echo "Missing booking id or signature"; 
    exit; 
} 
$bookingID = $_GET['id']; 
$sig = $_GET['sig']; 
$correct_hash = hash_hmac('sha256',$bookingID,$SECRET_KEY); 

//if anyone modifies the url, the sig will not equal the correct hash 
if($sig!==$correct_hash){ 
    http_response_code(400); 
    echo "Invalid signature"; 
    exit; 
} 
//we get here if the sig matched the booking ID. Show booking details 

Mit dieser Technik Sie weitere Informationen in der URL hinzufügen können, wie zum Beispiel ein expires Parameter, der dazu führt, dass die Anfrage abgelehnt wird, wenn jemand nach zu langer Zeit auf den Link klickt. Um sicherzustellen, dass niemand der Linksetzung verändert, nur sind alle Parameter in der Signatur:

$hash = hash_hmac('sha256',"$bookingID.$expires",$SECRET_KEY); 

Wenn Sie die Signatur überprüfen, indem Sie einen neuen Hash-Gebäude, stellen Sie sicher die gleichen Parameter in der gleichen Reihenfolge enthalten

+0

danke! Ich stimme zu, dass Authentifizierung besser ist, aber ich muss auch nicht registrierte Benutzer zulassen (ich habe es bereits mit Authentifizierung getan, aber brauche diese Methode auch :-() – Ford

+1

@Ford Ich habe einen Abschnitt am Ende meiner Antwort hinzugefügt zeige dir, was ich tun würde, wenn Authentifizierung keine Option wäre – BeetleJuice

+0

vielen Dank !! Ich werde das versuchen :-) – Ford

3

Erstens hat base64() nichts mit Verschlüsselungs- zu tun, es ist eine Art der Codierung ist und nicht für jede Art von Schutz verwendet werden soll. Bitte verwenden Sie diese Begriffe nicht im selben Satz!

Der Grund dafür, dass die Verschlüsselung jedes Mal eine andere Ausgabe bereitstellt, besteht darin, dass Sie für jede Verschlüsselung eine zufällige IV verwenden.

$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND); 


Warum ist es ein Problem mit, die der Benutzer authentifiziert werden, wenn sie die Buchungsbestätigung Endpunkt treffen? Sie könnten /bookingconfirmation.php?bookingID=123 besuchen und entweder bereits authentifiziert sein oder sich anmelden, um die Buchung anzusehen. Dies scheint die beste und sicherste Option zu sein. Die ID in der URL ist ebenfalls kein Problem mehr, da Sie sie gegen den Benutzer überprüfen können.

Alternativ können Sie eine zufällige ID an die Buchung binden, die ausreichend zufällig/stark genug ist, um einen Brute-Force-Angriff in Verbindung mit einer Ratenbegrenzung für den Endpunkt zu verhindern, wenn der Benutzer nicht authentifiziert werden soll.

$randomToken = bin2hex(openssl_random_pseudo_bytes(16)); 


würden Sie dann die Zufalls-Token verwenden, um die Buchung statt der Buchung ID, /bookingconfirmation.php?bookingID=$randomToken zu holen. Dies ist ein besserer und einfacherer Ansatz als die Verschlüsselung der Buchungs-ID in der URL.

+0

danke, sehr geschätzt. Ich authentifiziere auch einige Benutzer, aber die Registrierung ist optional, daher muss ich auch keinen registrierten Mitgliedern Zugriff gewähren. Danke für deine Antwort, es klingt eine gute Lösung! – Ford

+2

Ah ja, wenn der Benutzer eine Buchung ohne Registrierung vornehmen kann, benötigen Sie eine andere Methode. Ich sollte hinzufügen, wenn Sie die Route der Erstellung eines zufälligen Token für jede Buchung gehen, um sie abzurufen, können sie nicht über die sequenzielle ID zugegriffen werden, oder ein Angreifer könnte sie immer noch gehen. –

+0

danke. Ich denke, ich Understyand (/bookingconformation.php? bookingID = 123 würde keine Ergebnisse zurückgeben (wie es "123" zu etwas falsch entschlüsseln würde)). oder wie du sagst, ich nur auf dem randomToken übereinstimmen. wenn du das meinst? – Ford