长久以来,登录跳板机都要忍受二步验证,工作效率大打折扣。忍无可忍,爆发了。

在网上搜到一篇讲模拟二步验证的博文《两步验证的使用和TOTP在Python中的基本实现》,示例代码简单可用,比github上动辄几百行靠谱的多。此文是模拟二步验证的基础,在此感谢原作者。

模拟二步验证


此部分借鉴上文所说的博文,结合实际情况增加了点改进,用文件缓存了计数器。

CACHE_PATH = '/tmp/cache.txt'
TWO_STEP_KEY = '此处填二步验证key'

def hotp(secret, counter):    
    basedSecret = base64.b32decode(secret, True)    
    structSecret = struct.pack(">Q", counter)    
    hmacSecret = hmac.new(basedSecret, structSecret, hashlib.sha1).digest()    
    ordSecret = ord(hmacSecret[19]) & 15    
    tokenSecret = (struct.unpack(">I", hmacSecret[ordSecret:ordSecret+4])[0] & 0x7fffffff) % 1000000    
    return tokenSecret

def totp(secret, period=30):
    counter = int(time.time()) // period

    try:
        f = open(CACHE_PATH, 'r')
        prev = f.read()
        f.close()
    except Exception, reason:
        #crt.Dialog.MessageBox(str(reason))
        prev = 0

    if counter <= int(prev):
        counter = int(prev) + 1

    try:
        f = open(CACHE_PATH, 'w')
        f.write(str(counter))
        f.close()
    except Exception, reason:
        crt.Dialog.MessageBox(str(reason))

    return hotp(secret, counter)

未完待续

#$language = "Python"
#$interface = "1.0"

import base64
import struct
import hmac 
import hashlib
import time

CACHE_PATH = '/tmp/cache.txt'
PASSWORD = '此处填你的密码'
TWO_STEP_KEY = '此处填二步验证key'

def hotp(secret, counter):    
    basedSecret = base64.b32decode(secret, True)    
    structSecret = struct.pack(">Q", counter)    
    hmacSecret = hmac.new(basedSecret, structSecret, hashlib.sha1).digest()    
    ordSecret = ord(hmacSecret[19]) & 15    
    tokenSecret = (struct.unpack(">I", hmacSecret[ordSecret:ordSecret+4])[0] & 0x7fffffff) % 1000000    
    return tokenSecret

def totp(secret, period=30):
    counter = int(time.time()) // period

    try:
        f = open(CACHE_PATH, 'r')
        prev = f.read()
        f.close()
    except Exception, reason:
        #crt.Dialog.MessageBox(str(reason))
        prev = 0

    if counter <= int(prev):
        counter = int(prev) + 1

    try:
        f = open(CACHE_PATH, 'w')
        f.write(str(counter))
        f.close()
    except Exception, reason:
        crt.Dialog.MessageBox(str(reason))

    return hotp(secret, counter)

def Main():
    tab = crt.GetScriptTab()

    if tab.Session.Connected != True:
        crt.Dialog.MessageBox(
            "Error.\n" +
            "This script was designed to be launched after a valid "+
            "connection is established.\n\n"+
            "Please connect to a remote machine before running this script.")
        return

    # Ensure that we don't "miss" data coming from the remote by setting
    # our Screen's Synchronous flag to true.
    tab.Screen.Synchronous = True

    tab.Screen.WaitForStrings(['Verification code:'])
    tab.Screen.Send(str(totp(TWO_STEP_KEY)) + "\r\n")
    tab.Screen.WaitForStrings(['Password:'])
    tab.Screen.Send(PASSWORD + "\r\n")

Main()