3

I can encrypt/decrypt with Python OR with JavaScript but passing encrypted data generated by Python to my JavaScript code fails.

The base64 encoding/decoding works across languages so that base encoding on Python and decoding on JavaScript retrieves the original encrypted string.

Outside of test functions I am not using Python decrypt or JavaScript encrypt but they are here for completeness as some readers miss text saying they exist.

In Python 2:

import base64
from pyaes import AESModeOfOperationCTR
SECRET_KEY = "This_key_for_demo_purposes_only!"

def encrypt(raw_data, key=SECRET_KEY):
    aes = AESModeOfOperationCTR(key)
    encrypted_data = aes.encrypt(raw_data)
    base64_encrypted_data = base64.b64encode(encrypted_data)
    return base64_encrypted_data

def decrypt(base64_encrypted_data, key=SECRET_KEY):
encrypted_data = base64.b64decode(base64_encrypted_data)
aes = AESModeOfOperationCTR(key)
decrypted = aes.decrypt(encrypted_data)
return decrypted

In Javascript (running Server-side, on Parse.com Cloud Code):

var Buffer = require('buffer').Buffer;
var Crypto = require('crypto');

encrypt: function(raw) {
    var cryptoAlgorithm = "aes-256-ctr";
    var key = "This_key_for_demo_purposes_only!"
    var cipher = Crypto.createCipher(cryptoAlgorithm, key);

    var encrypted = cipher.update(raw, 'utf8', 'binary');
    encrypted += cipher.final('binary');

    var base = toBase64(encrypted);
    return base;
},

decrypt: function(base64raw) {
    var raw = fromBase64(base64raw);

    var cryptoAlgorithm = "aes-256-ctr";
    var key = "This_key_for_demo_purposes_only!"
    var decipher = Crypto.createDecipher(cryptoAlgorithm, key);

    var decrypted = decipher.update(raw, 'binary', 'utf8');
    decrypted += decipher.final('utf8');
    return decrypted;
}

The output of the JavaScript function decrypt() is nonsense. Where is the mismatch?

The output of the two encrypt functions does not match when given the same raw string.

My guess: in the JavaScript I shouldn't be using 'binary'. The JavaScript decrypt() function chokes if specify 'hex' for the data generated from the Python side.

Carl
  • 2,896
  • 2
  • 32
  • 50
  • 1
    Try it and see. But you don't gain any security; the client can look at the JS code, and thus the encryption key. – Colonel Thirty Two Oct 28 '15 at 12:32
  • 1
    Do have a working "All Javascript" version? I would also do an "all python" version as well. I would start there, perhaps compare the binary encrypted buffers? Perhaps compare the base64 outputs? Maybe they have differences in Base64 implementation? I seem to remember base64 issues with python - but that was too long ago for me to recall the details. – akaphenom Oct 28 '15 at 12:37
  • @ColonelThirtyTwo As I mention, in passing, the JavaScript is server-side and no no available to clients. – Carl Oct 28 '15 at 12:37
  • @akaphenom my thought as I typed the question :) I'll add a JavaScript encrypt() function so I can test as I have already done on the Python side. – Carl Oct 28 '15 at 12:39
  • @akaphenom I'm not sure how much I would clean by comparing the binary encrypted buffers - I'm hoping someone has coded this (or at least one side) before. – Carl Oct 28 '15 at 12:40
  • to be clear on both sides code the encrypt and decrypt to make sure they work with themselves. Once you are confident there, look at the output of each of the encrypt functions - are they the same? At the binary level? At the base64 level? We don't know enough as to where the problem lies. Perhaps someone has tried exactly this before. I seem to remember having issues with JS and Python with Base64 - but it was a long time ago and I have no recollection of how I resolved it. But in this case you can route out some more information... – akaphenom Oct 28 '15 at 12:50
  • @akaphenom Yes, I've stated in the question that I've implemented both sides in the Python side. But I've been lazy and not done so for the JavaScript side! Lesson learned. – Carl Oct 28 '15 at 12:54
  • @akaphenom A problem lies on the JavaScript side - I'll delete this question as it is now redundant! – Carl Oct 28 '15 at 12:54
  • @akaphenom with more investigation my question is republished! :) – Carl Oct 28 '15 at 17:29
  • 1
    You need the encryption to be done with every parameter the same. In your example the key is hashed in different way in the libraries. `Note: createCipher derives keys with the OpenSSL function EVP_BytesToKey with the digest algorithm set to MD5, one iteration, and no salt.` - Edit: From what I see `pyaes` (prefer the module crypto btw) does not hash the key. – Cyrbil Oct 28 '15 at 18:41
  • I needed to step away - I am gla you made progress though – akaphenom Oct 28 '15 at 18:46
  • 1
    See: http://stackoverflow.com/a/24503184/956660 as it is strongly related to your problem – Cyrbil Oct 28 '15 at 19:01
  • Thanks @cyrbil. That makes sense. – Carl Oct 28 '15 at 22:05
  • I've switched to PyCrypto which is provided by Google App Engine. I had hesitated in using this as we develop across Macs and Windows and local installations on Windows involves some... hoops. – Carl Oct 29 '15 at 10:02

0 Answers0