Golang implementation of Google authenticator CLI tools

Source: Internet
Author: User
Tags erro hmac sha1

Two-step authentication is used in many validations. If on the mobile client, if you use a computer, each time you have to take out the phone, manually entered. And worry about being out of date. Efficiency is not very high.

I am now dealing with the following ways:

    • Alfred Workflow Support on Mac
    • Chrom Extended Support
    • Mobile Client
    • CLI Logging Tool

Today mainly introduces the CLI tools, I am now in Golang, looking for some practiced hand projects.

First on the code

Package Mainimport ("FMT" "OS" "Log" "Sort" "github.com/urfave/cli" "Gopkg.in/ini.v1" "Crypto/hmac" "CRYPTO/SHA1" "Strings" "Encoding/base32" "Time" "Github.com/atotto/clipboard" "StrConv") func tobytes (VA Lue Int64) []byte {var result []byte Mask: = Int64 (0xFF) Shifts: = [8]uint16{56, max, 8, 0} fo R _, Shift: = range shifts {result = Append (result, byte ((value>>shift) &mask)} return Result}fun C toUint32 (bytes []byte) UInt32 {return (UInt32 (bytes[0]) <<) + (UInt32 (bytes[1]) << +) + (UINT (Bytes[2]) << 8) + UInt32 (bytes[3])}func Onetimepassword (key []byte, Value []byte] UInt32 {//Sign the value U Sing hmac-sha1 hmacSha1: = HMAC. New (SHA1. New, key) Hmacsha1.write (value) Hash: = Hmacsha1.sum (nil) Offset: = Hash[len (hash)-1] & 0x0F//Get a 32-bit (4-byte) chunk from the hash starting at offset hashparts: = hash[offset:offset+4]//IGnore the most significant bit as per RFC 4226 hashparts[0] = hashparts[0] & 0x7F Number: = ToUint32 (Hashparts) Size to 6 digits//One million are the first number with 7 digits so the remainder//of the Division would ALW Ays return < 7 digits pwd: = number% 1000000 return Pwd}func CLI () {app: = CLI. Newapp () app. Name = "Google authentiator CLI" app. Usage = "Create, List, Delete, Copy your GA" app. Version = "0.0.1" app. Commands = []CLI. Command {Name: "list", Aliases: []string{"L"}, Usage: "list | L ", Description:" List all item ", Category:" Show ", Action:func (c *cli.             Context) Error {list () return nil},}, {Name: "Show", Aliases: []string{"S"}, Usage: "Show | S github.com ", Description:" Show All Item ", Category:" Show ", Action:func (c *cli. ConText) Error {item: = C.args ().            First () Show (item) return nil},}, {Name: "Copy", Aliases: []string{"C"}, Usage: "Copy | C Github.com ", Usagetext:" Copy ga to Clipboard ", Category:" Show ", Action:func (c *cli.c Ontext) Error {Item: = C.args ().            First () copy (item) return nil},}, {Name: "Create", Aliases: []string{"R"}, Usage: "create| R github.com xxxxxxxxxx ", Usagetext:" Create a new GA Secrete item ", Category:" Store ", a Ction:func (c *cli. Context) Error {Item: = C.args ().        First () Secret: = C.args () [1] Create (item, secret) return nil}, }, {Name: "Modify", Aliases: []string{"M"}, Usage: "Modify | M gIthub.com xxxxxxxxx ", Usagetext:" Modify one item Secrete ", Category:" Store ", Action:fu NC (c *cli. Context) Error {Item: = C.args ().        First () Secret: = C.args () [1] Modify (item, secret) return nil}, }, {Name: "delete", Aliases: []string{"D"}, Usage: "Delete | D github.com ", Usagetext:" Delete one item Secrete ", Category:" Store ", Action:func (c *c Li. Context) Error {Delete (C.args (). First ()) return nil},},} app. Action = func (c *cli. Context) Error {FMT. PRINTLN ("can use List") return nil} sort. Sort (CLI. Flagsbyname (app. Flags)) Cli. Helpflag = CLI. Boolflag {Name: "Help, H", Usage: "help! Help! ","} CLI. Versionflag = CLI. Boolflag {Name: "print-version, V", Usage: "Print Version",} ERR: = App. Run (OS. Args) If err! = Nil {log. Fatal (Err)}}func Create (item, secret String) error {File,er:=os. Open ("/tmp/myga.ini") if er! = Nil {file, _ = os. Create ("/tmp/myga.ini")} file. Close () cfg, err: = ini. Load ("/tmp/myga.ini") if err! = Nil {panic (err)} If _, err: = cfg. GetSection (item); Err = = Nil {fmt.        PRINTLN (item + "is Exist!!!!") Os. Exit (1)} cfg. Newsection (item) cfg. Section (item). Key ("secret"). SetValue (Secret) cfg. SaveTo ("/tmp/myga.ini") return Nil}func Show (item string) error {File,er:=os. Open ("/tmp/myga.ini") if Er!=nil && os. Isnotexist (er) {fmt.        PRINTLN ("No Data!!!") Os. Exit (1)} file. Close () cfg, err: = ini. Load ("/tmp/myga.ini") if err! = Nil {panic (ERR)} section, Err: = cfg. GetSection (item) If Err! = Nil {panic (err)} key, Err: = section. GetKey ("secret") if err! = Nil {panic (err)} inputnospaces: = strIngs. Replace (key. String (), "", "" ",-1) Inputnospacesupper: = Strings. ToUpper (inputnospaces) KeyS, Erro: = Base32. Stdencoding.decodestring (inputnospacesupper) if erro! = nil {fmt. Fprintln (OS. Stderr, Err. Error ()) OS. Exit (1)}//Generate a one-time password using the time at 30-second intervals epochseconds: = time. Now (). Unix () pwd: = Onetimepassword (KeyS, Tobytes (EPOCHSECONDS/30)) Secondsremaining: =-(epochseconds%) fmt. Printf ("%06d (%d second (s) remaining) \ n", pwd, secondsremaining) return Nil}func copy (item string) error {file,er:= Os. Open ("/tmp/myga.ini") if Er!=nil && os. Isnotexist (er) {fmt.        PRINTLN ("No Data!!!") Os. Exit (1)} file. Close () cfg, err: = ini. Load ("/tmp/myga.ini") if err! = Nil {panic (ERR)} section, Err: = cfg. GetSection (item) If Err! = Nil {panic (err)} key, Err: = section. GetKey ("secret") if err! = Nil {panic (err)} InputnospaceS: = Strings. Replace (key. String (), "", "" ",-1) Inputnospacesupper: = Strings. ToUpper (inputnospaces) KeyS, Erro: = Base32. Stdencoding.decodestring (inputnospacesupper) if erro! = nil {fmt. Fprintln (OS. Stderr, Err. Error ()) OS. Exit (1)}//Generate a one-time password using the time at 30-second intervals epochseconds: = time. Now (). Unix () pwd: = Onetimepassword (KeyS, Tobytes (EPOCHSECONDS/30)) Secondsremaining: =-(epochseconds%) clipst r: = StrConv. The Itoa (int (pwd)) Clipboard. Writeall (CLIPSTR) fmt. Printf ("%06d (%d second (s) remaining) \ n", pwd, secondsremaining) return nil}func list () error {File,er:=os. Open ("/tmp/myga.ini") if Er!=nil && os. Isnotexist (er) {fmt.        PRINTLN ("No Data!!!") Os. Exit (1)} file. Close () cfg, err: = ini. Load ("/tmp/myga.ini") if err! = Nil {panic (ERR)} sections: = cfg. Sections () for _,v: = Range Sections {fmt. Println (V.name ())} return Nil}funcDelete (item string) error {File,er:=os. Open ("/tmp/myga.ini") if Er!=nil && os. Isnotexist (er) {file, _ = os. Create ("/tmp/myga.ini")} file. Close () cfg, err: = ini. Load ("/tmp/myga.ini") if err! = Nil {panic (err)} If _, err: = cfg. GetSection (item); Err! = Nil {fmt.        PRINTLN (item + "is not Exist!!!!") Os. Exit (1)} cfg. Deletesection (item) cfg. SaveTo ("/tmp/myga.ini") fmt.    PRINTLN ("OK!!!") Return Nil}func Modify (item string, secret String) error {File,er:=os. Open ("/tmp/myga.ini") if Er!=nil && os. Isnotexist (er) {file, _ = os. Create ("/tmp/myga.ini")} file. Close () cfg, err: = ini. Load ("/tmp/myga.ini") if err! = Nil {panic (err)} If _, err: = cfg. GetSection (item); Err! = Nil {fmt.        PRINTLN (item + "is not Exist!!!!") Os. Exit (1)} cfg. Section (item). Key ("secret"). SetValue (Secret) cfg. SaveTo ("/tmp/myga.ini") return Nil}func main () {Cli ()}

The functions implemented above have

    • GA creation, UPDATE, delete, data are saved locally
    • Show All Entries
    • Display the verification code, copy the verification code to the sticker board

The following describes the other ways and how GA works.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.