tambakoo
tambakoo

Reputation: 363

Output difference with successive RSA encryption and base64 encoding in php and ruby

My goal is to integrate an API service which wants me to generate a signature by following these steps.

  1. Retrieve your clientId.
  2. Append this with CURRENT UNIX timestamp separated by a period (.)
  3. Encrypt this data using RSA encrypt with Public key you received – this is the signature.
  4. Pass this signature through the header X-Cf-Signature.

Step 3 is the signature generation step. In my ruby application this is how I have implemented the steps.

def dynamic_signature
 raw_data = "#{client_id}.#{Time.now.to_i}"
 filepath = "public_key.pem"
 public_key = OpenSSL::PKey::RSA.new File.read(filepath)
 Base64.strict_encode64(public_key.public_encrypt(raw_data)).encode("UTF-8")
end

But the API service rejects this signature. They have code snippet examples in php so tried this process in php with the following code. I have used the variables from the ruby code above for representation.

<?php

$plainData = <raw_data>;
$publicKey = <public_key.to_s>;
openssl_public_encrypt($plainData, $encrypted, $publicKey, OPENSSL_PKCS1_OAEP_PADDING);
echo base64_encode($encrypted);

?>

This signature gets accepted by the API service. I did some manual inspection and both base64 outputs were obviously different. In ruby I have tried with and without enforcing an encode("UTF-8").

Interestingly the following statement returns true, no matter if I do a strict_encode64 or encode64 or append encode("UTF-8") at the end.

base64_generated_in_ruby.bytes == base64_generated_in_php.bytes

I did this equality check by copy pasting the base64 encoded strings in the ruby console.

I suspect base64 encoding is working differently for escape characters in both these languages. Any help is appreciated.

Edit 1: Adding an example.

  1. RSA encrypted string that I'm encoding in base64.
"g\xF3\f%\xA2\xC0(\xCBYAw\x80\xA5 c\x9DR\xC7r\xFE\xAF \xADJ\xCBy\x8D\xC8kd#\xD3\x04L(\x9B\xC0V\n\xCD\xFF\xD4\rj\xF0\x12\x86\xEC5\xC6ev\xCEUD\x9B\xA2\xAD\x9F{\xC8\xF5\x8A\x00->\xB5\xA4f\x05\x9F\xE1\x81u\xB5\x87\xD4\xD7\xA7\xCC\xE0:\xC9\xF3,\x8D(\x10\xEC\\\xE8'\r\xFA\x14\x82\x8A\xCF_^\xAA\x94\x17\x15\xD0Qw\x18\xDB\xE7\t\xEEy\x9E04\x94\xDE\xFB\xF6\xEB:\xDF\x90\xDER\xEB\xF1c\xF2\x98\x00\x9CM\x16\xA6{\x12\xA8\xA2\xE7\x00\x89\xDE\xB4\x9C\xB1\xE9\x81\x9D\xB4\xC8~q\x8A\xBDu#\xD2\xD2\x19T\xE4H\x7F\x0E\xDF\xECV\x8E\rF\xF7\x12m\x1C\xFE-\xC2gO\x90\xEDp\x88\x1A\x1D\t4\xC2\r!\xD5Y\xC3\xBB\xB8*B%\x00\xDF\xE2s\x8A\x19j\xFB\xEBy\xD7\xD6\xF5\x06\x99\xEE\xEA\xE4\xA3\x83\x97\xDB\x95\xA2o\x86\x97c\xA8w\xAAb\xEF\x00e\xC4\b\xD3\xEB\xFB\x86\xF4\xE2!\xF1{\xA5\x80\xD7\xC4\xC4\x01,\xBFj-"
  1. Using ruby as Base64.strict_encode64(rsa_string)
"Z/MMJaLAKMtZQXeApSBjnVLHcv6vIK1Ky3mNyGtkI9METCibwFYKzf/UDWrwEobsNcZlds5VRJuirZ97yPWKAC0+taRmBZ/hgXW1h9TXp8zgOsnzLI0oEOxc6CcN+hSCis9fXqqUFxXQUXcY2+cJ7nmeMDSU3vv26zrfkN5S6/Fj8pgAnE0WpnsSqKLnAInetJyx6YGdtMh+cYq9dSPS0hlU5Eh/Dt/sVo4NRvcSbRz+LcJnT5DtcIgaHQk0wg0h1VnDu7gqQiUA3+Jzihlq++t519b1Bpnu6uSjg5fblaJvhpdjqHeqYu8AZcQI0+v7hvTiIfF7pYDXxMQBLL9qLQ=="
  1. Using php as base64_encode($rsa_string)
"Z/MMJaLAKMtZQXeApSBjnVLHcv6vIK1Ky3mNyGtkI9METCibwFYKzf/UDWrwEobsNcZlds5VRJuirZ97yPWKAC0+taRmBZ/hgXW1h9TXp8zgOsnzLI0oEOxc6CcN+hSCis9fXqqUFxXQUXcY2+cJ7nmeMDSU3vv26zrfkN5S6/Fj8pgAnE0WpnsSqKLnAInetJyx6YGdtMh+cYq9dSPS0hlU5Eh/Dt/sVo4NRvcSbRz+LcJnT5DtcIgaHQk0wg0h1VnDu7gqQiUA3+Jzihlq++t519b1Bpnu6uSjg5fblaJvhpdjqHeqYu8AZcRcYtPr+4b04iHxe6WA18TEASy/ai0="

Upvotes: 0

Views: 458

Answers (1)

tambakoo
tambakoo

Reputation: 363

The ruby public_encrypt method does not include a padding argument by default. Use public_encrypt(raw_data, OpenSSL::PKey::RSA::PKCS1_OAEP_PADDING) to add the relevant padding argument. In the supplied php code submitted padding is explicitly mentioned.

Upvotes: 0

Related Questions