Skip to main content

Non-encrypted confidential information - Hexadecimal

Need

Encryption of confidential information to ensure data confidentiality

Context

  • Usage of Dart 2.0 for building scalable and performant applications
  • Usage of Shelf for managing and organizing data in a Node.js application

Description

Non compliant code

import 'package:shelf/shelf.dart' as shelf;

void main() {
var handler = const shelf.Pipeline().addMiddleware(shelf.logRequests())
.addHandler(_echoRequest);

shelf.serve(handler, 'localhost', 8080).then((server) {
print('Serving at http://${server.address.host}:${server.port}');
});
}

shelf.Response _echoRequest(shelf.Request request) {
var data = 'Confidential Information';
var hexData = data.codeUnits.map((byte) => byte.toRadixString(16)).join();
return shelf.Response.ok(hexData);
}

The above Dart code is a simple server application using the Shelf framework. It defines a single request handler _echoRequest which is invoked for every HTTP request received by the server.

The vulnerability lies in the _echoRequest function. This function is converting a string data (which is assumed to be confidential information) into a hexadecimal string hexData using the toRadixString(16) method. This hexadecimal string is then returned in the HTTP response.

The problem is that this hexadecimal encoding does not provide any form of data protection. Anyone who intercepts this HTTP response can easily decode the hexadecimal string back into the original confidential information. This is because hexadecimal encoding is not a secure method of encryption, it is merely a way of representing binary data in a human-readable format.

In other words, the server is transmitting confidential information over the network in a format that can be easily decoded by an attacker. This is a clear violation of data confidentiality, one of the key principles of information security.

Steps

  • Import a library that provides encryption functionality, such as 'dart:crypto'.
  • Create an encryption key. This should be a secure, randomly generated key that is kept secret.
  • Before converting the confidential information to hexadecimal, encrypt it using the encryption key.
  • Now, when the confidential information is converted to hexadecimal, it will be the encrypted data that is converted, not the original plain text.
  • When the data needs to be read, it should be first converted back from hexadecimal, then decrypted using the same encryption key.

Compliant code

import 'package:shelf/shelf.dart' as shelf;
import 'package:crypto/crypto.dart';
import 'dart:convert'; // for the utf8.encode method

void main() {
var handler = const shelf.Pipeline().addMiddleware(shelf.logRequests())
.addHandler(_echoRequest);

shelf.serve(handler, 'localhost', 8080).then((server) {
print('Serving at http://${server.address.host}:${server.port}');
});
}

shelf.Response _echoRequest(shelf.Request request) {
var data = 'Confidential Information';
var key = utf8.encode("randomly generated key"); // replace with your key
var bytes = utf8.encode(data);

var hmacSha256 = new Hmac(sha256, key); // HMAC-SHA256
var digest = hmacSha256.convert(bytes);

var hexData = digest.bytes.map((byte) => byte.toRadixString(16)).join();
return shelf.Response.ok(hexData);
}

The code above is a fixed version of the original code that was vulnerable to attacks due to non-encrypted confidential information. The confidential information was being converted to hexadecimal which could be easily decoded to plain text by an attacker.

To fix this vulnerability, the 'dart:crypto' library was imported to provide encryption functionality. The confidential information is now encrypted using HMAC-SHA256 before being converted to hexadecimal.

The encryption key is a secure, randomly generated key that is kept secret. In this example, the key is hardcoded as "randomly generated key", but in a real-world application, you should replace this with your own secure key.

The Hmac class from the 'dart:crypto' library is used to create a new HMAC object with the SHA256 hash function and the encryption key. The convert method is then used to encrypt the confidential information.

The encrypted data is then converted to hexadecimal. Now, even if an attacker is able to decode the hexadecimal, they will only see the encrypted data, not the original plain text.

When the data needs to be read, it should be first converted back from hexadecimal, then decrypted using the same encryption key. This decryption process is not shown in the code above, but would be necessary in a real-world application.

References