您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Bros
- // ==UserScript==
- // @name Gitlab 2FA Token Auto Fill
- // @namespace https://github.com/JZ6/20220202
- // @version 1.0
- // @description Bros
- // @author JZ6
- // @match *://gitlab.com/*
- // @include *://git.*.com/*
- // @icon https://www.google.com/s2/favicons?domain=gitlab.com
- // @grant none
- // @require https://cdnjs.cloudflare.com/ajax/libs/jsSHA/3.2.0/sha1.min.js
- // ==/UserScript==
- const config = {
- entry: init,
- TOTPKey: '',
- autoSubmit: false,
- tokenRefreshPeriod: 30,
- localStorageKey: 'bros',
- defaultInput: 'Get the key from your profile/account page!',
- }
- config.entry()
- function init() {
- const TOTPInput = document.getElementById('user_otp_attempt')
- if (!TOTPInput) return
- loadTOTPKey()
- const TOTPToken = get2FAToken(config.TOTPKey)
- console.log(TOTPToken)
- TOTPInput.value = TOTPToken
- if (config.autoSubmit) {
- const submitButton = document.querySelector("div.prepend-top-20 input[name='commit']")
- submitButton.click()
- }
- // data-qa-selector="otp_secret_content"
- }
- function loadTOTPKey() {
- config.TOTPKey = localStorage.getItem(config.localStorageKey) || ''
- if (!config.TOTPKey || config.TOTPKey == 'null') {
- promptKeyInput()
- loadTOTPKey()
- return
- }
- if (config.TOTPKey == config.defaultInput) {
- alert('Please enter your 2FA Key from from your profile/account page!')
- promptKeyInput()
- loadTOTPKey()
- }
- }
- function saveTOTPKey() {
- localStorage.setItem(config.localStorageKey, config.TOTPKey)
- }
- function promptKeyInput() {
- let key = prompt('Enter your Gitlab Two Factor Key', config.defaultInput)
- config.TOTPKey = key
- saveTOTPKey()
- }
- function get2FAToken(TOTPKey) {
- const HEX = 'HEX'
- const hexSHA = new jsSHA('SHA-1', HEX)
- const hexadecimalKey = getHexadecimalKey(TOTPKey)
- hexSHA.setHMACKey(hexadecimalKey, HEX)
- const hexTime = getHexTime()
- hexSHA.update(hexTime)
- const HMACKey = hexSHA.getHMAC(HEX)
- return getTOTPToken(HMACKey)
- }
- function getHexadecimalKey(TOTPKey) {
- const base32chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'
- cleanKey = TOTPKey.replace(/\s+/g, '').replace(/=+$/, '')
- let binary = ''
- for (const c of cleanKey) {
- let val = base32chars.indexOf(c.toUpperCase())
- binary += paddingFill(val.toString(2), 5)
- }
- let hexadecimalKey = ''
- for (let i = 0; i + 8 <= binary.length; i += 8) {
- const byte = binary.slice(i, i + 8)
- const hexByte = parseInt(byte, 2).toString(16)
- hexadecimalKey += paddingFill(hexByte, 2)
- }
- return hexadecimalKey
- }
- function getHexTime() {
- const currentSecond = Math.round(Date.now() / 1000.0)
- const tokenRefreshTime = Math.floor(currentSecond / config.tokenRefreshPeriod)
- let hexTime = Math.round(tokenRefreshTime).toString(16)
- if (tokenRefreshTime < 15.5) {
- hexTime = `0${hexTime}`
- }
- return paddingFill(hexTime, 16)
- }
- function getTOTPToken(HMACKey) {
- const offset = parseInt(HMACKey.slice(-1), 16)
- const hexOffset = parseInt(HMACKey.substr(offset * 2, 8), 16)
- const mask = parseInt('7fffffff', 16)
- const TOTPToken = String(hexOffset & mask)
- return TOTPToken.slice(TOTPToken.length - 6)
- }
- function paddingFill(str, len) {
- if (len < str.length - 1) {
- return str
- }
- return Array(len - str.length + 1).join('0') + str
- }
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址