GitHub Strict Standard 2FA Auto-Fill

100% RFC 6238 Standard TOTP Generator

スクリプトをインストールするには、Tampermonkey, GreasemonkeyViolentmonkey のような拡張機能のインストールが必要です。

You will need to install an extension such as Tampermonkey to install this script.

スクリプトをインストールするには、TampermonkeyViolentmonkey のような拡張機能のインストールが必要です。

スクリプトをインストールするには、TampermonkeyUserscripts のような拡張機能のインストールが必要です。

このスクリプトをインストールするには、Tampermonkeyなどの拡張機能をインストールする必要があります。

このスクリプトをインストールするには、ユーザースクリプト管理ツールの拡張機能をインストールする必要があります。

(ユーザースクリプト管理ツールは設定済みなのでインストール!)

Advertisement:

このスタイルをインストールするには、Stylusなどの拡張機能をインストールする必要があります。

このスタイルをインストールするには、Stylus などの拡張機能をインストールする必要があります。

このスタイルをインストールするには、Stylus tなどの拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

(ユーザースタイル管理ツールは設定済みなのでインストール!)

Advertisement:

このスクリプトの質問や評価の投稿はこちら通報はこちらへお寄せください
// ==UserScript==
// @name         GitHub Strict Standard 2FA Auto-Fill
// @name:ru      GitHub Автозаполнение 2FA
// @namespace    http://tampermonkey.net
// @version      3.0
// @description  100% RFC 6238 Standard TOTP Generator
// @description:ru Автоматически вычисляет и вводит 6-значные коды двухфакторной аутентификации (2FA) для GitHub. Работает на старых браузерах без сбоев математики.
// @icon         data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiIgd2lkdGg9IjQ4IiBoZWlnaHQ9IjQ4Ij48cGF0aCBmaWxsPSIjMjQyOTJlIiBkPSJNOCAwQzMuNTggMCAwIDMuNTggMCA4YzAgMy41NCAyLjI5IDYuNTMgNS40NyA3LjU5LjQuMDcuNTUtLjE3LjU1LS4zOCAwLS4xOS0uMDEtLjgyLS4wMS0xLjQ5LTIuMDEuMzctMi41My0uNDktMi42OS0uOTQtLjA5LS4yMy0uNDgtMS4wMS0uODItMS4yLS4yOC0uMTUtLjY4LS41Mi0uMDEtLjUzLjYzLS4wMSAxLjA4LjU4IDEuMjMgLjgyLjcyIDEuMjEgMS44Ny44NyAyLjMzLjY2LjA3LS41Mi4yOC0uODcuNTEtMS4wNy0xLjc4LS4yLTMuNjQtLjg5LTMuNjQtMy45NSAwLS44Ny4zMS0xLjU5LjgyLTIuMTUtLjA4LS4yLS4zNi0xLjAyLjA4LTIuMTIgMCAwIC42Ny0uMjEgMi4yIC44Mi42NC0uMTggMS4zMi0uMjcgMi0uMjcuNjggMCAxLjM2LjA5IDIgLjI3IDEuNTMtMS4wNCAyLjItLjgyIDIuMi0uODIsLjQ0IDEuMS4xNiAxLjkyLjA4IDIuMTIuNTEuNTYuODIgMS4yNy44MiAyLjE1IDAgMy4wNy0xLjg3IDMuNzUtMy42NSAzLjk1LjI5LjI1LjU0LjczLjU0IDEuNDggMCAxLjA3LS4wMSAxLjkzLS4wMSAyLjIgMCAuMjEuMTUuNDYuNTUuMzhDMTMuNzEgMTQuNTMgMTYgMTEuNTMgMTYgOEMxNiAzLjU4IDEyLjQyIDAgOCAwWiIvPjwvc3ZnPg==
// @match        https://github.com/sessions/two-factor*
// @match        https://github.com/sessions/two-factor/app*
// @grant        none
// @run-at       document-end
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    // ИНСТРУКЦИЯ ДЛЯ ПОЛЬЗОВАТЕЛЕЙ / INSTRUCTION:
    // Вставьте ваш личный текстовый секретный ключ 2FA (2FA setup key) вместо слова "YOUR_SECRET_KEY" ниже.
    // Insert your personal 2FA setup text key instead of "YOUR_SECRET_KEY" below.
    var SECRET = "YOUR_SECRET_KEY";

    // 1. Safe Base32 Decoder to Byte Buffer (Bypassing ESLint redeclare)
    function base32ToBuf(b32) {
        var alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
        var cleaned = b32.replace(/[\s=]/g, "").toUpperCase();
        var bits = "";
        var idx;
        
        for (idx = 0; idx < cleaned.length; idx++) {
            var val = alphabet.indexOf(cleaned.charAt(idx));
            bits += (val === -1 ? 0 : val).toString(2).padStart(5, '0');
        }
        var buf = new Uint8Array(Math.floor(bits.length / 8));
        for (idx = 0; idx < buf.length; idx++) {
            buf[idx] = parseInt(bits.substr(idx * 8, 8), 2);
        }
        return buf.buffer;
    }

    // 2. Async hardware TOTP implementation via WebCrypto API
    function calculateSystemTOTP(secret32, callback) {
        try {
            if (!secret32 || secret32 === "YOUR_SECRET_KEY") return callback("");
            var keyBuf = base32ToBuf(secret32);
            var epoch = Math.floor(new Date().getTime() / 1000);
            var counter = Math.floor(epoch / 30);
            var idx;

            var timeBuf = new Uint8Array(8);
            for (idx = 7; idx >= 0; idx--) {
                timeBuf[idx] = counter & 0xff;
                counter = counter >> 8;
            }

            window.crypto.subtle.importKey(
                "raw", keyBuf, { name: "HMAC", hash: { name: "SHA-1" } }, false, ["sign"]
            ).then(function(cryptoKey) {
                return window.crypto.subtle.sign("HMAC", cryptoKey, timeBuf);
            }).then(function(signature) {
                var hmac = new Uint8Array(signature);
                var offset = hmac[hmac.length - 1] & 0x0f;
                var binary = ((hmac[offset] & 0x7f) << 24) | (hmac[offset + 1] << 16) | (hmac[offset + 2] << 8) | hmac[offset + 3];
                var otp = String(binary % 1000000);
                while (otp.length < 6) { otp = "0" + otp; }
                callback(otp);
            }).catch(function() {
                callback("");
            });
        } catch (e) {
            callback("");
        }
    }

    // 3. Execution Block
    setTimeout(function() {
        var inputField = document.getElementById('app_totp') || document.getElementById('otp') || document.querySelector('input[autocomplete="one-time-code"]');
        if (inputField) {
            calculateSystemTOTP(SECRET, function(code) {
                if (code && code.length === 6 && code !== "000000") {
                    inputField.value = code;

                    // Trigger input events for GitHub frontend scripts
                    var evs = ['input', 'change', 'keyup'];
                    evs.forEach(function(e) {
                        var event = document.createEvent('HTMLEvents');
                        event.initEvent(e, true, true);
                        inputField.dispatchEvent(event);
                    });

                    // Auto-submit form
                    setTimeout(function() {
                        var form = inputField.form;
                        if (form) {
                            var submitBtn = form.querySelector('button[type="submit"]') || form.querySelector('input[type="submit"]');
                            if (submitBtn) submitBtn.click();
                            else form.submit();
                        }
                    }, 200);
                }
            });
        }
    }, 600);
})();