Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.1k views
in Technique[技术] by (71.8m points)

security - How to generate a Google ReCaptcha V2 secure token with PHP?

I'm trying to generate a secure token for ReCaptcha V2, as described here: https://developers.google.com/recaptcha/docs/secure_token

Unfortunately, my generated stoken isn't valid and I can't find a way to check why it doesn't work. There is a working Java example (STokenUtils.java), but I find myself unable to translate it to PHP.

public static function generateSecurityToken($secretKey){
    $stoken = array(
        'session_id' => session_id(),
        'ts_ms' => round(microtime(true)*1000)
    );
    $secretKey = self::pkcs5_pad(hash('sha1', $secretKey), 16);
    $stoken_json = json_encode($stoken);
    $stoken_crypt = self::encrypt(self::pkcs5_pad($stoken_json, 16), $secretKey);
    return $stoken_crypt;
}

public static function encrypt($sStr, $sKey) {
    return base64_encode(
        mcrypt_encrypt(
            MCRYPT_RIJNDAEL_128, 
            base64_decode($sKey),
            $sStr,
            MCRYPT_MODE_ECB
        )
    );
}

public static function pkcs5_pad ($text, $blocksize) { 
    $pad = $blocksize - (strlen($text) % $blocksize); 
    return $text . str_repeat(chr($pad), $pad); 
}

Can anybody provide a working PHP example or point out any obvious mistakes in my code?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

There are a number of problems in your code. First, your $secretKey value is computed as a padded SHA1 hash when the implementation requires the first sixteen bytes of the SHA1 hash.

$secretKey = substr(hash('sha1', $secretKey, true), 0, 16);

Second, you are trying to perform a base64 decode of the secret key, which is not valid here. The second argument to mcrypt_encrypt() should be $sKey, not base64_decode($sKey).

Finally, as explained in x77686d's answer, you should be using an "URL-safe" base64. That is a variation of base64 that is unpadded and does not use the + or / characters. Instead, the - and _ characters are used in their places.

ReCaptcha's secure tokens are a bit of a pain, honestly. They are insecure and the algorithm is undocumented. I've been in the same position as you and needed an implementation, so I wrote one and published it on Packagist as "slushie/recaptcha-secure-token". I'd recommend using it and/or contributing, if only because of the lack of alternative implementations of this algorithm.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...