2017-02-12 25 views
1

我使用加密下面的類(通過繼承)如何在PHP中的GET請求中傳遞加密的字符串?

class UnsafeCrypto { 

const METHOD = 'aes-256-ctr'; 

/** 
* Encrypts (but does not authenticate) a message 
* 
* @param string $message - plaintext message 
* @param string $key - encryption key (raw binary expected) 
* @param boolean $encode - set to TRUE to return a base64-encoded 
* @return string (raw binary) 
*/ 
public static function encrypt($message, $key, $encode = false) 
{ 
    $nonceSize = openssl_cipher_iv_length(self::METHOD); 
    $nonce = openssl_random_pseudo_bytes($nonceSize); 

    $ciphertext = openssl_encrypt(
     $message, 
     self::METHOD, 
     $key, 
     OPENSSL_RAW_DATA, 
     $nonce 
    ); 

    // Now let's pack the IV and the ciphertext together 
    // Naively, we can just concatenate 
    if ($encode) { 
     return base64_encode($nonce.$ciphertext); 
    } 
    return $nonce.$ciphertext; 
} 

/** 
* Decrypts (but does not verify) a message 
* 
* @param string $message - ciphertext message 
* @param string $key - encryption key (raw binary expected) 
* @param boolean $encoded - are we expecting an encoded string? 
* @return string 
*/ 
public static function decrypt($message, $key, $encoded = false) 
{ 
    if ($encoded) { 
     $message = base64_decode($message, true); 
     if ($message === false) { 
      throw new Exception('Encryption failure'); 
     } 
    } 

    $nonceSize = openssl_cipher_iv_length(self::METHOD); 
    $nonce = mb_substr($message, 0, $nonceSize, '8bit'); 
    $ciphertext = mb_substr($message, $nonceSize, null, '8bit'); 

    $plaintext = openssl_decrypt(
     $ciphertext, 
     self::METHOD, 
     $key, 
     OPENSSL_RAW_DATA, 
     $nonce 
    ); 

    return $plaintext; 
} 
} 

字符串繼承的類,如下。

class SaferCrypto extends UnsafeCrypto { 
const HASH_ALGO = 'sha256'; 

/** 
* Encrypts then MACs a message 
* 
* @param string $message - plaintext message 
* @param string $key - encryption key (raw binary expected) 
* @param boolean $encode - set to TRUE to return a base64-encoded string 
* @return string (raw binary) 
*/ 
public static function encrypt($message, $key, $encode = false) 
{ 
    list($encKey, $authKey) = self::splitKeys($key); 

    // Pass to UnsafeCrypto::encrypt 
    $ciphertext = parent::encrypt($message, $encKey); 

    // Calculate a MAC of the IV and ciphertext 
    $mac = hash_hmac(self::HASH_ALGO, $ciphertext, $authKey, true); 

    if ($encode) { 
     return base64_encode($mac.$ciphertext); 
    } 
    // Prepend MAC to the ciphertext and return to caller 
    return $mac.$ciphertext; 
} 

/** 
* Decrypts a message (after verifying integrity) 
* 
* @param string $message - ciphertext message 
* @param string $key - encryption key (raw binary expected) 
* @param boolean $encoded - are we expecting an encoded string? 
* @return string (raw binary) 
*/ 
public static function decrypt($message, $key, $encoded = false) 
{ 
    list($encKey, $authKey) = self::splitKeys($key); 
    if ($encoded) { 
     $message = base64_decode($message, true); 
     if ($message === false) { 
      throw new Exception('Encryption failure'); 
     } 
    } 

    // Hash Size -- in case HASH_ALGO is changed 
    $hs = mb_strlen(hash(self::HASH_ALGO, '', true), '8bit'); 
    $mac = mb_substr($message, 0, $hs, '8bit'); 

    $ciphertext = mb_substr($message, $hs, null, '8bit'); 

    $calculated = hash_hmac(
     self::HASH_ALGO, 
     $ciphertext, 
     $authKey, 
     true 
    ); 

    if (!self::hashEquals($mac, $calculated)) { 
     throw new Exception('Encryption failure'); 
    } 

    // Pass to UnsafeCrypto::decrypt 
    $plaintext = parent::decrypt($ciphertext, $encKey); 

    return $plaintext; 
} 

/** 
* Splits a key into two separate keys; one for encryption 
* and the other for authenticaiton 
* 
* @param string $masterKey (raw binary) 
* @return array (two raw binary strings) 
*/ 
protected static function splitKeys($masterKey) 
{ 
    // You really want to implement HKDF here instead! 
    return [ 
     hash_hmac(self::HASH_ALGO, 'ENCRYPTION', $masterKey, true), 
     hash_hmac(self::HASH_ALGO, 'AUTHENTICATION', $masterKey, true) 
    ]; 
} 

/** 
* Compare two strings without leaking timing information 
* 
* @param string $a 
* @param string $b 
* @ref https://paragonie.com/b/WS1DLx6BnpsdaVQW 
* @return boolean 
*/ 
protected static function hashEquals($a, $b) 
{ 
    if (function_exists('hash_equals')) { 
     return hash_equals($a, $b); 
    } 
    $nonce = openssl_random_pseudo_bytes(32); 
    return hash_hmac(self::HASH_ALGO, $a, $nonce) === hash_hmac(self::HASH_ALGO, $b, $nonce); 
} 
} 

加密字符串如下。

$email = '[email protected]'; 
$key = 'Some key'; 
$encrypted_email = $encrypted = SaferCrypto::encrypt($message, $key); 

字符串是越來越加密這樣的:

óÜCu!>Ò·<x0½「—J ‡l¿Ø ;ƒ;›OøVP#ï 1 Sjñ,(ñúrÛòv–~ºyÍg ÷–´´iƒû 

如果我通過這個與urlencode($string)數據是沒有得到解密因爲散列不匹配,因爲hashEquals方法是拋出異常。

在GET請求中傳遞加密字符串的正確方法是什麼?

+1

'哈希不matching'你有一個散列或加密? (哈希不能解密) – chris85

+0

@ chris85如果你看'解密'方法[這裏](http://stackoverflow.com/a/30189841)方法'hashEquals'拋出錯誤。 – Ankit

+1

你的問題應該有所有的信息。 – chris85

回答

0

目前還不清楚,問題是什麼,但是您可以使用base64_encode($encrypted_email)來傳遞字符串,如HDo1FaXabDHjfxBkpx7YBHNGVeZ/G8FvI2BoxES2rUu3lvNWRo5G0PImiv9IhENv

<a href="?enc=<?=base64_encode($encrypted_email)?>">link</a> 

接收時,對其進行解碼

$encrypted_email = base64_decode($_GET['enc']); 
+0

對不起,我錯過了隱藏的評論。只是一個答案) –

相關問題