Au 25 septembre 2020, certaines banques ont été piratées, mais aucune d'entre elles n'a d'authentification comme un mot de passe à usage unique. Bien sûr, si le mot de passe à usage unique est volé "pendant cette seule fois", il sera éliminé, mais il est plus difficile de voler le contenu de la communication à tout moment.
Cependant, le fait que le mécanisme de mot de passe à usage unique dépende d'un mécanisme externe tel que Google Authenticator est un risque dans un autre sens (comme des changements soudains dans les spécifications).
Alors, vérifiez tout ce que vous pouvez faire par vous-même.
Les éléments suivants sont combinés pour générer un condensé (sha256), et 6 chiffres de la valeur numérique sont extraits du condensé.
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)
#Arrondissez l'horodatage de secondes en minutes
ts_min = Time.now.to_i / 60
ts_min += 1 if next_min #Si vous voulez couvrir jusqu'à la minute suivante (le côté recevant le chèque)
text = "#{secret_key}_and_sault"
Digest::SHA256.hexdigest("#{text}#{ts_min}").to_i(16).to_s[-6, 6]
end
#En supposant qu'il ne durera qu'une minute, je serai en mesure d'obtenir le mot de passe après une minute
puts onetime_pass('secret_key')
puts onetime_pass('secret_key', true)
Vous pouvez voir que les mêmes 6 chiffres sont créés sur la face avant et côté serveur. (La deuxième ligne côté serveur est le mot de passe après 1 minute)
――Si vous écrivez JS pour la première fois depuis longtemps, quoi que vous fassiez, seules les promesses reviendront. J'ai écrit async et j'attends par essais et erreurs, mais je n'ai pas beaucoup de moi. ――Il semble que RFC a également la logique du mot de passe à usage unique correctement, mais j'en ai fini avec "Je suis sûr que c'est le cas" sans le lire. «J'ai écrit le côté terminal dans JS, mais l'essentiel" comment passer la clé privée "n'est pas mentionné dans cet article. Il semble bon de le transmettre avec un code QR, mais le programme qui lit le code QR et stocke la clé privée dans le stockage local côté terminal semble être beaucoup plus long que la source ci-dessus. Compte tenu de cela, Google Authenticator est utilisé et la bibliothèque côté serveur de Google Authenticator est utilisée, est-ce donc une solution? ――J'ai fait un condensé avec sha256, mais quand je retire les 6 derniers chiffres en décimal, la probabilité de collision augmente.
Recommended Posts