feat: Add basic signature support to archive cmd based on Minisign

This commit is contained in:
Felicitas Pojtinger
2021-12-04 16:44:31 +01:00
parent 1938e15eef
commit ce7c9df3ac
14 changed files with 162 additions and 62 deletions

View File

@@ -16,6 +16,7 @@ import (
"path/filepath"
"strconv"
"aead.dev/minisign"
"filippo.io/age"
"github.com/ProtonMail/go-crypto/openpgp"
"github.com/andybalholm/brotli"
@@ -37,7 +38,7 @@ import (
const (
recordSizeFlag = "record-size"
srcFlag = "src"
fromFlag = "from"
overwriteFlag = "overwrite"
compressionLevelFlag = "compression-level"
@@ -76,7 +77,11 @@ var archiveCmd = &cobra.Command{
return err
}
return checkKeyAccessible(viper.GetString(encryptionFlag), viper.GetString(recipientFlag))
if err := checkKeyAccessible(viper.GetString(encryptionFlag), viper.GetString(recipientFlag)); err != nil {
return err
}
return checkKeyAccessible(viper.GetString(signatureFlag), viper.GetString(identityFlag))
},
RunE: func(cmd *cobra.Command, args []string) error {
if viper.GetBool(verboseFlag) {
@@ -110,22 +115,34 @@ var archiveCmd = &cobra.Command{
return err
}
privkey, err := readKey(viper.GetString(signatureFlag), viper.GetString(identityFlag))
if err != nil {
return err
}
identity, err := parseSignerIdentity(viper.GetString(signatureFlag), privkey, viper.GetString(passwordFlag))
if err != nil {
return err
}
hdrs, err := archive(
viper.GetString(tapeFlag),
viper.GetString(driveFlag),
viper.GetInt(recordSizeFlag),
viper.GetString(srcFlag),
viper.GetString(fromFlag),
viper.GetBool(overwriteFlag),
viper.GetString(compressionFlag),
viper.GetString(compressionLevelFlag),
viper.GetString(encryptionFlag),
recipient,
viper.GetString(signatureFlag),
identity,
)
if err != nil {
return err
}
return index(
viper.GetString(tapeFlag),
viper.GetString(driveFlag),
viper.GetString(metadataFlag),
viper.GetInt(recordSizeFlag),
int(lastIndexedRecord),
@@ -156,6 +173,8 @@ func archive(
compressionLevel string,
encryptionFormat string,
recipient interface{},
signatureFormat string,
identity interface{},
) ([]*tar.Header, error) {
dirty := false
tw, isRegular, cleanup, err := openTapeWriter(tape)
@@ -268,13 +287,18 @@ func archive(
return err
}
signer, sign, err := sign(file, signatureFormat, identity)
if err != nil {
return err
}
if isRegular {
if _, err := io.Copy(compressor, file); err != nil {
if _, err := io.Copy(compressor, signer); err != nil {
return err
}
} else {
buf := make([]byte, controllers.BlockSize*recordSize)
if _, err := io.CopyBuffer(compressor, file, buf); err != nil {
if _, err := io.CopyBuffer(compressor, signer, buf); err != nil {
return err
}
}
@@ -299,6 +323,9 @@ func archive(
hdr.PAXRecords = map[string]string{}
}
hdr.PAXRecords[pax.STFSRecordUncompressedSize] = strconv.Itoa(int(hdr.Size))
if signature := sign(); signature != "" {
hdr.PAXRecords[pax.STFSRecordSignature] = signature
}
hdr.Size = int64(fileSizeCounter.BytesRead)
hdr.Name, err = addSuffix(hdr.Name, compressionFormat, encryptionFormat)
@@ -390,7 +417,7 @@ func archive(
}
func checkKeyAccessible(encryptionFormat string, pathToKey string) error {
if encryptionFormat == encryptionFormatNoneKey {
if encryptionFormat == noneKey {
return nil
}
@@ -402,7 +429,7 @@ func checkKeyAccessible(encryptionFormat string, pathToKey string) error {
}
func readKey(encryptionFormat string, pathToKey string) ([]byte, error) {
if encryptionFormat == encryptionFormatNoneKey {
if encryptionFormat == noneKey {
return []byte{}, nil
}
@@ -430,7 +457,7 @@ func encryptHeader(
encryptionFormat string,
recipient interface{},
) error {
if encryptionFormat == encryptionFormatNoneKey {
if encryptionFormat == noneKey {
return nil
}
@@ -471,7 +498,7 @@ func addSuffix(name string, compressionFormat string, encryptionFormat string) (
fallthrough
case compressionFormatBzip2ParallelKey:
name += compressionFormatBzip2Suffix
case compressionFormatNoneKey:
case noneKey:
default:
return "", errUnsupportedCompressionFormat
}
@@ -481,7 +508,7 @@ func addSuffix(name string, compressionFormat string, encryptionFormat string) (
name += encryptionFormatAgeSuffix
case encryptionFormatPGPKey:
name += encryptionFormatPGPSuffix
case compressionFormatNoneKey:
case noneKey:
default:
return "", errUnsupportedEncryptionFormat
}
@@ -498,7 +525,7 @@ func parseRecipient(
return age.ParseX25519Recipient(string(pubkey))
case encryptionFormatPGPKey:
return openpgp.ReadKeyRing(bytes.NewBuffer(pubkey))
case encryptionFormatNoneKey:
case noneKey:
return pubkey, nil
default:
return nil, errUnsupportedEncryptionFormat
@@ -525,13 +552,54 @@ func encrypt(
}
return openpgp.Encrypt(dst, recipient, nil, nil, nil)
case encryptionFormatNoneKey:
case noneKey:
return noop.AddClose(dst), nil
default:
return nil, errUnsupportedEncryptionFormat
}
}
func parseSignerIdentity(
signatureFormat string,
privkey []byte,
password string,
) (interface{}, error) {
switch signatureFormat {
case signatureFormatMinisignKey:
return minisign.DecryptKey(password, privkey)
case noneKey:
return privkey, nil
default:
return nil, errUnsupportedSignatureFormat
}
}
func sign(
src io.Reader,
signatureFormat string,
identity interface{},
) (io.Reader, func() string, error) {
switch signatureFormat {
case signatureFormatMinisignKey:
identity, ok := identity.(minisign.PrivateKey)
if !ok {
return nil, nil, errIdentityUnparsable
}
signer := minisign.NewReader(src)
return signer, func() string {
return base64.StdEncoding.EncodeToString(signer.Sign(identity))
}, nil
case noneKey:
return io.NopCloser(src), func() string {
return ""
}, nil
default:
return nil, nil, errUnsupportedSignatureFormat
}
}
func encryptString(
src string,
encryptionFormat string,
@@ -580,7 +648,7 @@ func encryptString(
}
return base64.StdEncoding.EncodeToString(out.Bytes()), nil
case encryptionFormatNoneKey:
case noneKey:
return src, nil
default:
return "", errUnsupportedEncryptionFormat
@@ -704,7 +772,7 @@ func compress(
}
return noop.AddFlush(bz), nil
case compressionFormatNoneKey:
case noneKey:
return noop.AddFlush(noop.AddClose(dst)), nil
default:
return nil, errUnsupportedCompressionFormat
@@ -713,10 +781,12 @@ func compress(
func init() {
archiveCmd.PersistentFlags().IntP(recordSizeFlag, "z", 20, "Amount of 512-bit blocks per record")
archiveCmd.PersistentFlags().StringP(srcFlag, "s", ".", "File or directory to archive")
archiveCmd.PersistentFlags().StringP(fromFlag, "f", ".", "File or directory to archive")
archiveCmd.PersistentFlags().BoolP(overwriteFlag, "o", false, "Start writing from the start instead of from the end of the tape or tar file")
archiveCmd.PersistentFlags().StringP(compressionLevelFlag, "l", compressionLevelBalanced, fmt.Sprintf("Compression level to use (default %v, available are %v)", compressionLevelBalanced, knownCompressionLevels))
archiveCmd.PersistentFlags().StringP(recipientFlag, "r", "", "Path to public key of recipient to encrypt for")
archiveCmd.PersistentFlags().StringP(identityFlag, "i", "", "Path to private key to sign with")
archiveCmd.PersistentFlags().StringP(passwordFlag, "p", "", "Password for the private key")
viper.AutomaticEnv()

View File

@@ -53,7 +53,7 @@ var deleteCmd = &cobra.Command{
}
return delete(
viper.GetString(tapeFlag),
viper.GetString(driveFlag),
viper.GetString(metadataFlag),
viper.GetString(nameFlag),
viper.GetString(encryptionFlag),

View File

@@ -21,7 +21,7 @@ var driveEjectCmd = &cobra.Command{
boil.DebugMode = true
}
f, err := os.OpenFile(viper.GetString(tapeFlag), os.O_RDONLY, os.ModeCharDevice)
f, err := os.OpenFile(viper.GetString(driveFlag), os.O_RDONLY, os.ModeCharDevice)
if err != nil {
panic(err)
}

View File

@@ -22,7 +22,7 @@ var driveTellCmd = &cobra.Command{
boil.DebugMode = true
}
f, err := os.OpenFile(viper.GetString(tapeFlag), os.O_RDONLY, os.ModeCharDevice)
f, err := os.OpenFile(viper.GetString(driveFlag), os.O_RDONLY, os.ModeCharDevice)
if err != nil {
panic(err)
}

View File

@@ -46,10 +46,10 @@ var moveCmd = &cobra.Command{
}
return move(
viper.GetString(tapeFlag),
viper.GetString(driveFlag),
viper.GetString(metadataFlag),
viper.GetString(srcFlag),
viper.GetString(dstFlag),
viper.GetString(fromFlag),
viper.GetString(toFlag),
viper.GetString(encryptionFlag),
recipient,
)
@@ -135,8 +135,8 @@ func move(
func init() {
moveCmd.PersistentFlags().IntP(recordSizeFlag, "z", 20, "Amount of 512-bit blocks per record")
moveCmd.PersistentFlags().StringP(srcFlag, "s", "", "Current path of the file or directory to move")
moveCmd.PersistentFlags().StringP(dstFlag, "d", "", "Path to move the file or directory to")
moveCmd.PersistentFlags().StringP(fromFlag, "f", "", "Current path of the file or directory to move")
moveCmd.PersistentFlags().StringP(toFlag, "t", "", "Path to move the file or directory to")
moveCmd.PersistentFlags().StringP(recipientFlag, "r", "", "Path to public key of recipient to encrypt for")
viper.AutomaticEnv()

View File

@@ -32,7 +32,7 @@ import (
const (
recordFlag = "record"
blockFlag = "block"
dstFlag = "dst"
toFlag = "to"
previewFlag = "preview"
)
@@ -72,11 +72,11 @@ var recoveryFetchCmd = &cobra.Command{
}
return restoreFromRecordAndBlock(
viper.GetString(tapeFlag),
viper.GetString(driveFlag),
viper.GetInt(recordSizeFlag),
viper.GetInt(recordFlag),
viper.GetInt(blockFlag),
viper.GetString(dstFlag),
viper.GetString(toFlag),
viper.GetBool(previewFlag),
true,
viper.GetString(compressionFlag),
@@ -240,7 +240,7 @@ func decompress(
bz := pbzip2.NewReader(context.Background(), src)
return io.NopCloser(bz), nil
case compressionFormatNoneKey:
case noneKey:
return io.NopCloser(src), nil
default:
return nil, errUnsupportedCompressionFormat
@@ -252,7 +252,7 @@ func decryptHeader(
encryptionFormat string,
identity interface{},
) error {
if encryptionFormat == encryptionFormatNoneKey {
if encryptionFormat == noneKey {
return nil
}
@@ -328,7 +328,7 @@ func parseIdentity(
}
return identities, nil
case encryptionFormatNoneKey:
case noneKey:
return privkey, nil
default:
return nil, errUnsupportedEncryptionFormat
@@ -385,7 +385,7 @@ func decryptString(
}
return out.String(), nil
case encryptionFormatNoneKey:
case noneKey:
return src, nil
default:
return "", errUnsupportedEncryptionFormat
@@ -422,7 +422,7 @@ func decrypt(
}
return io.NopCloser(r.UnverifiedBody), nil
case encryptionFormatNoneKey:
case noneKey:
return io.NopCloser(src), nil
default:
return nil, errUnsupportedEncryptionFormat
@@ -433,7 +433,7 @@ func init() {
recoveryFetchCmd.PersistentFlags().IntP(recordSizeFlag, "z", 20, "Amount of 512-bit blocks per record")
recoveryFetchCmd.PersistentFlags().IntP(recordFlag, "k", 0, "Record to seek too")
recoveryFetchCmd.PersistentFlags().IntP(blockFlag, "b", 0, "Block in record to seek too")
recoveryFetchCmd.PersistentFlags().StringP(dstFlag, "d", "", "File to restore to (archived name by default)")
recoveryFetchCmd.PersistentFlags().StringP(toFlag, "t", "", "File to restore to (archived name by default)")
recoveryFetchCmd.PersistentFlags().BoolP(previewFlag, "w", false, "Only read the header")
recoveryFetchCmd.PersistentFlags().StringP(identityFlag, "i", "", "Path to private key of recipient that has been encrypted for")
recoveryFetchCmd.PersistentFlags().StringP(passwordFlag, "p", "", "Password for the private key")

View File

@@ -53,7 +53,7 @@ var recoveryIndexCmd = &cobra.Command{
}
return index(
viper.GetString(tapeFlag),
viper.GetString(driveFlag),
viper.GetString(metadataFlag),
viper.GetInt(recordSizeFlag),
viper.GetInt(recordFlag),
@@ -421,7 +421,7 @@ func removeSuffix(name string, compressionFormat string, encryptionFormat string
name = strings.TrimSuffix(name, encryptionFormatAgeSuffix)
case encryptionFormatPGPKey:
name = strings.TrimSuffix(name, encryptionFormatPGPSuffix)
case encryptionFormatNoneKey:
case noneKey:
default:
return "", errUnsupportedEncryptionFormat
}
@@ -441,7 +441,7 @@ func removeSuffix(name string, compressionFormat string, encryptionFormat string
fallthrough
case compressionFormatBzip2ParallelKey:
name = strings.TrimSuffix(name, compressionFormatBzip2Suffix)
case compressionFormatNoneKey:
case noneKey:
default:
return "", errUnsupportedCompressionFormat
}

View File

@@ -45,7 +45,7 @@ var recoveryQueryCmd = &cobra.Command{
}
return query(
viper.GetString(tapeFlag),
viper.GetString(driveFlag),
viper.GetInt(recordFlag),
viper.GetInt(blockFlag),
viper.GetInt(recordSizeFlag),

View File

@@ -57,7 +57,7 @@ var restoreCmd = &cobra.Command{
}
headersToRestore := []*models.Header{}
src := strings.TrimSuffix(viper.GetString(srcFlag), "/")
src := strings.TrimSuffix(viper.GetString(fromFlag), "/")
dbhdr, err := metadataPersister.GetHeader(context.Background(), src)
if err != nil {
if err == sql.ErrNoRows {
@@ -100,20 +100,20 @@ var restoreCmd = &cobra.Command{
}
dst := dbhdr.Name
if viper.GetString(dstFlag) != "" {
if viper.GetString(toFlag) != "" {
if viper.GetBool(flattenFlag) {
dst = viper.GetString(dstFlag)
dst = viper.GetString(toFlag)
} else {
dst = filepath.Join(viper.GetString(dstFlag), strings.TrimPrefix(dst, viper.GetString(srcFlag)))
dst = filepath.Join(viper.GetString(toFlag), strings.TrimPrefix(dst, viper.GetString(fromFlag)))
if strings.TrimSuffix(dst, "/") == strings.TrimSuffix(viper.GetString(dstFlag), "/") {
if strings.TrimSuffix(dst, "/") == strings.TrimSuffix(viper.GetString(toFlag), "/") {
dst = filepath.Join(dst, path.Base(dbhdr.Name)) // Append the name so we don't overwrite
}
}
}
if err := restoreFromRecordAndBlock(
viper.GetString(tapeFlag),
viper.GetString(driveFlag),
viper.GetInt(recordSizeFlag),
int(dbhdr.Record),
int(dbhdr.Block),
@@ -134,9 +134,9 @@ var restoreCmd = &cobra.Command{
func init() {
restoreCmd.PersistentFlags().IntP(recordSizeFlag, "z", 20, "Amount of 512-bit blocks per record")
restoreCmd.PersistentFlags().StringP(srcFlag, "s", "", "File or directory to restore")
restoreCmd.PersistentFlags().StringP(dstFlag, "d", "", "File or directory restore to (archived name by default)")
restoreCmd.PersistentFlags().BoolP(flattenFlag, "f", false, "Ignore the folder hierarchy on the tape or tar file")
restoreCmd.PersistentFlags().StringP(fromFlag, "f", "", "File or directory to restore")
restoreCmd.PersistentFlags().StringP(toFlag, "t", "", "File or directory restore to (archived name by default)")
restoreCmd.PersistentFlags().BoolP(flattenFlag, "a", false, "Ignore the folder hierarchy on the tape or tar file")
restoreCmd.PersistentFlags().StringP(identityFlag, "i", "", "Path to private key of recipient that has been encrypted for")
restoreCmd.PersistentFlags().StringP(passwordFlag, "p", "", "Password for the private key")

View File

@@ -12,12 +12,13 @@ import (
)
const (
tapeFlag = "tape"
metadataFlag = "metadata"
verboseFlag = "verbose"
driveFlag = "drive"
metadataFlag = "metadata"
verboseFlag = "verbose"
compressionFlag = "compression"
compressionFormatNoneKey = "none"
noneKey = "none"
compressionFormatGZipKey = "gzip"
compressionFormatGZipSuffix = ".gz"
@@ -40,26 +41,33 @@ const (
encryptionFlag = "encryption"
encryptionFormatNoneKey = "none"
encryptionFormatAgeKey = "age"
encryptionFormatAgeSuffix = ".age"
encryptionFormatPGPKey = "pgp"
encryptionFormatPGPSuffix = ".pgp"
signatureFlag = "signature"
signatureFormatMinisignKey = "minisign"
)
var (
knownCompressionFormats = []string{compressionFormatNoneKey, compressionFormatGZipKey, compressionFormatParallelGZipKey, compressionFormatLZ4Key, compressionFormatZStandardKey, compressionFormatBrotliKey, compressionFormatBzip2Key, compressionFormatBzip2ParallelKey}
knownCompressionFormats = []string{noneKey, compressionFormatGZipKey, compressionFormatParallelGZipKey, compressionFormatLZ4Key, compressionFormatZStandardKey, compressionFormatBrotliKey, compressionFormatBzip2Key, compressionFormatBzip2ParallelKey}
errUnknownCompressionFormat = errors.New("unknown compression format")
errUnsupportedCompressionFormat = errors.New("unsupported compression format")
knownEncryptionFormats = []string{encryptionFormatNoneKey, encryptionFormatAgeKey, encryptionFormatPGPKey}
knownEncryptionFormats = []string{noneKey, encryptionFormatAgeKey, encryptionFormatPGPKey}
errUnknownEncryptionFormat = errors.New("unknown encryption format")
errUnsupportedEncryptionFormat = errors.New("unsupported encryption format")
errKeygenForEncryptionFormatUnsupported = errors.New("can not generate keys for this encryption format")
knownSignatureFormats = []string{noneKey, signatureFormatMinisignKey}
errUnknownSignatureFormat = errors.New("unknown signature format")
errUnsupportedSignatureFormat = errors.New("unsupported signature format")
)
var rootCmd = &cobra.Command{
@@ -99,6 +107,19 @@ https://github.com/pojntfx/stfs`,
return errUnknownEncryptionFormat
}
signatureFormatIsKnown := false
signatureFormat := viper.GetString(signatureFlag)
for _, candidate := range knownSignatureFormats {
if signatureFormat == candidate {
signatureFormatIsKnown = true
}
}
if !signatureFormatIsKnown {
return errUnknownSignatureFormat
}
return nil
},
}
@@ -111,11 +132,12 @@ func Execute() {
}
metadataPath := filepath.Join(home, ".local", "share", "stbak", "var", "lib", "stbak", "metadata.sqlite")
rootCmd.PersistentFlags().StringP(tapeFlag, "t", "/dev/nst0", "Tape or tar file to use")
rootCmd.PersistentFlags().StringP(driveFlag, "d", "/dev/nst0", "Tape or tar file to use")
rootCmd.PersistentFlags().StringP(metadataFlag, "m", metadataPath, "Metadata database to use")
rootCmd.PersistentFlags().BoolP(verboseFlag, "v", false, "Enable verbose logging")
rootCmd.PersistentFlags().StringP(compressionFlag, "c", compressionFormatNoneKey, fmt.Sprintf("Compression format to use (default %v, available are %v)", compressionFormatNoneKey, knownCompressionFormats))
rootCmd.PersistentFlags().StringP(encryptionFlag, "e", encryptionFormatNoneKey, fmt.Sprintf("Encryption format to use (default %v, available are %v)", encryptionFormatNoneKey, knownEncryptionFormats))
rootCmd.PersistentFlags().StringP(compressionFlag, "c", noneKey, fmt.Sprintf("Compression format to use (default %v, available are %v)", noneKey, knownCompressionFormats))
rootCmd.PersistentFlags().StringP(encryptionFlag, "e", noneKey, fmt.Sprintf("Encryption format to use (default %v, available are %v)", noneKey, knownEncryptionFormats))
rootCmd.PersistentFlags().StringP(signatureFlag, "s", noneKey, fmt.Sprintf("Signature format to use (default %v, available are %v)", noneKey, knownSignatureFormats))
if err := viper.BindPFlags(rootCmd.PersistentFlags()); err != nil {
panic(err)

View File

@@ -66,9 +66,9 @@ var updateCmd = &cobra.Command{
}
hdrs, err := update(
viper.GetString(tapeFlag),
viper.GetString(driveFlag),
viper.GetInt(recordSizeFlag),
viper.GetString(srcFlag),
viper.GetString(fromFlag),
viper.GetBool(overwriteFlag),
viper.GetString(compressionFlag),
viper.GetString(compressionLevelFlag),
@@ -80,7 +80,7 @@ var updateCmd = &cobra.Command{
}
return index(
viper.GetString(tapeFlag),
viper.GetString(driveFlag),
viper.GetString(metadataFlag),
viper.GetInt(recordSizeFlag),
int(lastIndexedRecord),
@@ -321,7 +321,7 @@ func update(
func init() {
updateCmd.PersistentFlags().IntP(recordSizeFlag, "z", 20, "Amount of 512-bit blocks per record")
updateCmd.PersistentFlags().StringP(srcFlag, "s", "", "Path of the file or directory to update")
updateCmd.PersistentFlags().StringP(fromFlag, "f", "", "Path of the file or directory to update")
updateCmd.PersistentFlags().BoolP(overwriteFlag, "o", false, "Replace the content on the tape or tar file")
updateCmd.PersistentFlags().StringP(compressionLevelFlag, "l", compressionLevelBalanced, fmt.Sprintf("Compression level to use (default %v, available are %v)", compressionLevelBalanced, knownCompressionLevels))
updateCmd.PersistentFlags().StringP(recipientFlag, "r", "", "Path to public key of recipient to encrypt for")

1
go.mod
View File

@@ -3,6 +3,7 @@ module github.com/pojntfx/stfs
go 1.17
require (
aead.dev/minisign v0.2.0
filippo.io/age v1.0.0
github.com/ProtonMail/go-crypto v0.0.0-20211112122917-428f8eabeeb3
github.com/ProtonMail/gopenpgp/v2 v2.3.0

5
go.sum
View File

@@ -1,3 +1,5 @@
aead.dev/minisign v0.2.0 h1:kAWrq/hBRu4AARY6AlciO83xhNnW9UaC8YipS2uhLPk=
aead.dev/minisign v0.2.0/go.mod h1:zdq6LdSd9TbuSxchxwhpA9zEb9YXcVGoE8JakuiGaIQ=
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
@@ -468,6 +470,7 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20191122220453-ac88ee75c92c/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ=
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
@@ -623,6 +626,7 @@ golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210228012217-479acdf4ea46/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -640,6 +644,7 @@ golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210903071746-97244b99971b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211117180635-dee7805ff2e1 h1:kwrAHlwJ0DUBZwQ238v+Uod/3eZ8B2K5rYsUHBQvzmI=
golang.org/x/sys v0.0.0-20211117180635-dee7805ff2e1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b h1:9zKuko04nR4gjZ4+DNjHqRlAJqbJETHwiNKDqTfOjfE=
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=

View File

@@ -21,6 +21,8 @@ const (
STFSRecordUncompressedSize = STFSPrefix + "UncompressedSize"
STFSRecordSignature = STFSPrefix + "Signature"
STFSEmbeddedHeader = STFSPrefix + "EmbeddedHeader"
)