Files
src.dualinventive.com/go/common/vendor/github.com/xor-gate/debpkg/digest.go
2024-08-09 12:10:16 +02:00

137 lines
3.7 KiB
Go

// Copyright 2017 Debpkg authors. All rights reserved.
// Use of this source code is governed by the MIT
// license that can be found in the LICENSE file.
package debpkg
import (
"bytes"
"crypto"
"crypto/md5"
"crypto/sha1"
"fmt"
"hash"
"io"
"os"
"time"
"golang.org/x/crypto/openpgp"
"golang.org/x/crypto/openpgp/clearsign"
"golang.org/x/crypto/openpgp/packet"
)
const digestDefaultHash = crypto.SHA1
const digestVersion = 4
const digestRole = "builder"
// Digest file for GPG signing
type digest struct {
plaintext string // Plaintext package digest (empty when unsigned)
clearsign string // GPG clearsigned package digest (empty when unsigned)
signer string // Name <email>
date string // Mon Jan 2 15:04:05 2006 (time.ANSIC)
files string // Multiple "\t<md5sum> <sha1sum> <size> <filename>"
// E.g:
// 3cf918272ffa5de195752d73f3da3e5e 7959c969e092f2a5a8604e2287807ac5b1b384ad 4 debian-binary
// 79bb73dbb522dc1a2dd1b9c2ec89fc79 26d29d15aad5c0e051d07571e28da2bc0009707e 366 control.tar.gz
// e1a6e48c95a760170029ef7872cec994 e02ed99e5c4fd847bde12b4c2c30dd814b26ec27 136 data.tar.gz
}
// Create unsigned digest file at toplevel of deb package
// NOTE: the deb.digest.version and deb.digest.role are set in this function!
func createDigestFileString(deb *DebPkg) string {
const digestFileTmpl = `Version: %d
Signer: %s
Date: %s
Role: %s
Files:
%s`
// debian-binary
md5sum, _ := digestCalcDataHash(bytes.NewBuffer([]byte(deb.debianBinary)), md5.New())
sha1sum, _ := digestCalcDataHash(bytes.NewBuffer([]byte(deb.debianBinary)), sha1.New())
deb.digest.files += fmt.Sprintf("\t%x %x %d %s\n",
md5sum,
sha1sum,
len(deb.debianBinary),
"debian-binary")
deb.digestAddFile("control.tar.gz", deb.control.tgz.Name(), deb.control.tgz.Size())
deb.digestAddFile("data.tar.gz", deb.data.tgz.Name(), deb.data.tgz.Size())
return fmt.Sprintf(digestFileTmpl,
digestVersion,
deb.digest.signer,
deb.digest.date,
digestRole,
deb.digest.files)
}
func (deb *DebPkg) digestAddFile(filename, filepath string, size int64) {
md5sum, _ := digestCalcDataHashFromFile(filepath, md5.New())
sha1sum, _ := digestCalcDataHashFromFile(filepath, sha1.New())
deb.digest.files += fmt.Sprintf("\t%x %x %d %s\n",
md5sum,
sha1sum,
size,
filename)
}
func digestCalcDataHashFromFile(filename string, hash hash.Hash) (string, error) {
f, err := os.Open(filename)
if err != nil {
return "", err
}
defer f.Close()
return digestCalcDataHash(f, hash)
}
func digestCalcDataHash(in io.Reader, hash hash.Hash) (string, error) {
var result []byte
if _, err := io.Copy(hash, in); err != nil {
return "", err
}
return string(hash.Sum(result)), nil
}
// WriteSigned package with GPG entity
func (deb *DebPkg) WriteSigned(filename string, entity *openpgp.Entity) error {
var buf bytes.Buffer
var cfg packet.Config
var signer string
cfg.DefaultHash = digestDefaultHash
for id := range entity.Identities {
// TODO real search for keyid, need to investigate maybe a subkey?
signer = id
}
deb.digest.date = time.Now().Format(time.ANSIC)
deb.digest.signer = signer
clearsign, err := clearsign.Encode(&buf, entity.PrivateKey, &cfg)
if err != nil {
return fmt.Errorf("error while signing: %s", err)
}
if err := deb.writeControlData(); err != nil {
return err
}
deb.digest.plaintext = createDigestFileString(deb)
if _, err = clearsign.Write([]byte(deb.digest.plaintext)); err != nil {
return fmt.Errorf("error from Write: %s", err)
}
if err = clearsign.Close(); err != nil {
return fmt.Errorf("error from Close: %s", err)
}
deb.digest.clearsign = buf.String()
if filename == "" {
filename = deb.GetFilename()
}
return deb.createDebAr(filename)
}