2016-08-03 4 views
1

ユーザが特定の予約の詳細にアクセスできるようにするには、GET文字列を電子メールに渡す必要があります。 つまり/bookingconformation.php?bookingID=123。私はそれを推測し、アクセス他のユーザーが(予約の詳細は本当にあまりにも敏感ではないが、細部を予約することはほぼ不可能になることを期待してbase64で(編集とmcryptの)(とbookingIDを暗号化しようとしていますbase64とmcryptによる暗号化について

!) )。これは、意図されたユーザだけが予約の形態にアクセスできるようにするためです。

私は暗号化の専門家から遠いので、私はここで主に見つかったコードを使用しています(stackOverflow)!

私はいくつかの問題を抱えています。私が使用しています コードは以下であり、この下に、私は

/** 
    * 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;  
    } 

1号が午前問題のリストです:basicEncryptを()を使用しては異なる暗号化文字列私は同じのために、すなわち(それを使用するたびになりますが123の予約ID)。 暗号化文字列が毎回異なるかどうかは同じですが、暗号化文字列が同じであるかどうかは関係ありません。毎回異なる文字列を返す必要があるかどうか誰にでも教えてもらえれば、これがなぜなのか理解しやすい説明があれば感謝します。

問題2: 上記のコードは、ほとんどの時間を動作します....(多分80%)が、他の回、それは正解に復号化していない...私はいけない理由を理解していれば:-(。誰もが、それは私は非常に感謝される100%の時間を動作するように私は私が間違っているのかを知るようにでき

問題3:!(可能性の問題) i)は(でurlencode()およびurldecodeを使用しています。私はstackOverflowの多くを読んだが、私はこれを使用する必要がある場合はうまくいかない!私は疑問を持っているissue 2がこれによって引き起こされるかもしれないが、正しい方法を理解できないURLを安全にすることができます。私は(ここで見つかった)以下のようなものでURLENCODEを交換しようとしているが、これは、時間も

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

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

の0%を動作するように上記の原因私はできるように使用しています方法であり、ユーザーは予約の詳細を確認するOK /お勧めですか? (データは本当に機密ではないと言われているように、ユーザー名、REFの予約、予約されたもののみが含まれています。

誰かが(私が訂正できるように)指摘できれば私の方法でのエラーは素晴らしいだろうと私が何をやっているのか理解するのを助けてくれます。 ! フォード

+0

で同じパラメータを含めるようにしてください:誰がリンクを変更しないことを確認するには、単に署名のすべてのパラメータを含めます@CharlotteDunois basee64_decodeは "解読"しません(あなたが知っているように)...デコードします。フォード:issue1は問題ではありません。ランダムな「初期化ベクトル」が毎回使用されています...異なる暗号文の結果となります –

+0

@BradKentとotherPosters、私は今何が違うか見ています...シンプルですが、 – Ford

+1

[defuse/php-encryption](https://github.com/defuse/php-encryption)を使用した方があなたの人生を楽にするかもしれません。 –

答えて

1

いつも別の文字列 を返す必要がある場合は誰でも教えてください。これはなぜですか?

暗号化結果は、暗号化キー、クリアテキスト、および初期化ベクトル(iv)によって決まります。 ivは、次の行の結果として暗号化するたびにランダムに作成されます。

結果は毎回異なります。

上記のコードは、ほとんどの時間を動作します....(多分80%)が、他の回 は、それは私がについて何を知っていない正解

に解読されません。 URLのエンコード/デコードで十分です。私はbase64エンコーディングが必要とは思わない。正しい順序で実行してください。まず暗号化してから、エンコードしてください。最初にデコードし、読み取ると解読します。

私はそれが は推測して 詳細をご予約の他のユーザーにアクセスすることはほぼ不可能になります...私は、ユーザーが参照できるようにするために使用している方法であることを期待して(BASE64でbookingIDを暗号化しようとしています

OK自分 予約の詳細は、より良いアプローチが。認証を必要とするだろうあなたは暗号化されていない予約IDを残していますが、予約の詳細を表示する前に、ユーザー名&パスを要求することによって、ユーザーを保護することができます

私は、認証が良いですが、私はまた、私は鍵付きハッシュを使用し、予約IDとURL内のハッシュの両方が含まれるであろう 非登録ユーザー

を可能にする必要があります同意します。ユーザーがいつ他の予約にアクセスしようとしているかを知ることは容易になります。あなたのような、URLに詳細情報を追加することができます

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 

をこの技術を使用して:ハッシュが正しいことを確認して、予約の詳細を示す前に

//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"; 

:URLを設定する

expiresパラメータを使用すると、あまりにも多くの時間が経過した後に誰かがリンクをクリックした場合にリクエストが拒否されます。

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

新しいハッシュを構築することにより、署名をチェックすると、同じ順序

+0

ありがとう!私は認証が優れていることに同意しますが、登録していないユーザーも許可する必要があります(認証済みですが、この方法も必要です:-() – Ford

+1

@Ford私の答えの最後にセクションを追加しました – BeetleJuice

+0

大変ありがとう!私はこれを試します:-) – Ford

3

まず、base64()は、暗号化とは何の関係もありません:-)これを見ているため

おかげで、それはエンコーディングのタイプだと保護の任意の種類のために使用すべきではありません。これらの用語を同じ文章で使用しないでください!

暗号化が毎回異なる出力を提供する理由は、暗号化ごとにランダムIVを使用しているためです。

$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND); 


なぜ彼らは予約確認書のエンドポイントを打ったときに、ユーザーが認証されたとの問題がありますか?彼らは/bookingconfirmation.php?bookingID=123を訪問することができ、既に認証されているか、または予約を見るためにログインする必要があります。これは最も安全なオプションのように思えます。 URL内のIDは、ユーザーに対して確認できるため、もはや問題にはなりません。

また、ユーザーを認証させたくない場合は、無差別攻撃を防止するのに十分なランダム/強力な予約IDと、エンドポイントのレート制限とを結びつけることができます。あなたは、代わりに予約ID、/bookingconfirmation.php?bookingID=$randomTokenの予約を取得するために、ランダムなトークンを使用することになり

$randomToken = bin2hex(openssl_random_pseudo_bytes(16)); 


。これは、URLの予約IDを暗号化するよりも簡単で簡単な方法です。

+0

ありがとう、よろしくお願いします。私もいくつかのユーザーを認証していますが、登録はオプションですので、登録されていないメンバーにもアクセスを許可する必要があります。あなたの答えをありがとう、それは良い解決策を聞く! – Ford

+2

ああ、ユーザーが登録なしで予約を行うことができる場合は、他の方法が必要です。私はそれを追加する必要があります。あなたがそれらを取得するために各予約のランダムなトークンを作成するルートを下った場合、シーケンシャルIDを介してアクセスすることはできません。 –

+0

ありがとうございます。私は私が考えていると思う(/bookingconformation.php?bookingID=123は何かを間違って "123"を解読するので)どんな結果も返さないだろう。あなたが言うように、私はrandomTokenにのみ一致します。これがあなたが意味することならば? – Ford

関連する問題