1
0
mirror of https://github.com/getsops/sops.git synced 2026-02-05 21:45:26 +01:00
Files
sops/decrypt/decrypt.go
2018-10-29 21:50:13 +01:00

78 lines
2.1 KiB
Go

/*
Package decrypt is the external API other Go programs can use to decrypt SOPS files. It is the only package in SOPS with
a stable API.
*/
package decrypt // import "go.mozilla.org/sops/decrypt"
import (
"fmt"
"io/ioutil"
"time"
"go.mozilla.org/sops"
"go.mozilla.org/sops/aes"
sopsjson "go.mozilla.org/sops/stores/json"
sopsyaml "go.mozilla.org/sops/stores/yaml"
sopsdotenv "go.mozilla.org/sops/stores/dotenv"
)
// File is a wrapper around Data that reads a local encrypted
// file and returns its cleartext data in an []byte
func File(path, format string) (cleartext []byte, err error) {
// Read the file into an []byte
encryptedData, err := ioutil.ReadFile(path)
if err != nil {
return nil, fmt.Errorf("Failed to read %q: %v", path, err)
}
return Data(encryptedData, format)
}
// Data is a helper that takes encrypted data and a format string,
// decrypts the data and returns its cleartext in an []byte.
// The format string can be `json`, `yaml`, `dotenv` or `binary`.
// If the format string is empty, binary format is assumed.
func Data(data []byte, format string) (cleartext []byte, err error) {
// Initialize a Sops JSON store
var store sops.Store
switch format {
case "json":
store = &sopsjson.Store{}
case "yaml":
store = &sopsyaml.Store{}
case "dotenv":
store = &sopsdotenv.Store{}
default:
store = &sopsjson.BinaryStore{}
}
// Load SOPS file and access the data key
tree, err := store.LoadEncryptedFile(data)
if err != nil {
return nil, err
}
key, err := tree.Metadata.GetDataKey()
if err != nil {
return nil, err
}
// Decrypt the tree
cipher := aes.NewCipher()
mac, err := tree.Decrypt(key, cipher)
if err != nil {
return nil, err
}
// Compute the hash of the cleartext tree and compare it with
// the one that was stored in the document. If they match,
// integrity was preserved
originalMac, err := cipher.Decrypt(
tree.Metadata.MessageAuthenticationCode,
key,
tree.Metadata.LastModified.Format(time.RFC3339),
)
if originalMac != mac {
return nil, fmt.Errorf("Failed to verify data integrity. expected mac %q, got %q", originalMac, mac)
}
return store.EmitPlainFile(tree.Branch)
}