我正在做一个跨语言项目,用php包装一个ruby/sinatra api,供另一个团队使用。api公开的信息都不敏感,但我们希望它不容易被猜测url的临时观察者访问。

    private function generateSliceIDToken($key){
    $currentEpoch = time();
    $ivSize = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
    $iv = mcrypt_create_iv($ivSize, MCRYPT_RAND);
    $encryptedBytes = mcrypt_encrypt(
        MCRYPT_RIJNDAEL_128,
        $key,
        $currentEpoch.**Passcode**,
        MCRYPT_MODE_CBC, $iv
    );
    $ivAndEncryptedBytes = $iv . $encryptedBytes;

    return urlencode(urlencode(base64_encode($ivAndEncryptedBytes)));

上面的代码使用mcrypt的rijndael实现对密码和时间戳进行加密,并对其进行编码以发送到ruby api
if identifier.validate_token Base64.decode64(URI.unescape( URI.unescape(params[:token])))

西纳特拉抓住它解码
def validate_token(token)
  cipher = OpenSSL::Cipher::AES.new(128, 'CBC')
  cipher.decrypt
  cipher.key = **key**
  cipher.iv = token[0,16]

  plain = cipher.update(token[16..-1]) + cipher.final
  return plain[10,8] == **Passcode**
end

把它传出去解密
问题是,解密失败,出现“错误解密”错误
我相信mcrypt的rijndael和cipher的aes是兼容的,但是这个假设是错误的吗?我能得到的任何帮助都会很有帮助的。

最佳答案

我相信mcrypt的rijndael和cipher的aes是兼容的,但是这个假设是错误的吗?
您需要稍微调整正在编码的数据,使其与aes兼容。数据必须右填充,字符和数量取决于其当前宽度:

$encode = $currentEpoch.'**Passcode**';
$len = strlen($encode);
$pad = 16 - ($len % 16);
$encode .= str_repeat(chr($pad), $pad);

还要记住$key正好有16个字符长。如果更短,ruby抛出ciphererror,而php则用空字节填充键。如果长度较长,ruby只使用前16个字符,而php会再次填充,并使用后16个字符。

关于php - 用PHP加密(mcrypt),用Ruby解密(OpenSSL::Cipher),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/21485437/

10-11 03:14