128 lines
2.5 KiB
Go
128 lines
2.5 KiB
Go
package encryption
|
|
|
|
import (
|
|
"archive/tar"
|
|
"bytes"
|
|
"encoding/base64"
|
|
"encoding/json"
|
|
"io"
|
|
|
|
"filippo.io/age"
|
|
"github.com/pojntfx/stfs/internal/noop"
|
|
"github.com/pojntfx/stfs/internal/pax"
|
|
"github.com/pojntfx/stfs/pkg/config"
|
|
"golang.org/x/crypto/openpgp"
|
|
)
|
|
|
|
func Encrypt(
|
|
dst io.Writer,
|
|
encryptionFormat string,
|
|
recipient interface{},
|
|
) (io.WriteCloser, error) {
|
|
switch encryptionFormat {
|
|
case config.EncryptionFormatAgeKey:
|
|
recipient, ok := recipient.(*age.X25519Recipient)
|
|
if !ok {
|
|
return nil, config.ErrRecipientUnparsable
|
|
}
|
|
|
|
return age.Encrypt(dst, recipient)
|
|
case config.EncryptionFormatPGPKey:
|
|
recipient, ok := recipient.(openpgp.EntityList)
|
|
if !ok {
|
|
return nil, config.ErrRecipientUnparsable
|
|
}
|
|
|
|
return openpgp.Encrypt(dst, recipient, nil, nil, nil)
|
|
case config.NoneKey:
|
|
return noop.AddClose(dst), nil
|
|
default:
|
|
return nil, config.ErrEncryptionFormatUnsupported
|
|
}
|
|
}
|
|
|
|
func EncryptHeader(
|
|
hdr *tar.Header,
|
|
encryptionFormat string,
|
|
recipient interface{},
|
|
) error {
|
|
if encryptionFormat == config.NoneKey {
|
|
return nil
|
|
}
|
|
|
|
newHdr := &tar.Header{
|
|
Format: tar.FormatPAX,
|
|
Size: hdr.Size,
|
|
PAXRecords: map[string]string{},
|
|
}
|
|
|
|
wrappedHeader, err := json.Marshal(hdr)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
newHdr.PAXRecords[pax.STFSRecordEmbeddedHeader], err = EncryptString(string(wrappedHeader), encryptionFormat, recipient)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
*hdr = *newHdr
|
|
|
|
return nil
|
|
}
|
|
|
|
func EncryptString(
|
|
src string,
|
|
encryptionFormat string,
|
|
recipient interface{},
|
|
) (string, error) {
|
|
switch encryptionFormat {
|
|
case config.EncryptionFormatAgeKey:
|
|
recipient, ok := recipient.(*age.X25519Recipient)
|
|
if !ok {
|
|
return "", config.ErrRecipientUnparsable
|
|
}
|
|
|
|
out := &bytes.Buffer{}
|
|
w, err := age.Encrypt(out, recipient)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
if _, err := io.WriteString(w, src); err != nil {
|
|
return "", err
|
|
}
|
|
|
|
if err := w.Close(); err != nil {
|
|
return "", err
|
|
}
|
|
|
|
return base64.StdEncoding.EncodeToString(out.Bytes()), nil
|
|
case config.EncryptionFormatPGPKey:
|
|
recipient, ok := recipient.(openpgp.EntityList)
|
|
if !ok {
|
|
return "", config.ErrRecipientUnparsable
|
|
}
|
|
|
|
out := &bytes.Buffer{}
|
|
w, err := openpgp.Encrypt(out, recipient, nil, nil, nil)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
if _, err := io.WriteString(w, src); err != nil {
|
|
return "", err
|
|
}
|
|
|
|
if err := w.Close(); err != nil {
|
|
return "", err
|
|
}
|
|
|
|
return base64.StdEncoding.EncodeToString(out.Bytes()), nil
|
|
case config.NoneKey:
|
|
return src, nil
|
|
default:
|
|
return "", config.ErrEncryptionFormatUnsupported
|
|
}
|
|
}
|