# Java - AES with 20 byte packet

I have 20 bytes of data that I need to encrypt and send to a bluetooth node. The main issue being that the receiving node only accepts 20 byte packets. Further, I cannot send multiple packets, one after another, as the node disconnects directly after receiving a packet. The node then connects to a mesh network and pushes the packet to all nodes in the network.

Is there way to set the encrypted block size using AES? My electrical engineer said that AES128 CCM was built in to his firmware programming IDE and was capable of doing that on his side of things. I honestly don't believe him.

If I cannot send 20 encrypted bytes using AES, what encryption method can?

• What are your actual requirements? Should the message be just confidential or should the message also be protected for integrity / authenticity? Are the packets themselves unique, is there message specific ID in there? Encrypting 20 bytes isn't even that hard, but without these kind of specifications you may still not have a secure system. – Maarten Bodewes Sep 18 '17 at 22:06
• @MaartenBodewes This is my first time dabbling with encryption so please know that i'm a little overwhelmed by what you are asking. Each packet is unique and I would like to have the packet as protected as possible. I am building a security system that passes message via an android app through multiple bluetooth nodes placed around a building. The nodes are connected through a mesh network. Currently the system works great. I just want to ensure than someone cannot read or write messages to my devices. – FoxDonut Sep 18 '17 at 22:19
• If the messages are unique then achieving confidentiality can be done, but you cannot add an authentication tag. AES CCM could be used with the nonce outside the encrypted message. However, the authentication tag required to protect the integrity and others to avoid sending the next message still requires overhead. That cannot be avoided. – Maarten Bodewes Sep 18 '17 at 22:26
• From all of the tutorials that I have looked at, all AES-128 encryption designates a block size of 16 bytes. Since I am encrypting 20 bytes, padding is added which makes my total output 32 bytes, which I cannot use. Would you be willing to provide me with a link or code (java) to only generate 20 bytes of output? Sorry for asking so much from you. I really appreciate your time. – FoxDonut Sep 18 '17 at 22:32
• Well, you could google Format Preserving Encryption (FPE) to form a 160 bit Feistel network (using 2 x 10 bytes output of AES). Check the Wikipedia page about format preserving encryption. – Maarten Bodewes Sep 18 '17 at 22:50

Take this answer as simplification and extension of the previous answer (from Squeamish Ossifrage)

AES-128 encryption designates a block size of 16 bytes. Since I am encrypting 20 bytes, padding is added which makes my total output 32 bytes,

You may use CTR mode which you may use without any padding. It effectively creates a stream cipher so if you have 20 bytes of data, the output is 20 bytes of data.

Though you still need the salt/counter and an authentication tag. However - it depends on your options. Are you able to use an implicit counter?

Someone already mentioned the Format Preserving Encryption, so - if you have no more space for salt/counter, you simply have to do with a constant salt and without any authentication tag accepting some thread vectors.

• Yes, I can use an implicit counter. – FoxDonut Sep 20 '17 at 1:18
• @FoxDonut still be adviced if you have place to include a counter. If you miss a single message, your producer/consumer goes out of sync and you are pretty much scr...d. – gusto2 Sep 20 '17 at 7:14

You can't change AES's block size—it's always 16 bytes. But you can use AES to conceal messages, and prevent forgery of messages, of other sizes, and AES-CCM is one way to do just that.

Provided you only ever use a key exactly once, or have a unique (say) sequence number called a nonce for each message transmitted under the key, AES-CCM can encrypt a message of any bit length, and at the cost of $\tau \leq 128$ extra bits in the ciphertext, detect any forgery with probability not much below $1 - 2^{-\tau}$.

Forgery detection. Specifically, an adversary who can persuade you to reveal the encryption of up to $q$ messages of up to $128\ell$ bits and make $f$ forgery attempts has probability about $$O(q \ell^2) 2^{-128} + f 2^{-\tau}$$ of a single forgery success.

Do forgeries affect your application? Unless you have a really strong reason, specific to your application, to believe that forgery is not a danger—a convincing argument that an adversary can never influence messages in transit without detection, even if they can somehow read them—you should use cryptography to prevent it. What authentication tag size $\tau$ do you use? It depends on your budget, the cost of a forgery, and how long an adversary has to attempt a forgery.

How the secrecy works for uneven block sizes. The basic idea of the encryption part of AES-CCM, which in isolation (or with $\tau = 0$) is also called AES-CTR, is to use the 16-byte-to-16-byte permutation $\operatorname{AES}_k$ for a key $k$ to generate a one-time pad $$\operatorname{AES}_k(n\mathbin\|0) \mathbin\| \operatorname{AES}_k(n\mathbin\|1) \mathbin\| \cdots$$ with as many blocks as your message needs—in this case, two blocks—and xor the message with the pad. Here $n$ is the (say) 126-bit message nonce for an up to 256-bit = 32-byte message.

Nonce requirements. The size in bits of the nonce and the maximum message length in blocks must sum to at most 128, to fit in an AES block. The security is destroyed if the nonce ever repeats.

If instead of a message sequence number you choose a nonce uniformly at random, the expected number of messages before a security-destroying nonce collision is about $2^{63}$. For low volumes of data in an embedded application that has an RNG but can't keep state, especially if the messages are produced sequentially, that may be acceptable.

On the other hand, using a sequence number naturally defends against replay attacks: the receiver can imply reject all messages with sequence numbers older than the next one it expects (and buffer newer ones, if messages may be reordered).