Compare commits
8 Commits
c3c506e206
...
c9cb1bb2d8
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c9cb1bb2d8 | ||
|
|
5184859c54 | ||
|
|
bd018136d6 | ||
|
|
d924708a1c | ||
|
|
5f13d1d409 | ||
|
|
d5192456ce | ||
|
|
3161afeb3b | ||
|
|
a873717f17 |
@ -11,4 +11,5 @@ Exact amount of required characters can be calculated by formula: $\lceil 256 /
|
||||
|
||||
## TODO
|
||||
[X] piped/terminal output as raw/verbose
|
||||
[ ] handle broken pipe signal since program will so much depend on pipes
|
||||
[X] handle broken pipe signal since program will so much depend on pipes
|
||||
[ ] option to read hex number that will be used instead of hash of password (usefull if user already has sha 256 hash of smth or want to use something else as input instead)
|
||||
|
||||
@ -7,8 +7,10 @@ import (
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"os/signal"
|
||||
"slices"
|
||||
"strconv"
|
||||
"syscall"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
@ -44,7 +46,76 @@ Each word or number is mapped following this list:
|
||||
- stupid - no limit
|
||||
`
|
||||
|
||||
type Flags struct {
|
||||
RawOutput bool
|
||||
OutputFile string
|
||||
EntropyLevel int
|
||||
}
|
||||
|
||||
func main() {
|
||||
setSystemSignalHandlers()
|
||||
flags, err := parseFlags()
|
||||
if err != nil {
|
||||
errorf("error while parsing arguments: %s\n", err)
|
||||
}
|
||||
|
||||
passbytes, err := getPasswordBytes()
|
||||
if err != nil {
|
||||
errorf("Failed to get password, error: %s\n", err)
|
||||
}
|
||||
valid := isEntropyValid(passbytes, flags.EntropyLevel)
|
||||
if !valid {
|
||||
errorf("You should choose stroger password!!! (or change entropy level, read more with --help)\n")
|
||||
}
|
||||
|
||||
sum := sha256.Sum256(passbytes)
|
||||
|
||||
k, err := newX25519IdentityFromScalar(sum[:])
|
||||
if err != nil {
|
||||
errorf("internal error: %v", err)
|
||||
}
|
||||
|
||||
// if user is not seeing private keyfile, which also contains public key,
|
||||
// also duplicate public key it to stderr,
|
||||
// but if user sees public key via stdout, no need for duplication
|
||||
if flags.OutputFile != "" {
|
||||
if !flags.RawOutput {
|
||||
fmt.Printf("Public key: %s\n", k.Recipient())
|
||||
} else {
|
||||
fmt.Printf("%s", k.Recipient())
|
||||
}
|
||||
}
|
||||
|
||||
output := os.Stdout
|
||||
if flags.OutputFile != "" {
|
||||
output, err = os.Create(flags.OutputFile)
|
||||
if err != nil {
|
||||
errorf("failed to create output file, error: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
err = writeSecretKey(output, k, !flags.RawOutput)
|
||||
if err != nil {
|
||||
fmt.Printf("Failed to write secret key to file, error: %s\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
func setSystemSignalHandlers() {
|
||||
go handleSigpipe()
|
||||
}
|
||||
|
||||
func handleSigpipe() {
|
||||
c := make(chan os.Signal, 1)
|
||||
signal.Notify(c, os.Interrupt, syscall.SIGPIPE)
|
||||
|
||||
<-c
|
||||
|
||||
errorf("Recieved SIGPIPE. Check if your programs that give input or recieve input do not stops before this one")
|
||||
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
func parseFlags() (*Flags, error) {
|
||||
log.SetFlags(0)
|
||||
flag.Usage = func() { fmt.Fprintf(os.Stderr, "%s", usage) }
|
||||
|
||||
@ -62,48 +133,14 @@ func main() {
|
||||
|
||||
eLevel, err := parseEntropyLevel(entropyLevel)
|
||||
if err != nil {
|
||||
errorf("error while parsing --entropy-level argument: %s\n", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
passbytes, err := getPasswordBytes()
|
||||
if err != nil {
|
||||
errorf("Failed to get password, error: %s\n", err)
|
||||
}
|
||||
valid := isEntropyValid(passbytes, eLevel)
|
||||
if !valid {
|
||||
errorf("You should choose stroger password!!! (or change entropy level, read more with --help)\n")
|
||||
}
|
||||
|
||||
sum := sha256.Sum256(passbytes)
|
||||
|
||||
k, err := newX25519IdentityFromScalar(sum[:])
|
||||
if err != nil {
|
||||
errorf("internal error: %v", err)
|
||||
}
|
||||
|
||||
// if user is not seeing private keyfile, which also contains public key,
|
||||
// also duplicate public key it to stderr,
|
||||
// but if user sees public key via stdout, no need for duplication
|
||||
if outputFile != "" {
|
||||
if !rawOutput {
|
||||
fmt.Printf("Public key: %s\n", k.Recipient())
|
||||
} else {
|
||||
fmt.Printf("%s", k.Recipient())
|
||||
}
|
||||
}
|
||||
|
||||
output := os.Stdout
|
||||
if outputFile != "" {
|
||||
output, err = os.Create(outputFile)
|
||||
if err != nil {
|
||||
errorf("failed to create output file, error: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
err = writeSecretKey(output, k, !rawOutput)
|
||||
if err != nil {
|
||||
fmt.Printf("Failed to write secret key to file, error: %s\n", err)
|
||||
}
|
||||
return &Flags{
|
||||
RawOutput: rawOutput,
|
||||
OutputFile: outputFile,
|
||||
EntropyLevel: eLevel,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func parseEntropyLevel(entropyLevel string) (int, error) {
|
||||
@ -134,10 +171,17 @@ func isEntropyValid(passbytes []byte, entropyLevel int) bool {
|
||||
|
||||
func getPasswordBytes() ([]byte, error) {
|
||||
if term.IsTerminal(int(os.Stdin.Fd())) {
|
||||
fmt.Fprintf(os.Stderr, "Enter password: ")
|
||||
passbytes, err := term.ReadPassword(int(os.Stdin.Fd()))
|
||||
fmt.Println()
|
||||
return passbytes, err
|
||||
oldState, err := term.MakeRaw(0)
|
||||
defer term.Restore(0, oldState)
|
||||
|
||||
screen := struct {
|
||||
io.Reader
|
||||
io.Writer
|
||||
}{os.Stdin, os.Stdout}
|
||||
t := term.NewTerminal(screen, "")
|
||||
pass, err := t.ReadPassword("Enter pass: ")
|
||||
|
||||
return []byte(pass), err
|
||||
} else {
|
||||
return io.ReadAll(os.Stdin)
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user