This code provides a secure API endpoint using encryption for...

September 4, 2025 at 01:03 PM

import json import os from base64 import b64decode, b64encode from cryptography.hazmat.primitives.asymmetric.padding import OAEP, MGF1, hashes from cryptography.hazmat.primitives.ciphers import algorithms, Cipher, modes from cryptography.hazmat.primitives.serialization import load_pem_private_key from django.http import HttpResponse from django.http import JsonResponse from django.views.decorators.csrf import csrf_exempt # Load the private key string PRIVATE_KEY = os.environ.get('PRIVATE_KEY') # Example: # '''-----BEGIN RSA PRIVATE KEY----- # MIIE... # ... # ...AQAB # -----END RSA PRIVATE KEY-----''' @csrf_exempt def data(request): try: # Parse the request body body = json.loads(request.body) # Read the request fields encrypted_flow_data_b64 = body['encrypted_flow_data'] encrypted_aes_key_b64 = body['encrypted_aes_key'] initial_vector_b64 = body['initial_vector'] decrypted_data, aes_key, iv = decrypt_request( encrypted_flow_data_b64, encrypted_aes_key_b64, initial_vector_b64) print(decrypted_data) # Return the next screen & data to the client response = { "screen": "SCREEN_NAME", "data": { "some_key": "some_value" } } # Return the response as plaintext return HttpResponse(encrypt_response(response, aes_key, iv), content_type='text/plain') except Exception as e: print(e) return JsonResponse({}, status=500) def decrypt_request(encrypted_flow_data_b64, encrypted_aes_key_b64, initial_vector_b64): flow_data = b64decode(encrypted_flow_data_b64) iv = b64decode(initial_vector_b64) # Decrypt the AES encryption key encrypted_aes_key = b64decode(encrypted_aes_key_b64) private_key = load_pem_private_key( PRIVATE_KEY.encode('utf-8'), password=None) aes_key = private_key.decrypt(encrypted_aes_key, OAEP( mgf=MGF1(algorithm=hashes.SHA256()), algorithm=hashes.SHA256(), label=None)) # Decrypt the Flow data encrypted_flow_data_body = flow_data[:-16] encrypted_flow_data_tag = flow_data[-16:] decryptor = Cipher(algorithms.AES(aes_key), modes.GCM(iv, encrypted_flow_data_tag)).decryptor() decrypted_data_bytes = decryptor.update( encrypted_flow_data_body) + decryptor.finalize() decrypted_data = json.loads(decrypted_data_bytes.decode("utf-8")) return decrypted_data, aes_key, iv def encrypt_response(response, aes_key, iv): # Flip the initialization vector flipped_iv = bytearray() for byte in iv: flipped_iv.append(byte ^ 0xFF) # Encrypt the response data encryptor = Cipher(algorithms.AES(aes_key), modes.GCM(flipped_iv)).encryptor() return b64encode( encryptor.update(json.dumps(response).encode("utf-8")) + encryptor.finalize() + encryptor.tag ).decode("utf-8")

This code provides a secure API endpoint using encryption for both request and response data. Here's a breakdown of what this code does:


Overall Functionality:

  1. The code implements a Django view (data) that:
    • Accepts a POST request with encrypted data.
    • Decrypts the provided data using an RSA private key.
    • Processes the decrypted data.
    • Returns a response encrypted using the provided AES (symmetric key encryption).

Components and Their Purpose:

1. PRIVATE_KEY:

  • Loaded from the environment variable PRIVATE_KEY, the RSA private key is used for decryption of the encrypted AES key in the request.

2. @csrf_exempt decorator:

  • Disables CSRF protection for the data view, allowing it to accept requests without CSRF tokens. This makes it suitable for APIs.

View (data function) - Request Handling:

Steps for the Request:

  1. Read and Parse Request Body:

    • The view expects a JSON body containing:
      • encrypted_flow_data: Encrypted data (base64-encoded).
      • encrypted_aes_key: Encrypted AES key (base64-encoded), encrypted with the API's RSA public key.
      • initial_vector: Initialization vector (IV) for AES decryption (base64-encoded).
  2. Call decrypt_request:

    • Decrypt the encrypted_flow_data using the decrypted AES key and initialization vector (IV).
    • This function:
      • Uses the RSA private key to decrypt the AES key.
      • Uses the decrypted AES key and IV to decrypt the actual flow data.
      • Parses the decrypted JSON data.
  3. Optional Use of Decrypted Data:

    • The decrypted data might be used to decide the response (not shown in detail in this code).
  4. Prepare the Response:

    • A basic response is prepared, e.g., specifying a new "screen" and some "data."
  5. Encrypt the Response:

    • Uses the same AES key and a modified version of the IV to encrypt the response data.
    • The response is then sent back to the client (base64-encoded).

Auxiliary Functions:

3. decrypt_request - Request Decryption:

  • This function decrypts the encrypted fields in the request using:
    • RSA Decryption (Private Key): To decrypt the AES key.
    • AES Decryption: To decrypt the actual flow data using the decrypted AES key and the IV.
  • Breakdown:
    • Decode the flow data (encrypted_flow_data_b64) and IV (initial_vector_b64) from base64.
    • Decrypt the AES key (encrypted_aes_key_b64) using the RSA private key and OAEP padding.
    • Separate flow data into ciphertext and GCM tag:
      • Last 16 bytes of the flow data are the GCM tag.
      • Remaining bytes are the encrypted payload.
    • Use AES-GCM mode (with the decrypted key and IV) to decrypt the flow data into plaintext JSON.

4. encrypt_response - Response Encryption:

  • Used to encrypt the response data before sending it to the client.
  • Key functionality:
    • The initialization vector (IV) from the request is "flipped" (each byte XOR-ed with 0xFF) to serve as a new IV for encryption.
    • Uses AES encryption in GCM mode with the flipped IV and the AES key.
    • The encrypted response includes:
      • Ciphertext + GCM tag (encoded as base64).

Example Workflow:

For Incoming Request:

  1. A client encrypts the AES key using the RSA public key of the API and sends it in encrypted_aes_key.
  2. The client encrypts some flow data using AES-GCM with the same AES key and an IV, sends the encrypted data as encrypted_flow_data, and sends the IV as initial_vector.

On Server (Backend):

  1. The backend (via decrypt_request) decrypts the AES key using its RSA private key.
  2. The flow data is decrypted using the provided IV and AES key.

For Outgoing Response:

  1. The backend prepares a response payload (e.g., the next "screen").
  2. The response data is encrypted using the client-provided AES key and a "flipped" version of the IV.
  3. The encrypted response is sent back to the client.

Security Notes:

  1. RSA (used for transmitting the AES key) is secure if a strong key size (e.g., 2048 or 4096 bits) is used.
  2. AES-GCM provides encryption integrity via the GCM tag, ensuring the ciphertext hasn't been tampered with.
  3. Flipping the IV for the response ensures it doesn't reuse the same IV for encryption, avoiding potential cryptographic vulnerabilities (e.g., nonce reuse).

Summary:

This code implements a secure, encrypted data-processing pipeline using a combination of RSA and AES encryption for confidentiality and integrity. It is used to accept and decrypt securely transmitted data from a client, process the data, and send an encrypted response back.

Generate your own explanations
Download our vscode extension
Read other generated explanations

Built by @thebuilderjr
Sponsored by beam analytics
Read our terms and privacy policy
Forked from openai-quickstart-node