security – Attempt: securing data-in-use in Flutter application

Theres many ways and options for protecting data-in-transit as well as data-at-rest. There are also many ways of protecting authentication as well as authorization. However in my research over the past months I haven’t come across any easy high-level ways of securing data-in-use. So I put something together today that may be somewhat of a programmatic high-level solution for protecting data-in-use in Flutter apps or really any app or software.

I would like input on this way of doing things. I want to know plus points as well as negatives and vulnerabilities in this method. I’m providing everything one would need to recreate the project below.

My programmatic approach to protecting data-in-use:

Firstly not sure if this would work in a real Flutter app because of rebuilding widgets, however read my readme and give some input if you have any ideas.

This approach loads data from secured memory, un-encrypts data, feeds it to user, re-encrypts data with new keys, scrambling old keys out of memory, closes data at rest & finally erases newly re-encrypted data in memory.

CODE

import 'dart:io';
import 'package:crypton/crypton.dart';
import 'package:hive/hive.dart';
import 'package:steel_crypt/steel_crypt.dart';

Future<void> main(List<String> arguments) async {
  // Initialize Hive directory
  Hive.init('PROJECT_STORAGE');

  ///
  ///
  /// Asymmetric example
  Box<String> asymmetricBox = await Hive.openBox<String>('asymmetric_box');

  // 1 INITIALIZE DEMO - Create keys & data
  print('Initializing asymmetric demo data');
  RSAKeypair rsaKeypair = RSAKeypair.fromRandom();
  String sensitiveDataAsymmetric = 'Super_secret_stuff_asymmetric';

  // 2 INITIALIZE DEMO - Encrypt data
  String asymmetricallyEncryptedData = rsaKeypair.publicKey.encrypt(sensitiveDataAsymmetric);

  // 3 INITIALIZE DEMO - Save keys & data
  await asymmetricBox.add(asymmetricallyEncryptedData);
  await asymmetricBox.add(rsaKeypair.privateKey.toFormattedPEM());
  await asymmetricBox.add(rsaKeypair.publicKey.toFormattedPEM());

  // 4 INITIALIZE DEMO - Scramble sensitive data with new misdirector keys, rescramble keys & reassign data in memory
  rsaKeypair = RSAKeypair.fromRandom();
  sensitiveDataAsymmetric = rsaKeypair.publicKey.encrypt(sensitiveDataAsymmetric);
  rsaKeypair = RSAKeypair.fromRandom();
  sensitiveDataAsymmetric = '';

  // 5 INITIALIZE DEMO - Close Hive box
  await asymmetricBox.close();

  sleep(Duration(seconds: 2));
  print('''
Begin asymmetric test ----------
''');

  // 1 TEST DEMO - Load private key from persistent storage
  Box<String> reopenedAsymmetricBox = await Hive.openBox<String>('asymmetric_box');
  bool boxOpen = reopenedAsymmetricBox.isOpen;
  (boxOpen) ? print('Box open') : print('Box closed');
  RSAPrivateKey privateKey = RSAPrivateKey.fromPEM(reopenedAsymmetricBox.getAt(1)!);

  // 2 TEST DEMO - Load, decrypt & display sensitive data
  String decryptedData = privateKey.decrypt(reopenedAsymmetricBox.getAt(0)!);
  print('Decrypted data: ' + decryptedData);

  // 3 TEST DEMO - Secure data, keys & storage
  await reopenedAsymmetricBox.close();
  (boxOpen) ? print('Box open') : print('Box closed');
  print('Exposed memory private key: ' + privateKey.toFormattedPEM());
  privateKey = RSAKeypair.fromRandom().privateKey;
  print('Misdirected private key: ' + privateKey.toFormattedPEM());
  RSAKeypair misdirectorKeys = RSAKeypair.fromRandom();
  decryptedData = misdirectorKeys.publicKey.encrypt(decryptedData);
  misdirectorKeys = RSAKeypair.fromRandom();
  print('Decrypted data re-encrypted: ' + decryptedData);
  decryptedData = '';
  print('Data cleared: ' + decryptedData);

  ///
  ///
  /// Symmetric example
  Box<String> symmetricBox = await Hive.openBox<String>('symmetric_box');

  // 1 INITIALIZE DEMO - Create keys & data
  print('''
Initializing symmetric demo data
''');
  String symmetricKey = CryptKey().genFortuna();
  String symmetricNonce = CryptKey().genDart(len: 12);
  AesCrypt symmetricCypher = AesCrypt(key: symmetricKey, padding: PaddingAES.pkcs7);
  String sensitiveDataSymmetric = 'Super_secret_stuff_symmetric';

  // 2 INITIALIZE DEMO - Encrypt data
  String symmetricallyEncryptedData =
      symmetricCypher.gcm.encrypt(inp: sensitiveDataSymmetric, iv: symmetricNonce);

  // 3 INITIALIZE DEMO - Save keys & data
  await symmetricBox.add(symmetricallyEncryptedData);
  await symmetricBox.add(symmetricKey);
  await symmetricBox.add(symmetricNonce);

  // 4 INITIALIZE DEMO - Scramble sensitive data with new misdirector keys, rescramble keys & reassign data in memory
  symmetricKey = CryptKey().genFortuna();
  symmetricNonce = CryptKey().genDart(len: 12);
  symmetricCypher = AesCrypt(key: symmetricKey, padding: PaddingAES.pkcs7);
  sensitiveDataSymmetric = symmetricCypher.gcm.encrypt(inp: sensitiveDataSymmetric, iv: symmetricNonce);
  sensitiveDataSymmetric = '';

  // 5 INITIALIZE DEMO - Close Hive box
  await symmetricBox.close();

  sleep(Duration(seconds: 2));
  print('''
Begin symmetric test ----------
''');

  // 1 TEST DEMO - Load private key from persistent storage
  Box<String> reopenedSymmetricBox = await Hive.openBox<String>('symmetric_box');
  boxOpen = reopenedSymmetricBox.isOpen;
  (boxOpen) ? print('Box open') : print('Box closed');
  AesCrypt symmetricCypherII = AesCrypt(key: reopenedSymmetricBox.getAt(1)!, padding: PaddingAES.pkcs7);

  // 2 TEST DEMO - Load, decrypt & display sensitive data
  String decryptedDataII =
      symmetricCypherII.gcm.decrypt(enc: reopenedSymmetricBox.getAt(0)!, iv: reopenedSymmetricBox.getAt(2)!);
  print('Decrypted data: ' + decryptedDataII);

  // 3 TEST DEMO - Secure data, keys & storage
  await reopenedSymmetricBox.close();
  (boxOpen) ? print('Box open') : print('Box closed');
  String symmetricKeyScramble = CryptKey().genFortuna();
  String symmetricNonceScramble = CryptKey().genDart(len: 12);
  symmetricCypherII = AesCrypt(padding: PaddingAES.pkcs7, key: symmetricKeyScramble);
  decryptedDataII = symmetricCypherII.gcm.encrypt(inp: decryptedDataII, iv: symmetricNonceScramble);
  misdirectorKeys = RSAKeypair.fromRandom();
  print('Decrypted data re-encrypted: ' + decryptedDataII);
  decryptedDataII = '';
  print('Data cleared: ' + decryptedDataII);
}

LIBRARIES

dependencies: 
  crypton: ^2.0.2
  hive: ^2.0.4
  steel_crypt: ^3.0.0+1

README

# demo_project_security_data_at_rest
    - Testing and experimental protection of data-in-use

# Project purpose:
    - Main purpose is to experiment with methods for protecting data-in-use
    - DATA SECURITY IS OF THE HIGHEST PRIORITY OVER RESOURCE MANAGEMENT (let the processor do its job baby)
    - Overall purpose is also to cut down on possibility of memory style attacks such as memory dumps, cold boot attack etc.
    - This is being done at a high level with simple actions such as:
      - Immediately re-encrypting decrypted data after use is garnered from exposed decrypted data
      - Immediately deleting from memory the previously re-encrypted data
  
    - Essentially this means:
      - 1: Decrypt data for immediate use
      - 2: Load data for user
      - 3: Re-encrypt data in-memory
      - 4: Delete re-encrypted data from memory
      - Note: the same would go for all keys used for encryption and decryption
        - The storage avenue used for keys would always be flutter_secure_storage i.e. iOS Keychain & Android Keystore

# This project features:
    - Steel Crypt package for symmetric encryption
    - Crypton package for asymmetric encryption
    - Hive boxes for storing data-at-rest & keys (for the sake of this demo project, non-encrypted boxes)

    - Note:
      - In a Flutter application:
        - Hive encrypted boxes would be used for data-at-rest storage
        - Flutter_secure_storage would be used for key storage
        - Steel Crypt & Crypton would be used for data-in-transit cryptography

# Possible issue:
- This is a Dart application only, so it should work as intended above with simple print statements. However when using rebuilding widgets I imagine that the widgets would reflect re-encrypted and also deleted data as they occur. Essentially due to computing speed the user wouldn't even see decrypted useful data for a split-second much less be able to use their data as normally. Must find a way around this.

- This will be posted for help on Stack Overflow and/or Information Security prior to attempting a Flutter graphical test.
```

docker – Securing a Kubernetes application – SSL on Kubernetes or container?

I have a gRPC server written in golang and containerized with Docker. I would like to deploy this application to Kubernetes with TLS (Let’s Encrypt).

What is the best way to secure the application? I’ve read that Kubernetes can use a Let’s Encrypt ingress controller to handle TLS and securing the cluster. However, my gRPC web server can also load certificates to enable TLS. This is less convenient though, because I have to restart the container when certificates renew, bind them to a volume, etc.

Is there anything wrong with leaving the container insecure (serving HTTP) and have the Kubernetes cluster proxy take care of securing the connection?

authorization – Securing a public service with single use token (or alternative approach)

I am working on a data uploading service. The requirements for this service dictate that it is accessible publicly on the internet. I need to protect the service from abuse. The service will be shared with companies that need to upload data to our platform and will be used for one-time submissions only. This leads me to token-based authorization setup, where we provide a third party with a token that expires after one use or after a specified amount of time, whichever comes first. The third party submits their data with the provided token.

I’m not sure if this is a conventional approach, or the best way to do it. We use Keycloak for authn/authz, but I haven’t figured out if it can support this use case. I would appreciate any pointers or suggestions for a better approach.

encryption – Securing data stored on a file

There can be many different solutions possible. I’d suggest to consider following.

First consider standard tools. Can your users use VeraCrypt?

If not, how about using some broadly used archiving formats like ZIP, RAR, 7z? They all support encryption.

Use any of encryption algorithms that are broadly known like AES-256, ChaCha20, Threefish-256.

Think of proper mode. For instance, if files are relatively big and if you need random access to different file fragments, you may prefer AES GCM to AES CBC.

Applying passwords for encryption as is can make brute-forcing easier, because depending an attacker can test a considerable number of passwords in a short time. Instead, derive the encryption key using algorithms like Argon2, bcrypt, scrypt. Configure it in such way that derivation of a single key takes 1s. Such delay can be acceptable for user and this will reduce brute-forcing speed to 1 password per second.

To derive encryption key you will need the same parameters as used for encryption: salt, the number of iterations, memory factor (Argon2), parallelism (Argon2). That’s why you need to store them. How you store them (at the beginning, at the end) is up to you.

embedded system – Securing IoT application

I’m designing an IoT product, I’m searching solutions to secure the system.

The system’s protocol is MQTT, while it’s very helpful, it contains vulnerabilities.

I’ve read enough to come with this proposed system:

  • Using TLS: It’s important, but it depends on support.
  • Apply a client-id prefix rule: The server wont accept any client-id other than ones meets a certain prefix, e.g. device-.
  • Authorization: Creating ACL (Access Control List) to allow each device to only subscribe to topics prefixed with its device-id rx/device00001/# and only publish to topics with the same property tx/device00001/.*
  • Limit the accepted messages lengths.*
  • Use authentication that depends on MCU’s MAC address and a device-name:
    Use device-id as client-id, and both device-id and MAC as password. Where MAC and device-id are securely shared to the server at flashing the firmware process.
  • Use application payload encryption.

Comments:

  • * Server terminates the client otherwise.
  • If TLS isn’t used, an encrypted password is needed to secure-out the CONNECT packet sent to the server; because credentials are sent in plaintext.
    Beside that: the password should be a function of UNIX time, to limit replay attacks. The time is used at server-side to checkout the freshness of the request.
  • If all security layers are used, Is there a need for application payload encryption?

Can you tell whether this system is secured or it contains threats?

dynamic programming – Algorithm that counts unique ways of securing doors

I’m having trouble even starting this problem and need help getting the ball rolling.

Here is the question:

You are given a row of n doors, each of which can either be locked or unlocked.
Your goal is to have exactly S secured doors. The issue is that not all locked doors are secure.
A door is secure if and only if:

  1. This door is locked AND
  2. This door is the first door (i.e., the left most door) OR The door to this one’s left is also
    locked

Develop an algorithm that, given the number of doors n and a value S, counts the total
number of unique ways the doors can be locked to achieve EXACTLY S secure doors

I understand that a Dynamic Programming approach should be used but I’m unsure on how to divide the problem into subproblems and what an optimal approach would be. Any thoughts on how to begin?

appsec – Securing APIs used by remote devices

We have desktop software that we install and run on remote, unattended machines. The software needs to hit API endpoints on our server. What is the best way to secure those endpoints to ensure that only our software can call them? We may or may not have admin rights to that machine. Others (staff or 3rd party individuals) may have access to that machine at an admin level.

networking – Securing a replay-based leaderboard system (as much as possible)

A few years ago, I implemented a basic online leaderboard system in one of my games that sent encrypted score data over the wire. The encryption keys were stored in the game client’s binary. Of course, the leaderboards got hacked the same day they were released.

I have now released a new game on Steam, and I’ve worked hard to implement fully-deterministic game logic and a replay system.

The replay system works by simply replaying the user’s input that was recorded in a previous playthrough. The fully-deterministic game logic ensures that the replay will work on any machine, independently of the game’s FPS.

Now, it is time for me to implement online leaderboards.

My idea is to create a server version of the game executable which receives replay files over the network, replays them on some remote machine, and adds the score to a database if the replay data is valid.

While this prevents cheaters from simply sending a fake score to the server, it opens up many other cheating avenues, including:

  • Tool assisted creation of replays, either by slowing down the game speed or by manually crafting a replay file after reverse-engineering its format (the game is open-source).

  • Taking someone else’s replay and sending it over the network, changing data regarding who the replay belongs to.

I could somehow encrypt and compress the replay data before sending it over (or saving it on the user’s local machine), but since the game is open-source, it would be easy to reverse-engineer the encrypted replay format.

What is a good way of securing a replay-based online leaderboard system?

One possible idea I had is to have the server generate an encryption key / token for a specific user which is only valid for a small amount of time, send it over to the client, and only accept replays that are encrypted with that key. This would prevent users from uploading older replays to the server, but in theory it should work — am I missing something?