我正在研究一个跨语言项目,将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个字符。