Here is my use case:

A user is trying to transfer money to his friend's account. He enters transaction details on banking website. Bank receives it and then Bank sends transaction details (receiver name and amount) + One Time Password back to the user (may be through different channel : mobile) so that user can verify the transaction details (this is to ensure transaction integrity. ie., no man-in-the-middle attack) and enter the OTP to confirm the transaction.

What is the threat model?

Man-in-the-middle attack. If an attacker (in middle) modifies the receiver's bank account details with attacker controlled bank account but shows fake transaction summary, the OTP that sent along with the transaction details should become invalid.

What OTP generation algorithm should I use?

   someOTPgenAlgo(transaction details) = OTP.  

Now if the attacker changes the receiver bank account details, he also has to find the matching OTP for that modified transaction details Which should be impossible. How do I achieve this? Is following enough ?

someOTPgenALgo(transaction details + some random key ) = OTP

Thanks a lot. Sorry if the question is naive, I am pretty clueless about this

  • $\begingroup$ Welcome to crypto.se I took the liberty to edit your message to clarify that OTP is for One Time Password, not One Time Pad. Can you check that the bank first sends the OTP? That seems odd. $\endgroup$
    – fgrieu
    Oct 12, 2016 at 14:23
  • 1
    $\begingroup$ @fgrieu, First of all thank you for editing. What is odd about bank sending OTP back to the user along with the transaction details that he had entered earlier? That is how it normally works, right? User receives OTP + transaction details via SMS or some different channel. Then user verifies the transaction details and enter OTP to confirm the transaction. $\endgroup$
    – aMa
    Oct 12, 2016 at 15:02
  • $\begingroup$ Usually computing the OTP happens off channel, in a provided crypto device (a card reader together with the bank card, mobile phone, ...) $\endgroup$
    – gusto2
    Oct 12, 2016 at 15:04
  • $\begingroup$ @aMa: ah, that kind of OTP, where the communication link to the user is assumed secure. This is the opposite of the usual assumption in cryptography (by default we assume communication links can at least be passively eavesdropped). Like Gabriel Vince I was thinking of an OTP generated by a gizmo like this. $\endgroup$
    – fgrieu
    Oct 12, 2016 at 15:07

3 Answers 3


What you're imagining is impossible to be secure.

Basically what you're describing is a message authentication system where a message is MAC'ed and only the MAC is matched against the actual MAC, but it isn't checked whether the message actually generates this MAC, so an attacker could just fake the transaction details and leave the MAC be and the user would enter the MAC and thus accept the transaction.

Now I'm gonna tell you how many banks here in Germany solved the problem.
This assumes you've issued a card with a chip to every customer and keep track of all cards.
If the user wants to make a transaction, he uses his browser to fill in the data. Then the browser takes him to a page where he is either presented with an optical code (not unlike a QR code, but also using time-based patterns) or some data.
The user has to either scan the code or enter the data, into a physically separate device in which the user plugged the card. The data consists of the amount and the last few digits of the recipients account number. Now the device passes this data to the card which basically just performs HOTP but also incorporates the values for amount and recipient in the calculations. This is done after the user verified the correctness of the transaction on the built-in display. Now he's presented with a short code which he has to enter into the browser. The server confirms the calculations and initiates the transaction.

In a more mathyy way, the OTP would look like this:


  • $\begingroup$ how is it impossible to secure? $\endgroup$
    – aMa
    Oct 12, 2016 at 15:27
  • $\begingroup$ @aMa you send the user the transaction details for a reason, right? To let the user verify the transaction. But if you send them a code just for entering you may aswell leave the details out, because an attacker (a mitm) can forge this part of the message while not changing the OTP and thus keeping it valid. $\endgroup$
    – SEJPM
    Oct 12, 2016 at 15:30
  • $\begingroup$ I've actually used a banking system with a separate authentication device, and wondered why it didn't tie in the account number or the sum to the verification made with the device. But I don't think a QR code or anything unreadable by the human user would fill the need here, since if a man in the middle sends the bank different transaction orders from those shown to the user, the user couldn't check that the QR code verifies the correct transaction. $\endgroup$
    – ilkkachu
    Oct 12, 2016 at 17:30
  • $\begingroup$ @ilkkachu the devices I'm talking about are documented here and will show you the amount and the account number for verification before the TAN is generated and the TAN is only valid for this very recipient / amount pair. $\endgroup$
    – SEJPM
    Oct 12, 2016 at 17:33
  • $\begingroup$ @SEJPM, ah yes, that would obviously work, too, if the user actually checks the details shown by the machine before getting the verification code. What I was thinking was basically the "older variant" mentioned, which I think has the advantage that having the user manually enter the transaction details to the verifier device would make it harder for them to skip checking the said details... $\endgroup$
    – ilkkachu
    Oct 12, 2016 at 17:39

In your model, the OTP could simply be a random number generated by the bank, independent of a key or transaction details. All that matters is that the random number is unpredictable. 8-digit integers are typical. Not having a key is a great advantage, as it can't be compromised.

The bank receives the transaction details and alleged originating user, generates a random number, sends it to alleged originating user over a separate channel assumed unobservable by adversary; originating user checks details, and if it approves the transaction sends OTP in the same browser session that was used to send the transaction details; bank checks OTP is what it generated for that session (with a very small number of incorrect guesses allowed, e.g. 2), and only then performs the transaction using the details for that session.

This can be secure, even if the machine running the browser gets pwned or the browser's link is otherwise insecure, but only if

  • adversary can't intercept communication of OTP to alleged originating user; if the transmission is by SMS, weak points include pwned mobile phone (especially worrying if the browser is on the mobile phone, because we have a single point of failure), stolen mobile phone or SIM, rampant use of weak crypto in SMS messaging, and compromize of IT gear of the mobile phone operator.
  • and the user really checks all transaction details; which is far from certain.

Making the OTP a function of transaction details and a key does not work, unless the key changes constantly or time is also mixed in, because that is vulnerable to replay.


welcome to the crypto stackexchange :)

I'd suggest using HOTP, effectively it is a derivate of the OATH specification.

effectively both parties share a shared secret and a counter.

For each authentication the client computes OTP = HOTP(transaction + counter). This is often used in banks today. This approach assumes enrolling the OTP device (the bank usually provides the shared password and the initial counter state).

The counter increases with every transaction, so the replay shouldn't be possible. If there's no counter (or the counter is out of synchro), the challenge-response mode could be used. (as well to reset/synchronize the counter)

  • 1
    $\begingroup$ My use case is bit more simpler. Client don't have a device to generate OTP. It is bank generating it and sending it through a different channel (Encrypted or through Mobile network) to the client. So how to generate an OTP which should be something derived from transaction details that is my question. So attacker should never able to generate a valid OTP for a modified transaction. Does HOTP(transaction_details + random key + Counter) do the job? $\endgroup$
    – aMa
    Oct 12, 2016 at 15:14
  • $\begingroup$ I don't think HOTP would do anything to protect the transaction itself. It would make stealing login credentials harder, but if the threat is an MitM modifying the data shown on the browser, it's hard to protect against that with an OTP that isn't aware of the transaction details. $\endgroup$
    – ilkkachu
    Oct 12, 2016 at 17:26
  • $\begingroup$ @ilkkachu: In fact, HTOP is a protection against the MiM attack ensiring the transaction integrity. The signed (hashed) data usually consists of the account number (or part of it) and the amount. Any change in these data would result in different computed OTP on the server side. (that's why another channel is used). As well it serves as a non-repudiation signature. (as the server-only SSL doesn't ensure the client's identity) $\endgroup$
    – gusto2
    Oct 12, 2016 at 19:12
  • $\begingroup$ @aMa: in the case the bank only sends an off-channel message (e.g. random SMS code), I'd consider it as multi-factor authentication. The integrity itself (between a browser and the server) is ensured by SSL. $\endgroup$
    – gusto2
    Oct 12, 2016 at 19:17
  • $\begingroup$ @GabrielVince, HOTP is defined as a HMAC of a counter with a shared key (with the resulting value truncated). There's no provision for any additional data. Now, of course it would be possible to calculate a MAC over the relevant details and form a verification code, but that's not HOTP any longer. $\endgroup$
    – ilkkachu
    Oct 12, 2016 at 19:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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