mirror of
https://github.com/ssh-vault/ssh-vault.git
synced 2025-07-03 03:22:34 +03:00
modified: close.go modified: cmd/ssh-vault/main.go modified: vault.go modified: vault_test.go modified: view.go
106 lines
2.2 KiB
Go
106 lines
2.2 KiB
Go
package sshvault
|
|
|
|
import (
|
|
"bufio"
|
|
"bytes"
|
|
"crypto/x509"
|
|
"encoding/base64"
|
|
"encoding/pem"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"os"
|
|
"strings"
|
|
"syscall"
|
|
|
|
"github.com/ssh-vault/crypto/aead"
|
|
"github.com/ssh-vault/crypto/oaep"
|
|
|
|
"golang.org/x/crypto/ssh/terminal"
|
|
)
|
|
|
|
// View decrypts data and print it to stdout
|
|
func (v *vault) View() ([]byte, error) {
|
|
file, err := os.Open(v.vault)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer file.Close()
|
|
|
|
var (
|
|
// ssh-vault;AES256;fingerprint
|
|
header []string
|
|
rawPayload bytes.Buffer
|
|
)
|
|
|
|
scanner := bufio.NewScanner(file)
|
|
scanner.Split(bufio.ScanLines)
|
|
l := 1
|
|
for scanner.Scan() {
|
|
line := scanner.Text()
|
|
if l == 1 {
|
|
header = strings.Split(line, ";")
|
|
} else {
|
|
rawPayload.WriteString(line)
|
|
}
|
|
l++
|
|
}
|
|
|
|
// password, body
|
|
payload := strings.Split(rawPayload.String(), ";")
|
|
|
|
// use private key only
|
|
if strings.HasSuffix(v.key, ".pub") {
|
|
v.key = strings.Trim(v.key, ".pub")
|
|
}
|
|
|
|
keyFile, err := ioutil.ReadFile(v.key)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Error reading private key: %s", err)
|
|
}
|
|
|
|
block, _ := pem.Decode(keyFile)
|
|
if block == nil || block.Type != "RSA PRIVATE KEY" {
|
|
return nil, fmt.Errorf("No valid PEM (private key) data found")
|
|
}
|
|
|
|
if x509.IsEncryptedPEMBlock(block) {
|
|
fmt.Print("Enter key password: ")
|
|
keyPassword, err := terminal.ReadPassword(int(syscall.Stdin))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
fmt.Println()
|
|
block.Bytes, err = x509.DecryptPEMBlock(block, keyPassword)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Password incorrect, Decryption failed.")
|
|
}
|
|
}
|
|
|
|
privateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
ciphertext, err := base64.StdEncoding.DecodeString(payload[0])
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
v.Password, err = oaep.Decrypt(privateKey, ciphertext, []byte(""))
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Decryption failed, use private key with fingerprint: %s", v.Fingerprint)
|
|
}
|
|
|
|
ciphertext, err = base64.StdEncoding.DecodeString(payload[1])
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// decrypt ciphertext using fingerprint as additionalData
|
|
data, err := aead.Decrypt(v.Password, ciphertext, []byte(header[2]))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return data, nil
|
|
}
|