我正在做一个跨语言项目,用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/