pythonnode.jsencryptioncryptography3des

3DES crypto on Python produces different result from Nodejs/Java


Im bulding a checkout that need creditcard 3DES Crypto, but I getting differente result on Python and NodeJs.

Python code: (im using pycryptodome package)

import binascii
import base64
from Crypto.Cipher import DES3
import json

iv = '04njBuE3/dc='
iv = base64.b64decode(iv)
key = 'DpzDLcvVCHdVoRqE/NuIHs0QJ0xFdH2p'
key = base64.b64decode(key)
data = {'CartaoNumero': '0000000000000000',
'CartaoMesAno':'00/0000',
'CartaoSeg': '000',
'CartaoNome':'Teste Teste',
'IdentFatura':'Teste',
'Valor':'1000',
'NomeCliente':'Teste Teste',
'EmailCliente':'teste@teste.com',
'CpfCliente':'11122233344'}
data = json.dumps(data)
data = base64.b64encode(data.encode('utf-8'))
#print (data)

def card_encrypt(iv,key, data):
    desT = DES3.new(key, DES3.MODE_CBC, IV=iv)
    desT_key = desT.encrypt(data)
    desT_key = base64.b64encode(desT_key)
    return (desT_key)

Result: b'+TSfdiGmLAir8RVEze4yr72d3Sm5RBkDBwLYhpv1NKIIfVM+AnIhoSArFzV5am7qOdaFO0Ob4KSS8vXRYnBAO1xyk9MEoNc93uf/53cCMVHbZ8FUx14Vilx3Mg8+kbSMsASki5Dn+hlKE0ElFC/nyiWoOJvkWmtndoL+EEb4rkFil0zg637YXFE7f0yTOWhz97G6CEb4mvegCPpizuVdh2sBQQFDsJMEQE1kGeY2gDiDADwRQiMTrznhWFn3H6SylMxjQaNJTxu820BNitefMgcwAUTUJSrZt6DyuJ59e7772DK2jLubpK8/8xNolKalcjYMx106T7jOxDoPWZEoIe7YSGn9+Z3IGe5R7YFQJVLJUJ3SzlwWLptr3ZbMRnDCh2rB4FbTsM4igic4ZUQjS3DUzUVpT5URQyGjJK9+434ivMehknko4x+1owaEgcLGsPT9zBADlKFQ+OE8JqOhwJ5IztyoWeOmBVPZsOQdYvo='

Nodejs code:

var secretKey = 'DpzDLcvVCHdVoRqE/NuIHs0QJ0xFdH2p'
 var secretIV = '04njBuE3/dc='
 var dataOfCard = {'CartaoNumero': '0000000000000000',
'CartaoMesAno':'00/0000',
'CartaoSeg': '000',
'CartaoNome':'Teste Teste',
'IdentFatura':'Teste',
'Valor':'1000',
'NomeCliente':'Teste Teste',
'EmailCliente':'teste@teste.com',
'CpfCliente':'11122233344'}

const crypto = require('crypto');
 
async function encryptCardData(dataOfCard, secretKey, secretIV) {
    try {
        const des3_key = new Buffer.from(secretKey, "base64");
        console.log(des3_key)
        const des3_iv = new Buffer.from(secretIV, "base64");
        console.log(des3_iv)
        const cardString = JSON.stringify(dataOfCard);
        console.log(cardString)
      
        const cipher = crypto.createCipheriv('des-ede3-cbc', des3_key, des3_iv);

        const encrypted = cipher.update(cardString, 'utf8', 'base64');
    
        return encrypted + cipher.final('base64');        
    } catch (error) {
        console.error("Error:", error.message);
        throw error;
    }
}

encryptCardData(dataOfCard, secretKey, secretIV)

Result: '7pkXCZCKIDY1ueGwkfLk5W5AnDw2iP4jiZ5YHUBRMd56eDhVyZvnJ6EG+mh/wmHl3ljrJ+sfDMgAbpOgljRRQb4pOc1LQKHdkgcl3ZWmlvmqv8mGKdGaZYTgXnQ9pZGwoUQJAcuQgOCYWD5wMvIA6g4zd8O1iy/IsXWkBEzCkQA3x6NIkwrCNdftogu3JZlbmOIj90flo8t+J2X89rXzQmWKw6uCWrzzfGQvmvqqNf7ecDduTtCXee3WCdvcC3Ar7TbVpSv+NenoK+Oh+Tkj6Y8h4t6YAexyE8HxQ1GqCqFlMAzdCa2TtA=='

The NodeJS is generating the correct result. What I need to correct on Python model?


Solution

  • The Python code differs from the NodeJS code for the following reasons:

    With that:

    ciphertext = card_encrypt(iv,key, dataPadded)
    print (ciphertext)
    

    returns the ciphertext:

    b'7pkXCZCKIDY1ueGwkfLk5W5AnDw2iP4jiZ5YHUBRMd56eDhVyZvnJ6EG+mh/wmHl3ljrJ+sfDMgAbpOgljRRQb4pOc1LQKHdkgcl3ZWmlvmqv8mGKdGaZYTgXnQ9pZGwoUQJAcuQgOCYWD5wMvIA6g4zd8O1iy/IsXWkBEzCkQA3x6NIkwrCNdftogu3JZlbmOIj90flo8t+J2X89rXzQmWKw6uCWrzzfGQvmvqqNf7ecDduTtCXee3WCdvcC3Ar7TbVpSv+NenoK+Oh+Tkj6Y8h4t6YAexyE8HxQ1GqCqFlMAzdCa2TtA=='
    

    which matches the ciphertext of the NodeJS code.

    Please note that 3DES is deprecated and should be replaced by e.g. the more modern and performant AES, s. here. Apart from that, the use of a static IV is generally insecure, s here.