Decrypting TLS_DHE_WITH_AES_256_CBC_SHA256

40 views Asked by At

I am trying to delve into some cryptography and am trying to decrypt a base64 encoded encrypted string using js. The actual string has been encrypted using TLS_DHE_WITH_AES_256_CBC_SHA256 cipher. I'm currently trying a js script to do the decryption.

const crypto = require("crypto");
const Algorithm = "aes-256-cbc";

const iv_length = 16;
const cipher_text = 'C180IC8anSEorqQU509H21mjifrgooMzVaT4IzgFAfij+BNPvp2koMt4N2JH3exGOkPVIxa/+eE16nP4sHGeLQ==';

const g = 149;
const p = 197;
const DHE = 56;

// Usage
const KEY = calculateKey(g, p, DHE);
console.log("Derived Key:", KEY.toString('hex'));

// Ensure the key is the correct length (32 bytes for AES-256-CBC)
if (KEY.length !== 32) {
    console.error("Invalid key length. The key must be 32 bytes long.");
    process.exit(1);
}

const IV = Buffer.from(cipher_text, 'base64').slice(0, 16);

console.log("IV:", IV.toString('hex')); // Print the IV in hexadecimal format

const decrypted = decrypt(cipher_text, KEY, IV);
console.log("Decrypted:", decrypted);

function decrypt(cipherText, key, iv, inputEncoding = "base64", outputEncoding = "utf8") {
    const decipher = crypto.createDecipheriv(Algorithm, key, iv);
    const decrypted = decipher.update(cipherText, inputEncoding, outputEncoding) + decipher.final(outputEncoding);
    return decrypted;
}

// Function to calculate the key
function calculateKey(g, p, DHE) {
    const sharedSecret = BigInt(Math.pow(g, DHE) % p);
    const sharedSecretHex = sharedSecret.toString(16).padStart(64, '0');
    const key = crypto.createHash('sha256').update(Buffer.from(sharedSecretHex, 'hex')).digest();
    return key;
}

Unfortunately I'm not understanding what the following error is indicating where my issue is:

node:internal/crypto/cipher:199
  const ret = this[kHandle].final();
                            ^

Error: error:1C800064:Provider routines::bad decrypt
    at Decipheriv.final (node:internal/crypto/cipher:199:29)
    at decrypt (/test.js:36:93)
    at Object.<anonymous> (/test.js:25:19)
    at Module._compile (node:internal/modules/cjs/loader:1356:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1414:10)
    at Module.load (node:internal/modules/cjs/loader:1197:32)
    at Module._load (node:internal/modules/cjs/loader:1013:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:128:12)
    at node:internal/main/run_main_module:28:49 {
  library: 'Provider routines',
  reason: 'bad decrypt',
  code: 'ERR_OSSL_BAD_DECRYPT'
}

I've also tried python as well.

from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
import base64
import hashlib

# Constants
g = 149
p = 197
DHE = 56
cipher_text = "C180IC8anSEorqQU509H21mjifrgooMzVaT4IzgFAfij+BNPvp2koMt4N2JH3exGOkPVIxa/+eE16nP4sHGeLQ=="

# Step 1: Extract IV from the ciphertext
iv = base64.b64decode(cipher_text)[:16]

# Step 2: Calculate symmetric encryption key using Diffie-Hellman shared secret
#def calculate_key(g, p, DHE):
#    shared_secret = pow(g, DHE, p)
#    key = hashlib.sha256(str(shared_secret).encode()).digest()
#    return key
def calculate_key(g, p, DHE):
    shared_secret = pow(g, DHE, p)
    shared_secret_hex = format(shared_secret, '064x')  # Pad with leading zeros to ensure 64 characters
    key = hashlib.sha256(bytes.fromhex(shared_secret_hex)).digest()
    return key

key = calculate_key(g, p, DHE)

key_hex = key.hex()
print("Derived Key:", key_hex)

# Step 3: Decrypt the ciphertext using AES-256 in CBC mode
def decrypt_aes_cbc(cipher_text, key, iv):
    cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend())
    decryptor = cipher.decryptor()
    decrypted_text = decryptor.update(base64.b64decode(cipher_text)) + decryptor.finalize()
    return decrypted_text

decrypted_message = decrypt_aes_cbc(cipher_text, key, iv)

print("Decrypted message:", decrypted_message)
# List of encodings to try
encodings = [
    'utf-8', 'utf-16', 'utf-32', 'ascii', 'latin-1', 'windows-1252',
    'iso-8859-2', 'iso-8859-3', 'iso-8859-4', 'iso-8859-5', 'iso-8859-6',
    'iso-8859-7', 'iso-8859-8', 'iso-8859-9', 'iso-8859-10', 'iso-8859-13',
    'iso-8859-14', 'iso-8859-15', 'iso-8859-16', 'koi8-r', 'koi8-u',
    'macroman', 'maccyrillic', 'ibm855', 'ibm866', 'cp437', 'cp1250',
    'cp1251', 'cp1252', 'cp1253', 'cp1254', 'cp1255', 'cp1256', 'cp1257',
    'cp1258'
]

# Attempt to decode the decrypted message using each encoding
valid_decrypted_messages = []
for encoding in encodings:
    try:
        decrypted_message_text = decrypted_message.decode(encoding)
        valid_decrypted_messages.append((encoding, decrypted_message_text))
    except UnicodeDecodeError:
        continue  # Try the next encoding if decoding fails

if valid_decrypted_messages:
    print("Decrypted messages:")
    for encoding, message in valid_decrypted_messages:
        print(f"Encoding: {encoding}, Decrypted message: {message}")
else:
    print("Failed to decode the decrypted message.")

I have noticed that the keys produced between js and python differ but I don't know js or python well enough to identify the issue, I refer a lot to chatGPT when trying to learn and understand (obviously it helps that it produces code)

js derived key - 218cd422fe6a50299655006c5c9a13a4a06d5d815f4c929b876885dda1fd4652

py dervied key - fa282a9c595eea43e942f1678efbff1f4b821a6b27aef7df0ae71b9de53fc8ce

I do however get the same IVs:

js derived IV - 0b5f34202f1a9d2128aea414e74f47db

py derived IV - 0b5f34202f1a9d2128aea414e74f47db

Overall, is it actually possible to decrypt when only knowing the given constants?

0

There are 0 answers