refactor: Split keys and keyext packages, make compression, signature and encryption packages public
This commit is contained in:
@@ -0,0 +1,141 @@
|
||||
package encryption
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"io"
|
||||
|
||||
"filippo.io/age"
|
||||
"github.com/ProtonMail/go-crypto/openpgp"
|
||||
"github.com/pojntfx/stfs/internal/records"
|
||||
"github.com/pojntfx/stfs/pkg/config"
|
||||
)
|
||||
|
||||
func Decrypt(
|
||||
src io.Reader,
|
||||
encryptionFormat string,
|
||||
identity interface{},
|
||||
) (io.ReadCloser, error) {
|
||||
switch encryptionFormat {
|
||||
case config.EncryptionFormatAgeKey:
|
||||
identity, ok := identity.(*age.X25519Identity)
|
||||
if !ok {
|
||||
return nil, config.ErrIdentityUnparsable
|
||||
}
|
||||
|
||||
r, err := age.Decrypt(src, identity)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return io.NopCloser(r), nil
|
||||
case config.EncryptionFormatPGPKey:
|
||||
identity, ok := identity.(openpgp.EntityList)
|
||||
if !ok {
|
||||
return nil, config.ErrIdentityUnparsable
|
||||
}
|
||||
|
||||
r, err := openpgp.ReadMessage(src, identity, nil, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return io.NopCloser(r.UnverifiedBody), nil
|
||||
case config.NoneKey:
|
||||
return io.NopCloser(src), nil
|
||||
default:
|
||||
return nil, config.ErrEncryptionFormatUnsupported
|
||||
}
|
||||
}
|
||||
|
||||
func DecryptHeader(
|
||||
hdr *tar.Header,
|
||||
encryptionFormat string,
|
||||
identity interface{},
|
||||
) error {
|
||||
if encryptionFormat == config.NoneKey {
|
||||
return nil
|
||||
}
|
||||
|
||||
if hdr.PAXRecords == nil {
|
||||
return config.ErrTarHeaderEmbeddedMissing
|
||||
}
|
||||
|
||||
encryptedEmbeddedHeader, ok := hdr.PAXRecords[records.STFSRecordEmbeddedHeader]
|
||||
if !ok {
|
||||
return config.ErrTarHeaderEmbeddedMissing
|
||||
}
|
||||
|
||||
embeddedHeader, err := DecryptString(encryptedEmbeddedHeader, encryptionFormat, identity)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var newHdr tar.Header
|
||||
if err := json.Unmarshal([]byte(embeddedHeader), &newHdr); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*hdr = newHdr
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func DecryptString(
|
||||
src string,
|
||||
encryptionFormat string,
|
||||
identity interface{},
|
||||
) (string, error) {
|
||||
switch encryptionFormat {
|
||||
case config.EncryptionFormatAgeKey:
|
||||
identity, ok := identity.(*age.X25519Identity)
|
||||
if !ok {
|
||||
return "", config.ErrIdentityUnparsable
|
||||
}
|
||||
|
||||
decoded, err := base64.StdEncoding.DecodeString(src)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
r, err := age.Decrypt(bytes.NewBufferString(string(decoded)), identity)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
out := &bytes.Buffer{}
|
||||
if _, err := io.Copy(out, r); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return out.String(), nil
|
||||
case config.EncryptionFormatPGPKey:
|
||||
identity, ok := identity.(openpgp.EntityList)
|
||||
if !ok {
|
||||
return "", config.ErrIdentityUnparsable
|
||||
}
|
||||
|
||||
decoded, err := base64.StdEncoding.DecodeString(src)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
r, err := openpgp.ReadMessage(bytes.NewBufferString(string(decoded)), identity, nil, nil)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
out := &bytes.Buffer{}
|
||||
if _, err := io.Copy(out, r.UnverifiedBody); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return out.String(), nil
|
||||
case config.NoneKey:
|
||||
return src, nil
|
||||
default:
|
||||
return "", config.ErrEncryptionFormatUnsupported
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
package encryption
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"io"
|
||||
|
||||
"filippo.io/age"
|
||||
"github.com/ProtonMail/go-crypto/openpgp"
|
||||
"github.com/pojntfx/stfs/internal/ioext"
|
||||
"github.com/pojntfx/stfs/internal/records"
|
||||
"github.com/pojntfx/stfs/pkg/config"
|
||||
)
|
||||
|
||||
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 ioext.AddCloseNopToWriter(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[records.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
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user