0

I have Java based Web API which receives AES encrypt user credentials and let the user get the session token. This is working fine with AES encryption on client side with CryptoJS. But the same throws bad padding exception while trying to access this API from Python.

In Java I've used PKCS5Padding padding. I have tried this with NoPadding as well, but in that case the de-crypted text is simply empty. Also, when trying with NoPadding, CryptoJS code is not working properly. As, this API should work for any client side program (Later I'm planning to expand this to PHP, .Net and R as well), I want to have a common, working mechnism for encryption of passwords thru AES. I'm pretty new to python and I have tried various programs provided in stack overflow as well as in other blogs on this subject.

Here is the java part

public String decrypto(String cipherText, String secret) {
        byte[] cipherData = java.util.Base64.getDecoder().decode(cipherText);
        byte[] saltData = Arrays.copyOfRange(cipherData, 8, 16);
        String decryptedText = null;
        try {
            MessageDigest md5 = MessageDigest.getInstance("MD5");

            final byte[][] keyAndIV = GenerateKeyAndIV(32, 16, 1, saltData, secret.getBytes(StandardCharsets.UTF_8),
                    md5);
            SecretKeySpec key = new SecretKeySpec(keyAndIV[0], "AES");
            IvParameterSpec iv = new IvParameterSpec(keyAndIV[1]);

            byte[] encrypted = Arrays.copyOfRange(cipherData, 16, cipherData.length);
            Cipher aesCBC = Cipher.getInstance("AES/CBC/PKCS5Padding");
            aesCBC.init(Cipher.DECRYPT_MODE, key, iv);
            byte[] decryptedData = aesCBC.doFinal(encrypted);
            decryptedText = new String(decryptedData, StandardCharsets.UTF_8);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return decryptedText;
    }

And this line send the encrypted password from CrptoJS without any issues which gets de-crypted properly in Java

encKey = CryptoJS.AES.encrypt(this.logingrp.value['loginpass'], this.localPublicKey).toString();
      this.localLogin(encKey);

LocalLogin is an AJAX function to call the API

Python code is below. I'm using Pycryptodome

import requests, json
import base64

from Crypto.Cipher import AES
from Crypto.Util import Padding
from Crypto import Random
from urllib.parse import urlencode
from urllib.request import Request, urlopen
from hashlib import sha256



BS = 16
pad = lambda s: bytes(s + (BS - len(s) % BS) * chr(BS - len(s) % BS), 'utf-8')
unpad = lambda s : s[0:-ord(s[-1:])]

class AESCipher:

    def __init__( self, key ):
        self.key = bytes(key, 'utf-8')

    def encrypt( self, raw ):
        raw = pad(raw)
        iv = Random.new().read( AES.block_size )
        cipher = AES.new(self.key, AES.MODE_CBC )
        return base64.b64encode( iv + cipher.encrypt( raw ) )

    def decrypt( self, enc ):
        enc = base64.b64decode(enc)
        iv = enc[:16]
        cipher = AES.new(self.key, AES.MODE_CBC, iv )
        return unpad(cipher.decrypt( enc[16:] )).decode('utf8')

header = {"Content-type": "application/json",
          "Authorization": "Bearer CT9797"
          } 

password = 'stone@123'
keyphrase = '9DA538D0HMQXQRGI';

cipher = AESCipher(keyphrase)
encrypted = cipher.encrypt(password).decode('utf8')


payload={'userId':'CT9797','userData':encrypted,'encKey':''}
response_decoded_json = requests.post(url=_base_URL+'eLogin', data=json.dumps(payload), headers=header)
print(response_decoded_json.status_code)

The below exception occurs while trying the above program on java side

javax.crypto.BadPaddingException: Given final block not properly padded. Such issues can arise if a bad key is used during decryption.
    at com.sun.crypto.provider.CipherCore.unpad(CipherCore.java:975)
    at com.sun.crypto.provider.CipherCore.fillOutputBuffer(CipherCore.java:10

Appreciate your time in reading and helping me out.

6
  • So it's working in Javascript with cryptojs but not working in either Java or python? Commented Aug 12, 2019 at 14:31
  • 1
    Why not just use TLS/SSL to securely communicate with the server and skip all the ad-hoc crypto? Commented Aug 12, 2019 at 14:55
  • @James - It works from Java too. Requests can be from anything (Like Java, PHP, .NET, Python and JS). The destination is Java based Rest API. Its an API based trading application and can not use anything else as its mandated by exchange. Commented Aug 12, 2019 at 15:24
  • It looks like a lot of important code is in GenerateKeyAndIV(...) which is missing. Commented Aug 12, 2019 at 15:29
  • 1
    When you encrypt on one system and decrypt on another you cannot rely on system defaults as they are likely to be different, so the decryption will fail. Explicitly specify everything: encryption mode, key, IV, character encoding etc. To troubleshoot, compare everything bit-by-bit to ensure that they match on both systems. Commented Aug 13, 2019 at 8:59

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.