일회용 암호를 서버 측과 클라이언트 측에서 만드는 샘플
일회용 비밀번호 로직을 만들어 보았습니다.
2020/09/25 현재는 무언가와 은행이 크랙 되고 있어도, 모두 원타임 패스워드와 같은 인증이 들어 있지 않다. 물론 원타임 패스워드도 '그 원타임 사이에' 훔치면 아웃이지만, 상시 통신 내용을 빼앗는 것은 훔치는 분도 힘들다.
다만, 일회용 비밀번호의 구조가 Google Authenticator 등의 외부의 구조에 의존하는 것은, 다른 의미로 리스크(갑자기 사양이 바뀌는 등).
그래서, 자기 앞에서 어디까지 할 수 있는지를 검증.
어떻게 움직이는가?
다음 요소를 조합하여 다이제스트(sha256)를 생성하고 다이제스트에서 숫자 6자리를 검색합니다.
샘플 소스
단말측
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)
# タイムスタンプを秒から分に丸める
ts_min = Time.now.to_i / 60
ts_min += 1 if next_min # 次の分までカバーしたい場合(チェックを受ける側)
text = "#{secret_key}_and_sault"
Digest::SHA256.hexdigest("#{text}#{ts_min}").to_i(16).to_s[-6, 6]
end
# ちょうど一分をまたがることを想定して、一分後のパスワードも取得できるようにしてる
puts onetime_pass('secret_key')
puts onetime_pass('secret_key', true)
실행 결과
프런트 측과 서버 측에서 같은 6자리수가 되어 있는 것을 알 수 있다.
(서버측의 니행째는, 1분 후의 패스워드)
마음 나머지
Reference
이 문제에 관하여(일회용 암호를 서버 측과 클라이언트 측에서 만드는 샘플), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/yugo-yamamoto/items/8388ccb750821b9746be텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)