feat: Start implementation of signed headers
This commit is contained in:
@@ -349,6 +349,10 @@ func archive(
|
||||
hdrToAppend := *hdr
|
||||
headers = append(headers, &hdrToAppend)
|
||||
|
||||
if err := signHeader(hdr, signatureFormat, identity); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := encryptHeader(hdr, encryptionFormat, recipient); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -472,7 +476,38 @@ func encryptHeader(
|
||||
return err
|
||||
}
|
||||
|
||||
newHdr.PAXRecords[pax.STFSEmbeddedHeader], err = encryptString(string(wrappedHeader), encryptionFormat, recipient)
|
||||
newHdr.PAXRecords[pax.STFSRecordEmbeddedHeader], err = encryptString(string(wrappedHeader), encryptionFormat, recipient)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*hdr = *newHdr
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func signHeader(
|
||||
hdr *tar.Header,
|
||||
signatureFormat string,
|
||||
identity interface{},
|
||||
) error {
|
||||
if signatureFormat == 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] = string(wrappedHeader)
|
||||
newHdr.PAXRecords[pax.STFSRecordSignature], err = signString(newHdr.PAXRecords[pax.STFSRecordEmbeddedHeader], signatureFormat, identity)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -655,6 +690,26 @@ func encryptString(
|
||||
}
|
||||
}
|
||||
|
||||
func signString(
|
||||
src string,
|
||||
signatureFormat string,
|
||||
identity interface{},
|
||||
) (string, error) {
|
||||
switch signatureFormat {
|
||||
case signatureFormatMinisignKey:
|
||||
identity, ok := identity.(minisign.PrivateKey)
|
||||
if !ok {
|
||||
return "", errIdentityUnparsable
|
||||
}
|
||||
|
||||
return base64.StdEncoding.EncodeToString(minisign.Sign(identity, []byte(src))), nil
|
||||
case noneKey:
|
||||
return src, nil
|
||||
default:
|
||||
return "", errUnsupportedSignatureFormat
|
||||
}
|
||||
}
|
||||
|
||||
func compress(
|
||||
dst io.Writer,
|
||||
compressionFormat string,
|
||||
|
||||
@@ -43,6 +43,8 @@ var (
|
||||
errIdentityUnparsable = errors.New("recipient could not be parsed")
|
||||
|
||||
errInvalidSignature = errors.New("invalid signature")
|
||||
|
||||
errSignatureMissing = errors.New("missing signature")
|
||||
)
|
||||
|
||||
var recoveryFetchCmd = &cobra.Command{
|
||||
@@ -157,6 +159,10 @@ func restoreFromRecordAndBlock(
|
||||
return err
|
||||
}
|
||||
|
||||
if err := verifyHeader(hdr, signatureFormat, recipient); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if showHeader {
|
||||
if err := formatting.PrintCSV(formatting.TARHeaderCSV); err != nil {
|
||||
return err
|
||||
@@ -297,7 +303,7 @@ func decryptHeader(
|
||||
return errEmbeddedHeaderMissing
|
||||
}
|
||||
|
||||
encryptedEmbeddedHeader, ok := hdr.PAXRecords[pax.STFSEmbeddedHeader]
|
||||
encryptedEmbeddedHeader, ok := hdr.PAXRecords[pax.STFSRecordEmbeddedHeader]
|
||||
if !ok {
|
||||
return errEmbeddedHeaderMissing
|
||||
}
|
||||
@@ -317,6 +323,43 @@ func decryptHeader(
|
||||
return nil
|
||||
}
|
||||
|
||||
func verifyHeader(
|
||||
hdr *tar.Header,
|
||||
signatureFormat string,
|
||||
recipient interface{},
|
||||
) error {
|
||||
if signatureFormat == noneKey {
|
||||
return nil
|
||||
}
|
||||
|
||||
if hdr.PAXRecords == nil {
|
||||
return errEmbeddedHeaderMissing
|
||||
}
|
||||
|
||||
embeddedHeader, ok := hdr.PAXRecords[pax.STFSRecordEmbeddedHeader]
|
||||
if !ok {
|
||||
return errEmbeddedHeaderMissing
|
||||
}
|
||||
|
||||
signature, ok := hdr.PAXRecords[pax.STFSRecordSignature]
|
||||
if !ok {
|
||||
return errSignatureMissing
|
||||
}
|
||||
|
||||
if err := verifyString(embeddedHeader, signatureFormat, recipient, signature); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var newHdr tar.Header
|
||||
if err := json.Unmarshal([]byte(embeddedHeader), &newHdr); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*hdr = newHdr
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseIdentity(
|
||||
encryptionFormat string,
|
||||
privkey []byte,
|
||||
@@ -525,6 +568,36 @@ func verify(
|
||||
}
|
||||
}
|
||||
|
||||
func verifyString(
|
||||
src string,
|
||||
signatureFormat string,
|
||||
recipient interface{},
|
||||
signature string,
|
||||
) error {
|
||||
switch signatureFormat {
|
||||
case signatureFormatMinisignKey:
|
||||
recipient, ok := recipient.(minisign.PublicKey)
|
||||
if !ok {
|
||||
return errRecipientUnparsable
|
||||
}
|
||||
|
||||
decodedSignature, err := base64.StdEncoding.DecodeString(signature)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if minisign.Verify(recipient, []byte(src), decodedSignature) {
|
||||
return nil
|
||||
}
|
||||
|
||||
return errInvalidSignature
|
||||
case noneKey:
|
||||
return nil
|
||||
default:
|
||||
return errUnsupportedSignatureFormat
|
||||
}
|
||||
}
|
||||
|
||||
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")
|
||||
|
||||
@@ -23,7 +23,7 @@ const (
|
||||
|
||||
STFSRecordSignature = STFSPrefix + "Signature"
|
||||
|
||||
STFSEmbeddedHeader = STFSPrefix + "EmbeddedHeader"
|
||||
STFSRecordEmbeddedHeader = STFSPrefix + "EmbeddedHeader"
|
||||
)
|
||||
|
||||
var (
|
||||
|
||||
Reference in New Issue
Block a user