0

I was asked to work with RSA Encryption for sending data between bluetooth nodes, and this is my first week researching any form of encryption, so i'm in need of a bit of help.

It appears that output size is always relative to the size of the modulus. Mod 2048 and 1024 seem to be popular, which have 256-byte and 128-byte output sizes, respectively.

I am working with Bluetooth low energy (Bluetooth Smart) nodes which only accept a data packet of size 20(bytes).

My Question: Is there any point in encrypting data if I can only send 20 bytes? I don't see it being plausible to have 20 bytes of data encrypted as 20 bytes...which isn't much of an encryption. I'm not even sure if it's possible to set up a modulus of 160 to encrypt this? If you are wondering, why a modulus of 160? This is because if (2048 / 8 = 256 bytes), then (160 / 8 = 20 bytes).

NEW INFO: I can not send multiple packets as this system is a mesh system. That is, every time that I send a packet, the node disconnects from the sender, then broadcasts the message to any node in the air. It takes about 4 seconds before I can send a second packet.

So far, I have wrote some test code just to get my hands dirty and to check the default output of encrypting 20 bytes (which ended up being a 256 byte output).

public class Encryption {

    // Possibly use files for saving keys
    private static String PUBLIC_KEY_FILE = "Public.key";
    private static String PRIVATE_KEY_FILE = "Private.key";

    Key publicKey = null;
    Key privateKey = null;
    KeyPairGenerator kpg;
    KeyPair kp;
    Cipher cipher;

    public Encryption() {

        try {
            kpg = KeyPairGenerator.getInstance("RSA");
            kp = kpg.generateKeyPair();
            publicKey = kp.getPublic();
            privateKey = kp.getPrivate();
        } catch (Exception e) {
            Log.e("Encryption", "RSA KeyPair Error...");
            e.printStackTrace();
        }
    }

    // Encode
    public byte[] encode(byte[] bytesToEncode) {
        byte[] encodedBytes = null;

        try {
            // Basic Cipher (mode/padding excluded for now)
            cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.ENCRYPT_MODE, privateKey);
            encodedBytes = cipher.doFinal(bytesToEncode);
        } catch (Exception e) {
            Log.e("Encryption", "RSA Encoding Error...");
            e.printStackTrace();
        }

        return encodedBytes;
    }

    public byte[] decode(byte[] encodedBytes) {
        byte[] decodedBytes = null;

        try {
            cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.DECRYPT_MODE, publicKey);
            decodedBytes = cipher.doFinal(encodedBytes);
        } catch (Exception e) {
            Log.e("Encryption", "RSA Decoding Error...");
            e.printStackTrace();
        }

        return decodedBytes;
    }
}

As you can see in my global variables, I will later have to change the code to save these keys at some point instead of recreating them every time so I am always using the same keypair. Additionally, I need to give the public key file to my engineer who writes the node firmware so he can decode my encryption. Since i'm working strictly with bytes, I shouldn't have issues with charsets.

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
  • "which only accept a data packet of size 20(bytes)..." So send multiple packets. You also don't seem to have a question in here. – President James K. Polk Sep 03 '17 at 21:04
  • @JamesKPolk Please see my added information. I highlighted the question as well. Since i'm working with a mesh system, I cannot stream data or send simultaneous packets. When sending a packet to one of my nodes, the node goes from receiving to sending, which terminates the connection. It takes ~4 seconds before I can "see" the bluetooth node again. –  Sep 03 '17 at 21:49
  • 160 bit RSA offers so little security it's pointless to even bother. 160 bit elliptic curve cryptography is much stronger, though still far below contemporary standards. Your requirements are unfortunately extremely limiting. – President James K. Polk Sep 03 '17 at 21:54
  • @JamesKPolk Thank you. I suppose I was just looking for a second opinion since I know very little about Cryptography. Please post an answer so that I may accept and give you proper credit. –  Sep 03 '17 at 23:25
  • Instead of posting an answer let me suggest you ask the question on crypto.stackexchange.com. Rather than post your code, simply mention your requirements. They have a lot of experts there, some of whom may have experience in mesh network / resource-constrained cryptography. – President James K. Polk Sep 03 '17 at 23:36

1 Answers1

1

You are trying to reinvent the wheel:

  • you should only use RSA to sign and encrypt randomly generated keys that you will share between your devices, not to exchange any other type of data.

  • then you should use these keys with symmetric algorithms to authenticate and encrypt data between your devices.

The standard RSA key length is about 2048 bits, nowadays.

The standard AES symmetric key length is about 256 bits, nowadays.

But the key size and the block size are not the same: AES block size is 16 bytes. This should fit comfortably in your small packets.

More precisely, since your data size may not be exactly 16 bytes, you should use a block cipher algorithm (CBC, for instance) or a stream cipher one (GCM, for instance) for your data to be processed with AES or other symmetric algorithms.

The state-of-the-art AES-256-GCM algorithm integrates authentication and encryption in a single stream cipher. Since you SHOULD always authenticate data before trying to decrypt it (most of the people that did not comply with this rule have had problems), only using something like AES-256-CBC is a bad idea.

Finally, note that Bluetooth LE, that you are using, introduced AES-CCM, for confidentiality, integrity, and authentication. May you base your communications on this feature to achieve your goals.

Alexandre Fenyo
  • 4,526
  • 1
  • 17
  • 24
  • Thanks, I understood most of what you said. It looks like I will have to use a block/stream cipher algorithm with padding? Are there any tutorials that you recommend? –  Sep 04 '17 at 20:50
  • Since you are programming in Java, you should really consider using BouncyCastle instead of the native implementation of Java crypto APIs. Perhaps you could start here: https://stackoverflow.com/questions/885485/how-do-i-get-started-using-bouncycastle – Alexandre Fenyo Sep 04 '17 at 20:54