githubEdit

πŸ—οΈEncryption

ws4sqlite includes a functionality not directly related to SQLite, but useful in many use cases. It allows you to specify a set of column that, when executing a statement, can be encrypted before being saved to a db; and conversely decrypted when reading them in a query, before returning them to a client. It can also compress the string before encryption, if it's very long.

In the request it's necessary to specify a password to encrypt/decrypt the data, and of course it must be the same when calling encryption and decryption.

The data saved to the database are normal TEXT data, so a text/varchar column is enough.

circle-exclamation

How To

Let's suppose to have a table called TEMP, with an integer primary key named ID and a text column called VAL.

A simple request that saves some data in encrypted form and reads them both undecrypted and decrypted is this:

{
    "transaction": [
        {
            "statement": "INSERT INTO TEMP VALUES (:id, :val)",
            "values": { "id": 1, "val": "Secret!!" },
            "encoder": {
                "password": "myPassword",
                "compressionLevel": 6,
                "fields": [ "val" ]
            }
        }, {
            "query": "SELECT ID, VAL FROM TEMP"
        }, {
            "query": "SELECT ID, VAL FROM TEMP",
            "decoder": {
                "password": "myPassword",
                "fields": [ "VAL" ]
            }
        }
    ]
}

Relevant structures are at Lines 6-10 for encryption, and at Lines 15-18 for decryption.

Notice that:

  • The password is the same (Lines 7 and 16) and is specified as clear text (be sure to use a secure connection!);

  • What to encode is specified as a list of fields from the values or valuesBatch nodes (Line 9). Fields that are not in this list will be saved as they are;

  • What to decode is specified as a list of fields from the resultset (Line 17);

  • Compression is requested, at Line 8. Here it is level 6; valid levels are 1-19. A level of 0 (or omitting the node) disable the compression;

    • Compression is applied only if it actually reduces the size of the text; if it doesn't, it's discarded at runtime without feedback;

  • You don't need to specify if data are compressed, when decoding.

The response is as this:

Notice that:

  • The 2nd request doesn't specify a decoder, so the response return the "raw" data in the field VAL. This is clearly not what you want;

  • The 3rd request does specify decryption, so the original value is returned;

  • If we had specified the wrong decryption password, an error would have been generated, of course it's possible to use noFail to manage it.

Implementation

For this function, the crypgoarrow-up-right library was used, featuring:

  • SCrypt key derivation;

  • XChaCha20-Poly1305 authenticated encryption;

  • ZStd compression;

  • Base64 encoding.

Please refer to its documentation for details.

Last updated