Sample to create one-time password on server side and client side

I made a one-time password logic

As of September 25, 2020, banks have been cracked for some reason, but none of them have authentication such as one-time passwords. Of course, if a one-time password is stolen "during that one-time", it will be out, but it is harder to steal the communication contents at all times.

However, the fact that the one-time password mechanism depends on an external mechanism such as Google Authenticator is a risk in another sense (such as sudden changes in specifications).

So, verify how much you can do on your own.

How does it work?

The following elements are combined to generate a digest (sha256), and 6 digits are extracted from the digest.

--Different private key for each user (client and server have the same private key) --Timestamp (This sample uses the integer part divided by 60 seconds) --Salt (long string held on the server side)

Sample source

Terminal side

onetime.js



async function digestMessage(message) {
  const encoder = new TextEncoder();
  const data = encoder.encode(message);
  const hash = crypto.subtle.digest('SHA-256', data);
  return hash;
}

function buf2hex(buffer) { // buffer is an ArrayBuffer
  return Array.prototype.map.call(new Uint8Array(buffer), x => ('00' + x.toString(16)).slice(-2)).join('');
}

async function onetimePass(secret_key){
  const ts_min = parseInt( Date.now() / 60000 ).toString();
  const buffer = await digestMessage(secret_key + '_and_sault' + ts_min);
  const hexString = '0x' + await buf2hex(buffer) ;
  const digitString = BigInt(hexString).toString(10);
  return digitString.slice(-6);
}

onetime.html


<html>
<script type="text/javascript" src="./onetime.js"></script>
<body>
<script>
(async () => {
document.write(await onetimePass('secret_key'));
})();
</script>
</body>
</html>

Server side

onetime.rb


require 'digest/sha1'

def onetime_pass(secret_key, next_min = false)
  #Round the timestamp from seconds to minutes
  ts_min = Time.now.to_i / 60
  ts_min += 1 if next_min #If you want to cover up to the next minute (the side receiving the check)
  text = "#{secret_key}_and_sault"
  Digest::SHA256.hexdigest("#{text}#{ts_min}").to_i(16).to_s[-6, 6]
end

#Assuming that it will span just one minute, we will be able to obtain the password after one minute.
puts onetime_pass('secret_key')
puts onetime_pass('secret_key', true)

Execution result

You can see that the same 6 digits are created on the front side and the server side. (The second line on the server side is the password after 1 minute)

image.png

Remaining part

――If you write JS for the first time in a long time, no matter what you do, only promises will come back. I wrote async and await by trial and error, but I don't have much of myself. ――It seems that RFC also has the logic of a one-time password properly, but I'm done with "I'm sure this is the case" without reading it. ――I wrote it in JS on the terminal side, but the essential "how to pass the private key" is not mentioned in this article. It seems good to pass it with a QR code, but the program that reads the QR code and stores the private key in the local storage on the terminal side seems to be much longer than the above source. Considering that, Google Authenticator is used, and the library on the server side of Google Authenticator is used, so is it a solution? ――I made a digest with sha256, but when the last 6 digits are taken out in decimal, the collision probability increases.

Recommended Posts

Sample to create one-time password on server side and client side
(Ruby on Rails6) How to create models and tables
How to create an application server on an EC2 instance on AWS
Apache Geode-Easy way to execute logic on the server side
How to run React and Rails on the same server
How to place and share SwiftLint config files on the server
How to create a web server on an EC2 instance on AWS
Stop resending from client to server
[Java] How to retrieve the parameters passed from html on the server side
How to create a server executable JAR and WAR with Spring gradle
Do your best with gRPC with ruby ​​on the server and PHP on the client
Debug with VSCode + Next.js + Docker (+ Chrome) (supports both server side and client side)
Volume of trying to create a Java Web application on Windows Server 2016
Sample to display (head-up) notifications on Android
Java implementation to create and solve mazes
Sample to create custom tag for JSP
Connect with VS Code from a Windows client to Docker on another server
[Spring sample code included] How to create a form and how to get multiple records
How to share on the host side (windows) and guest side (CentOS 7) with VirtualBox