Simple (but good) Message Encryption?

Posted on
of 2
/ 2
  • Just to add, we could use Uint32Arrays here which would end up being a bit more memory efficient.

  • Cool. It would be interesting to know the relative speed of the C implementation and the JS implementation. I guess for most things it does not matter that much, but it would be good to know.

  • The JS implementation is going to be significantly slower - maybe in the 100x range? So something built in would definitely be preferable - but this is a good stopgap for very small amounts of data.

  • Hi @Stevie and @Gordon

    This is so cool, like to setup a PR to have this in master, if you don't mind ?

  • Do you mean the JS version, or the C?

    There's already proper AES crypto in the Crypto library:­

    Is that not compiled into ESP8266 now (which I guess is what you'd want it for)?

    We could add it, but some devices are getting short on flash now and I wonder if it's a good idea if AES is available.

  • Sorry for not being specific enough, I am talking about the C part.

    We could add it, but some devices are getting short on flash now and I wonder if it's a good idea if AES is available.

    What about a USE_TEA option which is not set by default and implementing the TEA function into module crypto.

  • We could do that, yes.

    But what is the reasoning for it? Can you not just include AES in whatever platform you care about?

    I would imagine that is a much more secure encryption method?

  • I want to have a simple and good encryption and decryption as a balance of size and security.

    On ESP8266 there will be no https with Espruino as far as I unterstand. So I was thinking about to secure the content thats being send and received. TEA seems to be simple to implement in C or in JS, both are available as source in this thread.

    Tried to include AES on ESP8266, looks like no one tried this before :)

    libs/crypto/jswrap_crypto.c: In function 'jswrap_crypto_AES_encrypt':
    libs/crypto/jswrap_crypto.c:433:3: error: implicit declaration of function 'jswrap_crypto_AEScrypt' [-Werror=implicit-function-declaration]
       return jswrap_crypto_AEScrypt(message, key, options, true);
    libs/crypto/jswrap_crypto.c:433:3: warning: return makes pointer from integer without a cast [enabled by default]
    libs/crypto/jswrap_crypto.c: In function 'jswrap_crypto_AES_decrypt':
    libs/crypto/jswrap_crypto.c:452:3: warning: return makes pointer from integer without a cast [enabled by default]
       return jswrap_crypto_AEScrypt(message, key, options, false);
    libs/crypto/jswrap_crypto.c: At top level:
    cc1: warning: unrecognized command line option "-Wno-float-conversion" [enabled by default]
    cc1: warning: unrecognized command line option "-Wno-discarded-qualifiers" [enabled by default]
    cc1: some warnings being treated as errors
    make: *** [libs/crypto/jswrap_crypto.o] Error 1
    make: *** Waiting for unfinished jobs....
  • Odd errors to get - there shouldn't be specific build options for AES stuff so I don't know why you're getting those errors.

    Add TEA as a PR then. It may well be that it adds extremely little to the code size in which case it'll be nice to add to everything

  • It'd be good if you could add it as part of the Crypto module though, rather than its own XXTEA namespace

  • That's what I will do !

  • one more try to make ESP8266_BOARD

    LD espruino_esp8266_user1.elf
    /Volumes/ESPTools/esp-open-sdk/xtensa-lx­106-elf/bin/../lib/gcc/xtensa-lx106-elf/­4.8.2/../../../../xtensa-lx106-elf/bin/l­d: address 0x3fffdbd8 of espruino_esp8266_user1.elf section `.bss' is not within region `dram0_0_seg'
    /Volumes/ESPTools/esp-open-sdk/xtensa-lx­106-elf/bin/../lib/gcc/xtensa-lx106-elf/­4.8.2/../../../../xtensa-lx106-elf/bin/l­d: espruino_esp8266_user1.elf section `.text' will not fit in region `iram1_0_seg'
    /Volumes/ESPTools/esp-open-sdk/xtensa-lx­106-elf/bin/../lib/gcc/xtensa-lx106-elf/­4.8.2/../../../../xtensa-lx106-elf/bin/l­d: address 0x3fffdbd8 of espruino_esp8266_user1.elf section `.bss' is not within region `dram0_0_seg'
    make: *** [espruino_esp8266_user2.elf] Error 1

    no idea how to fix or if possible at all

  • That looks like a RAM usage issue? I guess you'd have to reduce the amount of variables?

  • I've put comments on your GitHub issue... it's the static tables that by default got to ram...

    The errors in #33 above are due to the headers not being included.

  • First I've seen this thread, but I can suggest an alternative less resource intensive solution that I have used...

    Assumptions... @Gordon initial premises of low resources, low message overhead, validating message integrity, use of a predefined secret, and use of the built-in SHA256 hash function; however, no message encryption. This can be extended to Puck.js security as well.

    Consider that sometimes authentication of the message can be more important than the actual message -- the message bears the kings seal! For example, if I want to read a sensor value or send a message to open/close a garage door, particularly within a small coverage area such as BLE vs the global Internet, I may not need to encrypt the message if I can validate that the message is authentic. In other words who cares what the message says if I can discriminate and trust who sent the message.

    This involves a much simpler and faster procedure. For a string of "data", you calculate an authentication hash equivalent say to the following pseudo-code.

    hash = SHA256(salt+epoch+secret+data);
    message = {data:data, salt:salt, epoch:epoch,hash:hash, version:1};

    Where salt is a random prefix string, typically 2-8 characters, to ensure sending the same message does not generate the same hash response; epoch is a time stamp that enables checking that the message was generated within a valid time window (i.e. sent just now, not a replay from yesterday. Also, need to be able to sync time.); secret is a piece of information known only by the sender and receiver and never passed openly (although this may be required one time in a learn mode, which presumably you can control); and the optional version provides identification of the scheme used that allows the receiver to discriminate different formats and enables a migration path to newer schemes.

    Note the salt, epoch, and the hash get passed with the data message. The receiver uses the same code to generate the same hash locally, using the locally known secret. If the sent message hash matches the locally generated hash, the message is authentic so act on it; otherwise, ignore the message or report it as a bad request perhaps. The hash also acts as a "checksum" to validate the integrity of the data. A single bit error will radically alter the generated hash.

    If the overhead of the hash, salt, and epoch represent to much bandwidth burden, many options exist. For example, send a simple string instead of a JS object with the fixed length version (1 byte), salt (2 byte), epoch (4 byte), and hash (32 bytes) prefixed to the data string, which the receiver can very easily parse by fixed substrings. Alternately, the hash can be truncated as a trade with security. A 4 byte hash for example still has 256^4 or ~1:4 billion chance of being replicated, probably good enough for most personal sensor/actuator applications. Assuming 5 byte hash, you only add 12 bytes overhead per message, which even works for the limited BLE message size.

    Another feature I like is that with an initial stored secret, the secret used for the hash can itself be adapted on the fly or on (authenticated) command. For example, you could hash the stored secret with a client provided random string, which changes the key for the specific message at the request of the client. Or roll the key based on a variable such as the day of the week. Or generate the key internally to the transmitter perhaps with a PUF -- see­nclonable_function

    There are many variations on this theme, but...

    1. Always randomize the message (i.e. salt it).
    2. Never pass the secret (other than possibly a controlled one time learn).
    3. Pass time and build in a time syncing capability.

  • What about a sequence number ? This should allow the receiver to identify if a message is missing.

  • What about a sequence number ? This should allow the receiver to identify if a message is missing.

    Yes, useful for flagging lost data but i wouldn't recommend for validating data, that is, you don't want to rely on having to receive every sequential packet. It's probably not as easy to recover a missing packet as it is to just design with expectation of missing samples. Recovery means having to queue each data packet until you get an acknowledgement for each, which means memory resources and additional overhead for handshaking too, pretty significant for small devices like Espruino.

    It can be useful for rolling a secret code too, essentially what garage door openers do.

  • Yes, I fully agree, never thought of recover, just as flag to get an idea how reliable the communication really is.

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview

Simple (but good) Message Encryption?

Posted by Avatar for Gordon @Gordon