Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I am sending data through insecure connection between Apache and Node.js servers. I need to encrypt data in PHP and decrypt in Node.js. I've spent 2 days trying to get it to work, however I only managed to get message signing to work, no encryption. I tried passing AES128-CBC, AES256-CBC, DES, AES128, AES256 as algorithms, however nothing worked well..

I tried this in PHP:

$data = json_encode(Array('mk' => $_SESSION['key'], 'algorithm' => 'SHA1', 'username' => $_SESSION['userid'], 'expires' => $expires));
$payload = openssl_encrypt($data, 'des', '716c26ef');
return base64_encode($payload);

And in Node.js:

var enc_json = new Buffer(response[1], 'base64');
var decipher = crypto.createDecipher('des', '716c26ef');
var json = decipher.update(enc_json).toString('ascii');
json += decipher.final('ascii');

And besides wrong decrypted data I get error such as these:

TypeError: error:0606508A:digital envelope routines:EVP_DecryptFinal_ex:data not multiple of block length

TypeError: error:0606506D:digital envelope routines:EVP_DecryptFinal_ex:wrong final block length

I need a simple encryption as data is not too sensitive (no password or user data), however data should only be read by the recipient. Key length can be anything, but procedure to encrypt/decrypt has to be as simple as possible, please no IVs.

share|improve this question
    
Why can't you use HTTPS? –  ThiefMaster Nov 12 '13 at 16:29
3  
Shouldn't you be returning base64_encode($payload);? –  Ben Fortune Nov 12 '13 at 16:29
    
@BenFortune I am.. I was editing variable names for the question. –  Xeos Nov 12 '13 at 16:30
    
@ThiefMaster there is third party in this: data goes to the client, where it can be stored for future use or be sent to Node.js server immediatly. –  Xeos Nov 12 '13 at 16:31
add comment

1 Answer

up vote 4 down vote accepted

When dealing with symmetric encryption like this, the first step is realize that it's probably going to be a huge pain in the rear - I've never, ever had it work right away, even when I was copy pasting my own code. This is mainly because encryption and decryption methods are, by design, utterly unforgiving and rarely give useful error messages. A single null character, carriage return, line feed, or dynamically converted type can silently blow the whole process up.

Knowing this, progress stepwise. I suggest the following:

First, get PHP alone working. Pass in sample text, encrypt it, immediately decrypt it, and compare it with strict equality to the original clear text variable. Are they perfectly the same? Output both, as well - are they the same type and appear perfectly unmolested? Watch out for non-printed characters - check the length and character encoding too!

Now, do the above with one more sample text that is 1 character more or less than the previous one. This debugs block size/zero-padding issues - it matters.

If that's working - and it rarely does right away, for hard to predict reasons, continue to Node.js.

In Node.js, do the same thing as you did in PHP, even if it seems like wasted effort - for extra reasons that will be obvious in a moment. Encrypt and decrypt, all together, in your Node.js. Does it work with all the same provisos given above?

Once that is done, here comes the 'fun' part: using the same encryption methods independently in Node.js and PHP, have them both output to you the 'final' ready-to-transmit cryptext that both produced.

If all is well, they should be perfectly, exactly the same. If they aren't, you have a problem with your encryption implementations and methods not being compatible between systems. Some setting is wrong or conflicting (perhaps with zero padding or a host of other possibilities, or IV, etc), or you need to try a different implementation.

If I had to guess blindly, I'd say there is an issue with the base64 encoding and decoding (it's most commonly what goes wrong). Things tend to get done twice, because it can be tricky to debug binary data types in web applications (through a browser). Sometimes things are being encoded twice but only decoded once, or one implementation will 'helpfully' encode/decode something automatically without being clear that's what it's doing, etc.

It's also possible it's a zero-padding implementation issue between Node and PHP, as suggested here: AES encrypt in Node.js Decrypt in PHP. Fail.

These last two issues are strongly suggested by your error codes. The encryption methods predict block sizes of precise length, and if they are off then that signals corruption of the data being passed to the functions - which happens if a single extra character slipped in, or if encoding is handled differently, etc.

If you step through each of the above one at a time, assuring yourself you can't rush and must check every painstaking tiny little step of the process, it should be much more clear where exactly things are going wrong, and then that can be troubleshooted.

share|improve this answer
1  
nice answer, very thorough –  nathan hayfield Nov 12 '13 at 17:00
    
This is probably better than giving the code listing. Plus after reading it, it seems like there is no 'answer' to solve my problem except more testing and debugging. Thank you very much. –  Xeos Nov 12 '13 at 18:00
    
You're very welcome! If you get to the bottom of it an update would be great - if nothing else I'd like to know if my intuition was close or if it was something completely different. It's really fun when it works, but symmetric encryption can really take a bite out of your day/week/month, even when you aren't crossing systems like this. Naturally, feel free to ask another question (cross-posting a link here for "follow up questions" is handy) with more code if you narrow it down a bit. –  BrianDHall Nov 12 '13 at 18:20
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.