TransWikia.com

The .json printed data doesn't respect the dictionary order in Python

Stack Overflow Asked on December 16, 2021

I am analyzing some real-time captured data in order to parse some TLS Client Hello information.
After capturing and analyzing the data, I print out the information in an output.txt file as a .json format by using a dictionary in python.

My question is about the .json output in the output.txt file. The data is not being printed in order, which means it doesn’t respect the order of the data in the dictionary (output_dictionary.py).

The dictionary that I am using for the .json output:

output_dictionary.py

HANDSHAKE = {
    "Client_Hello" : {
        'Length': 'unknown',
        'Version': 'unknown', 
        'Random': 'unknown', 
        'Session ID': 'unknown', 
        'Session ID Length': 'unknown', 
        'Cipher Suites Length': 'unknown',
        'Cipher Suites': 'unknown', 
        'Compression Method': 'unknown'
        }
    }

The function that fills the dictionary in order to print it as a .json with json_read("output.txt") call:

def parse_client_hello(handshake):
    if isinstance(handshake.data, dpkt.ssl.TLSClientHello):
        client = dpkt.ssl.TLSClientHello(str(handshake.data))
        **HANDSHAKE["Client_Hello"]['Length'] = len(client)**
        **HANDSHAKE["Client_Hello"]['Version'] = tls_dictionary('tls_version',client.version)**
        
        **HANDSHAKE["Client_Hello"]['Random'] = hexlify(client.random)**
        
        session_id, pointer = parse(client.data, 1)
        **HANDSHAKE["Client_Hello"]['Session ID'] = hexlify(session_id)**
        **HANDSHAKE["Client_Hello"]['Session ID Length'] = len(session_id)**
        
        ciphersuites, pointer1 = parse(client.data[pointer:], 2)
        ciphersuites, pretty_cipher_suites = parse_ciphers_compressions(ciphersuites, 'cipher_suites')
        **HANDSHAKE["Client_Hello"]['Cipher Suites Length'] = len(ciphersuites)**
        **HANDSHAKE["Client_Hello"]['Cipher Suites'] = pretty_cipher_suites**
        
        pointer += pointer1 
        compression_methods, pointer1 = parse(client.data[pointer:], 1)
        compression_methods, pretty_compressions = parse_ciphers_compressions(compression_methods,
            'compression_methods')
        **HANDSHAKE["Client_Hello"]['Compression Method'] = pretty_compressions**

        json_read("output.txt")

The json.read function that converts the dictionary into a .json format:

def json_read(filename):
    with open(filename, "a") as f:
        json.dump(HANDSHAKE, f, indent = 4)
    

How the data is printed in the ouput.txt file as a .json format:

{
    "Client_Hello": {
        "Session ID Length": 32, 
        "Length": 236, 
        "Version": "TLS 1.2", 
        "Handshake Type": "Client Hello : 1", 
        "Compression Method": [
            "null"
        ], 
        "Session ID": "3eadfb1c6243f6aa70a880af598d52873e1fe049f15c3a7e2e6f4a3e4b58fc0e", 
        "Random": "502143b34cab4a59f947a8da76f58e66215bf709e85f71f7cbfa4ead8e99736b", 
        "Cipher Suites Length": 15, 
        "Cipher Suites": [
            "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", 
            "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", 
            "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256", 
            "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256", 
            "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", 
            "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", 
            "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", 
            "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", 
            "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", 
            "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", 
            "TLS_RSA_WITH_AES_128_GCM_SHA256", 
            "TLS_RSA_WITH_AES_256_GCM_SHA384", 
            "TLS_RSA_WITH_AES_128_CBC_SHA", 
            "TLS_RSA_WITH_AES_256_CBC_SHA", 
            "TLS_RSA_WITH_3DES_EDE_CBC_SHA"
        ]
    }
}

The problem is that the .json printed data doesn’t respect the dictionary order, which means first it should have printed the length,the version,the random..etc.
Is there a way to fix this?

One Answer

Basically you question boils down to "Keep keys/values in same order as declared while initializing a dictionary". For this you have to use OrderedDict. OrderedDict maintains the order in which your keys are inserted.

For your case, you can initialize your HANDSHAKE dict like below:

from collections import OrderedDict
client_hello_params = ['Length', 'Version', 'Random', 'Session ID', 'Session ID Length', 'Cipher Suites Length', 'Cipher Suites', 'Compression Method']
HANDSHAKE = {
"Client_Hello": OrderedDict((param, 'unknown') for param in client_hello_params)

Now you can keep whatever order you want by changing the order in client_hello_params list.

Printing this will print your desired result eg.

import json
HANDSHAKE["Client_Hello"]['Length'] = 10
print(json.dumps(HANDSHAKE))
{"Client_Hello": {"Length": 10, "Version": "unknown", "Random": "unknown", "Session ID": "unknown", "Session ID Length": "unknown", "Cipher Suites Length": "unknown", "Cipher Suites": "unknown", "Compression Method": "unknown"}}

Answered by viky.pat on December 16, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP