Solved

AES-256-CBC Encryption between Ruby and PHP

Posted on 2015-01-15
5
462 Views
Last Modified: 2015-01-16
Dear Experts:

I'm starting to find myself guessing at this issue, so it's time to call in the experts!

I want to start by saying that prior to posting this question, I have researched several potential solutions, including a couple from this site. However, none have them have solved the issue and/or I am not applying the potential solution properly.

The ultimate solution will allow passing encrypted data back and forth between a Ruby based system and a PHP  based system. Encrypting and decrypting on both sides using AES-256-CBC. Here are the details:

I have received a key, initialization vector (iv), and an encrypted test phrase - "Eureka! We have a bingo!" This was initiated from the Ruby side and passed to me (the PHP side).

Here are the values:

base64 url safe encoded key:
"f2da64041ad7dbabaf8030ff6cbc65c90f9f376080228e3f5498fdb8d5af0b37"

decoded base64 url safe key:
"\x7FgZ\xEB\x8D8\xD5\xA7{u\xB6\x9Bi\xFF4\xDFG\xDF\xE9\xC6\xDC\xEB\x97=\xD1\xFF_\xDF\xBE\xB4\xF3M\xB6\xF1\xED\xDF\xE7\x8F|}\xD6\xFCw\x96\x9F\xD1\xBD\xFB"

base64 url safe encoded Initialization Vector (iv):
“c124a4c542ed25380ce4f46ee43c265d”

decoded base64 url safe initialization vector (iv):
"s]\xB8k\x879\xE3g\x9D\xDB\x9D\xFC\xD1\xC7\xB8\x7F\x8E\x9E{\x8D\xDC\xDB\xAE]"

encrypted value (Eureka! We have a bingo!):
aPpg0SsMC_xcrw4zZpZ0modgxqcKo35mCAslSMxL1zA=

Regarding the "base64 url safe". The Ruby developer pointed me to (credit to Justin Kelly):
http://blog.justin.kelly.org.au/simple-base64-encodedecode-url-safe-functions/
to pass the encoded key/iv through. I'm not sure if that is doing what it needs to do or not.

The Ruby developer was gracious enough to give me the code sequence he is using to encrypt the value before passing to me:

def self.encrypt(plaintext, key = nil, iv = nil)
 
# if there is anything to encrypt
    if plaintext.present?
      # assign the var for key and iv from the Base64 encoded copies stored on the server.
      key ||= AppConfig.api['key’]
      iv ||= AppConfig.api['iv’]
      # create a new instance of a Cipher object using the AES-256-CBC algorithm.
      aes = OpenSSL::Cipher::Cipher.new('AES-256-CBC’)
      aes.encrypt
      # assign the decoded Base64 key and iv to the cipher object.
      aes.key = Base64.urlsafe_decode64(key)
      aes.iv = Base64.urlsafe_decode64(iv)
      # add my encrypted texts to the cipher object.  final is now an encrypted string.
      final = aes.update(plaintext) + aes.final
      # Base 64 encode final so that it is cleaner when sending back and forth.
      Base64.urlsafe_encode64(final)
    else
      return nil
    end
  end

Open in new window


I was going to list out some of the different code attempts I have made and realized it was pointless, since none of them worked and is why I am here. I can tell you I have tried different combinations of (PHP) pack(), hex2bin and the like, with results varying from absolute garbage to errors - "Size of key is too large for this algorithm", for example.

I will include what I have as the "core" of my attempts:

<?php

$org_64_key = 'f2da64041ad7dbabaf8030ff6cbc65c90f9f376080228e3f5498fdb8d5af0b37';
$org_64_iv  = 'c124a4c542ed25380ce4f46ee43c265d';

//encrypted value (Eureka! We have a bingo!):
$cipher_value = 'aPpg0SsMC_xcrw4zZpZ0modgxqcKo35mCAslSMxL1zA=';

$key    = base64_url_decode($org_64_key);
$iv     = base64_url_decode($org_64_iv);
$target = base64_url_decode($cipher_value);

$result = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $target, MCRYPT_MODE_CBC, $iv );

//credit to Justin Kelly for following two functions
function base64_url_encode($input) {
    return strtr(base64_encode($input), '+/=', '-_,');
}

function base64_url_decode($input) {
    return base64_decode(strtr($input, '-_,', '+/='));
}

Open in new window


I tried to keep this on the line between "get to the point" and "need more info", so please let me know if I can offer any more insight. Your help is greatly appreciated.

Thanks in advance,
--Mike
0
Comment
Question by:mwheeler_fsd
  • 3
  • 2
5 Comments
 
LVL 82

Accepted Solution

by:
Dave Baldwin earned 500 total points
ID: 40552474
Instead of trying to decode first, you should try to encode/encrypt using all of the same data on both systems.  then compare the 'results' from both systems.  Between PHP and ASP.NET, there is apparently a difference in the way that block padding is or isn't done.  I don't have a page reference for you on that.  Suffice it to say that there are differences in the implementations of this 'standard' method.
0
 

Author Comment

by:mwheeler_fsd
ID: 40552746
Hello Dave,

Thank you for your response. That is an excellent suggestion. In the middle of these situations its easy to overlook what, in most cases, should be obvious. Call it "KISS" or Occam's Razor, breaking this down to the basic steps make's total sense. I will make a request to the Ruby Programmer to send me the cipher unencumbered.

On a side note, I had to chuckle a bit at your last sentence. In my quest to solve this issue, I came across this on Stack Overflow -
"... and , you know, the good thing about standards is, that there are so many to chose from. " with credit to Eugen Rieck at this link:
http://stackoverflow.com/questions/9186541/why-does-something-encrypted-in-php-not-match-the-same-string-encrypted-in-ruby

Story of our lives...

Dave - I'm going to leave this open over night and, unless somebody provides a lock, stock, and barrel solution/explanation, will award you the points.

Thank you!
--Mike
0
 
LVL 82

Expert Comment

by:Dave Baldwin
ID: 40552773
Go back to at least 1981 and some famous names for that quote.  http://c2.com/cgi/wiki?AndrewTanenbaum
0
 

Author Closing Comment

by:mwheeler_fsd
ID: 40554253
Thank you Dave. Your suggestion to break it down is probably the best advice on this type of an issue. This situation could have one thing masking another, and another, etc. I am going to follow your suggestion and work the problem one step at a time and see where it breaks.
Thank you!
--Mike

**Note - if I discover anything helpful regarding the issue, I will post back.
0
 
LVL 82

Expert Comment

by:Dave Baldwin
ID: 40554302
Thanks for the points.!
0

Featured Post

Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

Join & Write a Comment

Password hashing is better than message digests or encryption, and you should be using it instead of message digests or encryption.  Find out why and how in this article, which supplements the original article on PHP Client Registration, Login, Logo…
Nothing in an HTTP request can be trusted, including HTTP headers and form data.  A form token is a tool that can be used to guard against request forgeries (CSRF).  This article shows an improved approach to form tokens, making it more difficult to…
Explain concepts important to validation of email addresses with regular expressions. Applies to most languages/tools that uses regular expressions. Consider email address RFCs: Look at HTML5 form input element (with type=email) regex pattern: T…
The viewer will learn how to create a basic form using some HTML5 and PHP for later processing. Set up your basic HTML file. Open your form tag and set the method and action attributes.: (CODE) Set up your first few inputs one for the name and …

758 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

17 Experts available now in Live!

Get 1:1 Help Now