feat: Poprawiona obsługa hasła z klawiatury
This commit is contained in:
parent
473b76d1c9
commit
18c29e4621
16
README.md
16
README.md
@ -111,14 +111,13 @@ W efekcie, jeśli warunek jest spełniony, w katalogu wynikowym działania skryp
|
|||||||
|
|
||||||
## Obsługa plików szyfrowanych
|
## Obsługa plików szyfrowanych
|
||||||
|
|
||||||
Od wersji 0.2.0 plik z hasłami (pgpass) musi być zaszyforwany. Szyfrowanie można wykonać następującym poleceniem
|
Od wersji 0.2.1 plik z hasłami (pgpass) musi być zaszyforwany. Szyfrowanie można wykonać następującym poleceniem:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
multisql -P encrypt pgpass.sec pgpass
|
multisql encrypt pgpass.sec pgpass
|
||||||
```
|
```
|
||||||
|
|
||||||
Jeśli nie jest ustawiona zmienna środowiskowa MULTISQLPASS, to opcja -P powoduje, że program zapyta o hasło
|
Program zapyta o nowe hasło a następnie zaszyfruje treść pliku pgpass i zapisze go do pliku pgpass.sec.
|
||||||
a następnie zaszyfruje treść pliku pgpass i zapisze go do pliku pgpass.sec.
|
|
||||||
|
|
||||||
> Uwaga: plik pgpass.sec zostanie napisany bez pytania.
|
> Uwaga: plik pgpass.sec zostanie napisany bez pytania.
|
||||||
|
|
||||||
@ -132,7 +131,10 @@ multisql -P decrypt pgpass.sec # po udanym odszyfrowaniu wyświetli treść pli
|
|||||||
multisql -P decryp pgpass.sec newpgpass # w tym wariancie odszyfrowana treść zostanie zapisana do newpgpass
|
multisql -P decryp pgpass.sec newpgpass # w tym wariancie odszyfrowana treść zostanie zapisana do newpgpass
|
||||||
```
|
```
|
||||||
|
|
||||||
Żeby nie podawać hasła z klawiatury, należy ustawić je w zmiennej środowiskowej:
|
Opcja `-P` powoduje, że program pyta o hasło. Jeśli nie podano tej opcji, program
|
||||||
|
próbuje użyć hasła ustawionego w zmiennej środowiskowej `MULTISQLPASS`.
|
||||||
|
|
||||||
|
Zmienną można ustawić w następujący sposób:
|
||||||
|
|
||||||
Linux:
|
Linux:
|
||||||
|
|
||||||
@ -152,6 +154,4 @@ Windows, powershell:
|
|||||||
$env:MULTISQLPASS = "abc"
|
$env:MULTISQLPASS = "abc"
|
||||||
```
|
```
|
||||||
|
|
||||||
Program nigdy nie pyta o hasła, jeśli wczytał je ze zmiennej środowiskowej.
|
Użycie opcji `-P` powoduje, że zmienna środowiskowa jest ignorowana.
|
||||||
Jeśli nie podano hasła w zmiennej i nie podano
|
|
||||||
opcji `-P`, to program przerwie działanie.
|
|
||||||
|
@ -66,7 +66,7 @@ Użycie:
|
|||||||
multisql -outdir /tmp -sqldir /data/skrypty -passfile ./hasla
|
multisql -outdir /tmp -sqldir /data/skrypty -passfile ./hasla
|
||||||
|
|
||||||
Użycie w trybie szyfrowania:
|
Użycie w trybie szyfrowania:
|
||||||
multisql [-P] encrypt plik.wynikowy.zaszyfrowany plik.zródłowy
|
multisql encrypt plik.wynikowy.zaszyfrowany plik.zródłowy
|
||||||
lub
|
lub
|
||||||
multisql [-P] decrypt plik.źródłowy.zaszyfrowany [plik.wynikowy.jawny]
|
multisql [-P] decrypt plik.źródłowy.zaszyfrowany [plik.wynikowy.jawny]
|
||||||
|
|
||||||
|
@ -72,8 +72,6 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func encryption(args []string, params cfg.Parameters) {
|
func encryption(args []string, params cfg.Parameters) {
|
||||||
password := pass.GetMasterPass(params.AskPass)
|
|
||||||
|
|
||||||
switch strings.ToLower(args[0]) {
|
switch strings.ToLower(args[0]) {
|
||||||
case "encrypt":
|
case "encrypt":
|
||||||
if len(args) < 3 {
|
if len(args) < 3 {
|
||||||
@ -84,6 +82,9 @@ func encryption(args []string, params cfg.Parameters) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Błąd odczytu pliku: %v", err)
|
log.Fatalf("Błąd odczytu pliku: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
password := pass.EnterMasterPass()
|
||||||
|
|
||||||
err = pass.EncryptFile(password, args[1], plain)
|
err = pass.EncryptFile(password, args[1], plain)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Błąd szyfrowania pliku: %v", err)
|
log.Fatalf("Błąd szyfrowania pliku: %v", err)
|
||||||
@ -93,6 +94,8 @@ func encryption(args []string, params cfg.Parameters) {
|
|||||||
log.Fatal("decryp wymaga podania pliku zaszyfrowanego")
|
log.Fatal("decryp wymaga podania pliku zaszyfrowanego")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
password := pass.GetMasterPass(params.AskPass)
|
||||||
|
|
||||||
data, err := pass.DecryptFile(password, args[1])
|
data, err := pass.DecryptFile(password, args[1])
|
||||||
if err !=nil {
|
if err !=nil {
|
||||||
log.Fatalf("Błąd deszyfrowania pliku: %v", err)
|
log.Fatalf("Błąd deszyfrowania pliku: %v", err)
|
||||||
|
7
go.mod
7
go.mod
@ -2,4 +2,9 @@ module baal.ar76.eu/x/pub/multisql
|
|||||||
|
|
||||||
go 1.19
|
go 1.19
|
||||||
|
|
||||||
require golang.org/x/crypto v0.3.0 // indirect
|
require (
|
||||||
|
golang.org/x/crypto v0.3.0
|
||||||
|
golang.org/x/term v0.2.0
|
||||||
|
)
|
||||||
|
|
||||||
|
require golang.org/x/sys v0.2.0 // indirect
|
||||||
|
4
go.sum
4
go.sum
@ -1,2 +1,6 @@
|
|||||||
golang.org/x/crypto v0.3.0 h1:a06MkbcxBrEFc0w0QIZWXrH/9cCX6KJyWbBOIwAn+7A=
|
golang.org/x/crypto v0.3.0 h1:a06MkbcxBrEFc0w0QIZWXrH/9cCX6KJyWbBOIwAn+7A=
|
||||||
golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
||||||
|
golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A=
|
||||||
|
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/term v0.2.0 h1:z85xZCsEl7bi/KwbNADeBYoOP0++7W1ipu+aGnpwzRM=
|
||||||
|
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
||||||
|
@ -5,10 +5,8 @@ import (
|
|||||||
"crypto/cipher"
|
"crypto/cipher"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"baal.ar76.eu/x/pub/multisql/cfg"
|
|
||||||
"golang.org/x/crypto/scrypt"
|
"golang.org/x/crypto/scrypt"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -70,22 +68,22 @@ func Decrypt(key, data []byte) ([]byte, error) {
|
|||||||
return plaintext, nil
|
return plaintext, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func DecryptFile(password, file string) ([]byte, error) {
|
func DecryptFile(password []byte, file string) ([]byte, error) {
|
||||||
data, err := os.ReadFile(file)
|
data, err := os.ReadFile(file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
salt := data[:32] //
|
salt := data[:32] //
|
||||||
data = data[32:]
|
data = data[32:]
|
||||||
key, _, err := DeriveKey([]byte(password), salt)
|
key, _, err := DeriveKey(password, salt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return Decrypt(key, data)
|
return Decrypt(key, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
func EncryptFile(password, file string, data []byte) error {
|
func EncryptFile(password []byte, file string, data []byte) error {
|
||||||
key, salt, err := DeriveKey([]byte(password), nil)
|
key, salt, err := DeriveKey(password, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -108,17 +106,4 @@ func EncryptFile(password, file string, data []byte) error {
|
|||||||
return fd.Close()
|
return fd.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetMasterPass(askPass bool) string {
|
|
||||||
password := os.Getenv(cfg.MULTISQLPASS)
|
|
||||||
if password == "" {
|
|
||||||
if !askPass {
|
|
||||||
log.Fatalf("Nieustalone hasło. Użyj flagi -P lub ustaw hasło w zmiennej %s", cfg.MULTISQLPASS)
|
|
||||||
}
|
|
||||||
fmt.Fprintf(os.Stderr, "Podaj hasło: ")
|
|
||||||
n, e := fmt.Scanln(&password)
|
|
||||||
if n == 0 || e != nil {
|
|
||||||
log.Fatalln("Nie udało się wczytać hasła z konsoli")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return password
|
|
||||||
}
|
|
||||||
|
@ -18,7 +18,7 @@ type PassDb struct {
|
|||||||
cache map[string]*pgpassrow
|
cache map[string]*pgpassrow
|
||||||
}
|
}
|
||||||
|
|
||||||
func Load(file string, master string) (*PassDb, error) {
|
func Load(file string, master []byte) (*PassDb, error) {
|
||||||
|
|
||||||
data, err := DecryptFile(master, file)
|
data, err := DecryptFile(master, file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
55
pass/term.go
Normal file
55
pass/term.go
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
package pass
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"baal.ar76.eu/x/pub/multisql/cfg"
|
||||||
|
"golang.org/x/term"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetMasterPass(askPass bool) []byte {
|
||||||
|
if askPass {
|
||||||
|
res, err := termGetPassword("Podaj hasło")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln("Nie udało się wczytać hasła z konsoli")
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
password := os.Getenv(cfg.MULTISQLPASS)
|
||||||
|
|
||||||
|
if password != "" {
|
||||||
|
return []byte(password)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Fatalf("Nieustalone hasło. Użyj flagi -P lub ustaw hasło w zmiennej %s", cfg.MULTISQLPASS)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func EnterMasterPass() []byte {
|
||||||
|
p1, err := termGetPassword("Podaj nowe hasło (min 8 znaków)")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Błąd wczytywania hasła: %v", err)
|
||||||
|
}
|
||||||
|
if len(p1) < 8 {
|
||||||
|
log.Fatalf("podano zbyt krótkie hasło")
|
||||||
|
}
|
||||||
|
p2, err := termGetPassword("Powtórz nowe hasło")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Błąd wczytywania hasła: %v", err)
|
||||||
|
}
|
||||||
|
if !bytes.Equal(p1, p2) {
|
||||||
|
log.Fatalf("podane hasła są różne")
|
||||||
|
}
|
||||||
|
|
||||||
|
return p1
|
||||||
|
}
|
||||||
|
|
||||||
|
func termGetPassword(prompt string) ([]byte, error) {
|
||||||
|
fmt.Fprintf(os.Stderr, "%s: ", prompt)
|
||||||
|
passwd, err := term.ReadPassword(int(os.Stdin.Fd()))
|
||||||
|
fmt.Fprintln(os.Stderr)
|
||||||
|
return passwd, err
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user