在PHP(MCRYPT)中加密,在Ruby(Openssl :: Cipher)中解密



我正在研究一个跨语言项目,将PHP中的Ruby/Sinatra API包裹在另一个团队中,将在PHP中使用。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])))

Sinatra抓住它并解码

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和密码的AES兼容,但是这个假设不正确吗?我可以得到的任何帮助,这将最有帮助。

我被认为是麦克里普特的rijndael和密码AES是兼容的,但是这个假设不正确?

您需要稍微调整数据,以使其兼容。数据必须正确填充,具体和数量取决于其当前宽度:

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

还记得将$key恰好16个字符长。如果较短,Ruby会抛出CipherError,而PHP则使用null字节填充键。如果较长的话,Ruby仅使用第一个16个字符,但是PHP再次使用,并使用了最后16个字符。

最新更新