
Rework gauth.Code as gauth.Codes, which returns the previous, current, and next strings in one step. Remove authCodeOrDie, since there is now only one decode step to check. The implementation now uses the bitbucket.org/creachadair/otp package, which makes the code simpler and subsumes normalizeSecret.
90 lines
1.8 KiB
Go
90 lines
1.8 KiB
Go
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/aes"
|
|
"crypto/cipher"
|
|
"crypto/sha256"
|
|
"encoding/csv"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"log"
|
|
"os"
|
|
"os/user"
|
|
"path"
|
|
"strings"
|
|
"syscall"
|
|
"text/tabwriter"
|
|
|
|
"github.com/pcarrier/gauth/gauth"
|
|
"golang.org/x/crypto/ssh/terminal"
|
|
)
|
|
|
|
func main() {
|
|
user, e := user.Current()
|
|
if e != nil {
|
|
log.Fatal(e)
|
|
}
|
|
cfgPath := path.Join(user.HomeDir, ".config/gauth.csv")
|
|
|
|
cfgContent, e := ioutil.ReadFile(cfgPath)
|
|
if e != nil {
|
|
log.Fatal(e)
|
|
}
|
|
|
|
// Support for 'openssl enc -aes-128-cbc -md sha256 -pass pass:'
|
|
if bytes.HasPrefix(cfgContent, []byte("Salted__")) {
|
|
fmt.Printf("Encryption password: ")
|
|
passwd, e := terminal.ReadPassword(int(syscall.Stdin))
|
|
fmt.Printf("\n")
|
|
if e != nil {
|
|
log.Fatal(e)
|
|
}
|
|
salt := cfgContent[8:16]
|
|
rest := cfgContent[16:]
|
|
salting := sha256.New()
|
|
salting.Write([]byte(passwd))
|
|
salting.Write(salt)
|
|
sum := salting.Sum(nil)
|
|
key := sum[:16]
|
|
iv := sum[16:]
|
|
block, e := aes.NewCipher(key)
|
|
if e != nil {
|
|
log.Fatal(e)
|
|
}
|
|
|
|
mode := cipher.NewCBCDecrypter(block, iv)
|
|
mode.CryptBlocks(rest, rest)
|
|
// Remove padding
|
|
i := len(rest) - 1
|
|
for rest[i] < 16 {
|
|
i--
|
|
}
|
|
cfgContent = rest[:i]
|
|
}
|
|
|
|
cfgReader := csv.NewReader(bytes.NewReader(cfgContent))
|
|
// Unix-style tabular
|
|
cfgReader.Comma = ':'
|
|
|
|
cfg, e := cfgReader.ReadAll()
|
|
if e != nil {
|
|
log.Fatal(e)
|
|
}
|
|
|
|
currentTS, progress := gauth.IndexNow()
|
|
|
|
tw := tabwriter.NewWriter(os.Stdout, 0, 8, 1, ' ', 0)
|
|
fmt.Fprintln(tw, "\tprev\tcurr\tnext")
|
|
for _, record := range cfg {
|
|
name, secret := record[0], record[1]
|
|
prev, curr, next, err := gauth.Codes(secret, currentTS)
|
|
if err != nil {
|
|
log.Fatalf("Code: %v", err)
|
|
}
|
|
fmt.Fprintf(tw, "%s\t%s\t%s\t%s\n", name, prev, curr, next)
|
|
}
|
|
tw.Flush()
|
|
fmt.Printf("[%-29s]\n", strings.Repeat("=", progress))
|
|
}
|