1

I have a use case to generate one time codes, and need to, in some cases, verify them offline. A use case:

On arriving at customers door, the delivery agent needs to verify that they dropped off a letter. Before arriving, they send out a SMS to the client with a code. The delivery agents needs to type in the code to verify that the code is valid. Sometimes the agent doesn't have internet connection nor service on their phone. So they need a way to scan the code and verify it locally.

My first solution would be to have a private key which hashes a code. The private key has to be on the drivers phone as well, so they can decrypt the code offline and therefore mark it as "checked".

Is there a better way of validating hashes/codes offline if the backend is not reachable?

Mike Ounsworth
  • 57,707
  • 21
  • 150
  • 207
ohboy21
  • 113
  • 3
  • I'm not fully sure about your scenario. What you describe sounds more like generating a random password, sending it to the customer and saving it with an established password hash at the local device (i.e. slow hash and salt). Verification is thus like password verification - hash what the customer provides and see if it matches. When done delete the hashed password from the device to "mark" it as done. No OTP algorithms need to be involved in this. – Steffen Ullrich Mar 15 '21 at 16:22
  • Please give more context. Is the device trusted that's verifying the OTP? – cisnjxqu Mar 15 '21 at 16:51
  • For whom is the verification? Is it for the delivery driver to know that their delivery was recognized, or to ensure that the delivery took place? – cisnjxqu Mar 15 '21 at 16:53
  • What if the person receiving the parcel is not at home? What if a neighbor is taking the parcel in? – cisnjxqu Mar 15 '21 at 16:54

2 Answers2

1

You are trying to take something which is inherently online (sending and verifying an SMS OTP code) and make it offline. This is possible, but it will require great thought to do it correctly, and the approach you take will depend on your requirements (ie your question does not contain enough details to decide which is the best solution).

I think the first step is for you to examine security properties that a traditional online OTP system provides, and decide which are important for you to preserve in your offline system. Once you have this list of requirements laid out, the set of viable solutions will likely become obvious.


I am not intending to provide a complete list of security properties that OTP gives -- I leave that as an exercise for the reader -- but here are some ideas to get you started:

  • Uniqueness: Each SMS OTP code is unique and the client must provide the one sent to them (ie if the system currently has 1,000 active OTPs, then your offline system needs to only accept the one sent to this client and reject the other 999).
  • Lifetime / expiry: SMS OTP codes typically expire after 15 minutes. You will likely want your offline system to reject codes older than 15 mins (or whatever time period is appropriate for your offline use-case).
  • One-time use: As the name implies, OTPs are intended to be one-time use, ie you can only use them once. If this is a required property of your offline system, then you will have a significant engineering problem ahead of you.

Solution for "one-time" problem.

I don't know exactly your design requirements, but a solution that might satisfy the "one-time" property might look something like this:

  • Before leaving WiFi, the delivery driver indicates which customer they are delivering for and the time they expect to make the delivery,
  • The OTP server generates an OTP for that customer and gives the OTP code to the driver's app.
  • 15 minutes / 30 minutes / 1 hour / whatever before the expected delivery time, the system sends that code to the customer via SMS. (you will likely need to make the lifetime of this code long enough to account for variance in delivery times, for example maybe 24 hours is not unreasonable here). At this point the server no longer needs to know the OTP code and could delete it from the server's DB.
  • When the driver enters / scans the customer's code, their local offline app records that code as USED and will not accept it again.
  • Since the OTP server generated this OTP for offline use, the server will not accept it directly, and it will not give that OTP code to any other driver's app (it will generate a new OTP if a new driver takes over that delivery). This way that OTP code will only work against the intended driver's app, and only once.
Mike Ounsworth
  • 57,707
  • 21
  • 150
  • 207
  • Thanks a lot! With "one-time use": I assume I can make it one-time, by increasing the byte length? Which makes it way harder to type in again. I am thinking about Bitcoin public addresses here. I am not an Info Sec person, just an engineer fyi. – ohboy21 Mar 15 '21 at 16:36
  • @ohboy21 I'm not sure I understand how that makes it one-time-use? These days, most people copy&paste or scan a QR code; I very rarely need to type out an OTP code anymore and increasing the length will only cause user frustration. What you really want is the server to give an error *"This code has already been used"*. I updated my answer with how I imagine a solution like that might work. – Mike Ounsworth Mar 15 '21 at 16:48
  • Thanks! So the server generates the code, sends it to the driver, and waits until the driver marks it as used and sends it back to the server. Why does the server mark it as "offline" if it already waits for the confirmation of "being used"? It can wait 1 hour or 2 hours, right? – ohboy21 Mar 15 '21 at 17:05
  • With my suggestion above, I don't think the driver's app actually needs to communicate back to the server that the OTP was used. Because the driver's app is the only one that can ever accept this OTP, I think it is sufficient for the app to record locally that it was used. The server doesn't even need to store the OTP code once it has been handed to the driver's app. (though I suppose that at the end of the delivery run, the driver's app may need to update the server of the delivery status, including whether or not an OTP was used, but that's really a logging thing not a security thing). – Mike Ounsworth Mar 15 '21 at 17:15
  • This makes sense, thanks! So in the drivers app, I store the OTPs from the server, and match against the OTP from the receiver. There is a case where a OTP can be created twice - so like a 10 digits code with letters and numbers should be enough to make it unique? – ohboy21 Mar 15 '21 at 17:23
  • Since in my suggestion, all OTPs are generated by the central server, it could check if the new code is a collision of an existing code as part of the generation process (I assume any existing OTP system already does this?). The length is to prevent attackers from guessing the code. Length of OTPs is really a separate question, so I won't answer it in this thread. – Mike Ounsworth Mar 15 '21 at 17:28
0

Asynchronous OTP will be Solution.

Your OTP generator should generate OTP code based on Specific algorithm and your application should be able to validate that particular key. Same technology used in hardware OTP tokens. Code will be in activate status until it used.

But problem is you have to keep all of your data on local device, if user lost internet connections. Otherwise you can add code to specific form or page, it will not update anything. I am assuming that, if you want to complete your use case in proper way, it is required to have internet or network connectivity. Otherwise you should be able to update server when connection is activated. But it makes another problem if any human error like misspelling, user had to go back to or contact them again for verification. Not only that it is totally unsecured.

Infra
  • 650
  • 1
  • 6
  • 19
  • I'm not sure that I agree. With offline TOTP / HOTP tokens, it's the *client* which is offline, and it only has its own seed to protect. Here it is the *server* which is offline and must protect seeds for many users. I'm not sure that the security properties of an offline TOTP / HOTP token solution are trivial to apply here. – Mike Ounsworth Mar 15 '21 at 16:34
  • @MikeOunsworth i think, i have mentioned all points you have given..... – Infra Mar 15 '21 at 16:39