Bis zum 25. September 2020 wurden einige Banken geknackt, aber keine von ihnen verfügt über eine Authentifizierung wie ein Einmalpasswort. Wenn das Einmalpasswort "während dieser einmaligen Zeit" gestohlen wird, ist es natürlich nicht verfügbar, aber es ist für die Person schwierig, den Kommunikationsinhalt jederzeit zu stehlen.
Die Tatsache, dass der Einmalkennwortmechanismus von einem externen Mechanismus wie Google Authenticator abhängt, ist jedoch in einem anderen Sinne ein Risiko (z. B. plötzliche Änderungen der Spezifikationen).
Überprüfen Sie also, wie viel Sie selbst tun können.
Die folgenden Elemente werden kombiniert, um einen Digest (sha256) zu generieren, und 6 Ziffern des numerischen Werts werden aus dem Digest extrahiert.
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>
onetime.rb
require 'digest/sha1'
def onetime_pass(secret_key, next_min = false)
#Runden Sie den Zeitstempel von Sekunden auf Minuten
ts_min = Time.now.to_i / 60
ts_min += 1 if next_min #Wenn Sie bis zur nächsten Minute abdecken möchten (die Seite, die den Scheck erhält)
text = "#{secret_key}_and_sault"
Digest::SHA256.hexdigest("#{text}#{ts_min}").to_i(16).to_s[-6, 6]
end
#Unter der Annahme, dass es nur eine Minute dauert, kann ich das Passwort nach einer Minute erhalten
puts onetime_pass('secret_key')
puts onetime_pass('secret_key', true)
Sie können sehen, dass auf der Vorderseite und der Serverseite dieselben 6 Ziffern erstellt werden. (Die zweite Zeile auf der Serverseite ist das Passwort nach 1 Minute)
――Wenn Sie JS zum ersten Mal seit langer Zeit schreiben, kommen nur Versprechen zurück, egal was Sie tun. Ich habe asynchron geschrieben und warte auf Versuch und Irrtum, aber ich habe nicht viel von mir. ――Es scheint, dass RFC auch die Logik eines Einmalkennworts richtig hat, aber anstatt es zu lesen, bin ich sicher, dass es so ist ――Ich habe die Terminalseite in JS geschrieben, aber das wesentliche "Übergeben des privaten Schlüssels" wird in diesem Artikel nicht erwähnt. Es scheint gut, es mit einem QR-Code zu übergeben, aber das Programm, das den QR-Code liest und den privaten Schlüssel im lokalen Speicher auf der Terminalseite speichert, scheint viel länger zu sein als die obige Quelle. In Anbetracht dessen wird Google Authenticator verwendet und die Bibliothek auf der Serverseite von Google Authenticator wird verwendet. Ist dies also eine Lösung? ――Ich habe mit sha256 einen Digest erstellt, aber wenn ich die letzten 6 Ziffern dezimal herausnehme, erhöht sich die Kollisionswahrscheinlichkeit.