I'm developing a device that will require ownership proof to activate HOTP authorizations. The HOTP codes will be used in the BLE bonding between the device and the owner's phone.

I came up with the following scheme: Upon fabrication, the device will generate

  1. HOTP context (Random key, and counter = 0) Let's call it C
  2. Random AES Key - Let's call it K
  3. Random 8 byte Salt
  4. It will generate Pt = Salt..C (.. is concatenation)
  5. and Cyphertext Ct = AES(K, Pt)
  6. It will store Salt and Ct in the Flash Memory
  7. It will send K to that fab controller which will print it in the Users Manual

The owner will enter the key from the Manual the device will use it to decode Ct from the flash to Pt and compare the stored Salt with decoded Salt. If they are equal the device will transmit decoded HOTP context to the owner...

All this to avoid storing the initial HOTP context unprotected in the flash. And I'm assuming that the printed K is not accessible to any person except the actual owner of the device

Any comments on this scheme?


An entire AES key is an awkward thing to manually enter from a printed manual. Even if the device has a proper keypad, a 128-bit AES key is 22 characters of base64 or 32 characters of hex. It's not impossible, and from a security perspective it's probably fine (so long as the printed K is indeed not visible to anybody else), but it's awkward.

I'm not sure why you're so worried about storing the HOTP context in plain text within the device, but are fine printing the AES key needed to decrypt the context in plain text within the manual. Unless it's a lot more likely that the device gets stolen (before activation, and without the manual) than that the entire package gets stolen including the manual or the device gets stolen after activation (presumably it then keeps the HOTP context in the clear, or it couldn't use HOTP without entering K every time...), you're not gaining much.

Is the salt doing anything other than checking if K is correct? If not, you should just store the cryptographic hash of K (e.g. sha256(K)) in the device flash, and verify it before doing the decryption. Alternatively, do authenticated encryption and check that the authentication tag is correct.

Speaking of authenticated encryption, you don't talk about the cipher mode you'll use at all. AES is a block cipher and doesn't natively handle plaintexts longer than one block (128 bits); for anything more (or less!) than that, you need a "mode of operation" and possibly padding. The most common mode is probably CBC, which uses an IV (Initialization Vector) and requires padding if the text isn't an exact multiple of the block length. CBC does not verify that the ciphertext hasn't been tampered with, and if padding is used you risk introducing a "padding oracle" that can completely break the encryption of the ciphertext; I don't really recommend using CBC. There are also authenticated encryption modes, such as GCM, which uses a nonce (like the IV) and an authentication tag (like a hash, you store it along with the ciphertext and check after decryption whether it matches the output of the decryption function; don't trust the decryption if the tag doesn't match). GCM doesn't use padding at all, and while it has some problems with very long messages, it's great for short ones.

Are you deleting Ct from the flash after the device is first activated? If so, do you have a way to re-activate it? If not, do you have a way to prevent an attacker from extracting C by stealing the manual and re-entering the code?

Do you have a way to rotate C? It seems like, if reactivation is supported, you might want a new C each time (in case the old one leaked, e.g. via a breach of the mobile app exposing C there, or the phone getting stolen). If not, a stolen phone with C on it means the device's security can't be trusted anymore because the HOTP code might be coming from an attacker with C; there's no way to revoke a phone.

How are you securing the transmission of decoded context C from the device to the phone during activation? If you don't yet have a secured bluetooth channel...

  • Dear @CBHaking, Thank you for your input. It made me realize that I failed to consider some aspects of the problem. Now to answer your concerns: 1. K will be printed as QRcode in the manual so there will be no problem entering it 2. Your advice on using sha256(K) or authenticated encryption is very useful indeed. 3. Your concern about the need to recycle C in case of phone theft is EXTREMELY on the mark as I didn't think about it at ALL.
    – Vadim
    Dec 8 '21 at 22:59
  • 4. The point about initial activation over yet insecure BLE channel is also valid - I initially thought the initial activation will be done in a secure environment but given the potential need to recycle C this assumption could be wrong. So it seems that I need to devize a scheme based on public key crypto....
    – Vadim
    Dec 8 '21 at 23:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.