1
0
mirror of https://github.com/ssh-vault/ssh-vault.git synced 2026-01-12 10:43:12 +03:00
Files
ssh-vault/view.go
2017-08-20 19:08:33 +02:00

115 lines
2.6 KiB
Go

package sshvault
import (
"bufio"
"bytes"
"crypto/x509"
"encoding/base64"
"encoding/pem"
"fmt"
"io/ioutil"
"os"
"strings"
"github.com/ssh-vault/crypto/aead"
"github.com/ssh-vault/crypto/oaep"
)
// View decrypts data and print it to stdout
func (v *vault) View() ([]byte, error) {
var (
header []string
rawPayload bytes.Buffer
scanner *bufio.Scanner
)
// check if there is someting to read on STDIN
stat, _ := os.Stdin.Stat()
if (stat.Mode() & os.ModeCharDevice) == 0 {
scanner = bufio.NewScanner(os.Stdin)
} else {
file, err := os.Open(v.vault)
if err != nil {
return nil, fmt.Errorf("missing vault name, use (\"%s -h\") for help", os.Args[0])
}
defer file.Close()
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++
}
// ssh-vault;AES256;fingerprint
if len(header) != 3 {
return nil, fmt.Errorf("bad ssh-vault signature, verify the input")
}
// password, body
payload := strings.Split(rawPayload.String(), ";")
if len(payload) != 2 {
return nil, fmt.Errorf("bad ssh-vault payload, verify the input")
}
// 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) {
keyPassword, err := v.GetPassword()
if err != nil {
return nil, fmt.Errorf("unable to get private key password, Decryption failed")
}
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", header[2])
}
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
}