aboutsummaryrefslogtreecommitdiff
path: root/pkg/signatures/signify
diff options
context:
space:
mode:
authorRasmus Dahlberg <rasmus@mullvad.net>2022-03-02 23:16:43 +0100
committerRasmus Dahlberg <rasmus@mullvad.net>2022-03-02 23:17:48 +0100
commit8da382069f42f6d88d3abf914dd38d7e40a845bc (patch)
tree780e8297ee3905ab662c6c88cb8bf33f0717c90c /pkg/signatures/signify
initial commit
Diffstat (limited to 'pkg/signatures/signify')
-rw-r--r--pkg/signatures/signify/signify.go91
1 files changed, 91 insertions, 0 deletions
diff --git a/pkg/signatures/signify/signify.go b/pkg/signatures/signify/signify.go
new file mode 100644
index 0000000..6dbbf07
--- /dev/null
+++ b/pkg/signatures/signify/signify.go
@@ -0,0 +1,91 @@
+package signify
+
+import (
+ "bytes"
+ "encoding/base64"
+ "fmt"
+ "io"
+ "io/ioutil"
+
+ "git.sigsum.org/sigsum-lib-go/pkg/types"
+)
+
+type Parser struct{}
+
+func (p *Parser) SignatureSuffix() string {
+ return ".sig"
+}
+
+func (p *Parser) PublicKey(r io.Reader) (*types.PublicKey, error) {
+ b, err := ioutil.ReadAll(r)
+ if err != nil {
+ return nil, fmt.Errorf("signify: read failed: %v", err)
+ }
+ var pub types.PublicKey
+ if err := parse(pub[:], b); err != nil {
+ return nil, fmt.Errorf("signify: %v", err)
+ }
+ return &pub, nil
+}
+
+func (p *Parser) Signature(r io.Reader) (*types.Signature, error) {
+ b, err := ioutil.ReadAll(r)
+ if err != nil {
+ return nil, fmt.Errorf("signify: read failed: %v", err)
+ }
+ var sig types.Signature
+ if err := parse(sig[:], b); err != nil {
+ return nil, fmt.Errorf("signify: %v", err)
+ }
+ return &sig, nil
+}
+
+func parse(dst, lines []byte) error {
+ commentLine, dataLine, err := parseLines(lines)
+ if err != nil {
+ return fmt.Errorf("invalid: %v", err)
+ }
+ if err := parseCommentLine(commentLine); err != nil {
+ return fmt.Errorf("invalid: %v", err)
+ }
+ if err := parseDataLine(dst, dataLine); err != nil {
+ return fmt.Errorf("invalid: %v", err)
+ }
+ return nil
+}
+
+func parseLines(lines []byte) ([]byte, []byte, error) {
+ split := bytes.Split(lines, []byte("\n"))
+ if len(split) != 3 {
+ return nil, nil, fmt.Errorf("number of lines")
+ }
+ return split[0], split[1], nil
+}
+
+func parseCommentLine(line []byte) error {
+ if !bytes.HasPrefix(line, []byte("untrusted comment: ")) {
+ return fmt.Errorf("no untrusted comment")
+ }
+ return nil
+}
+
+func parseDataLine(dst, line []byte) error {
+ data, err := base64.StdEncoding.DecodeString(string(line))
+ if err != nil {
+ return fmt.Errorf("base64 encoding")
+ }
+ if len(data) < 2 || !bytes.Equal(data[:2], []byte("Ed")) {
+ return fmt.Errorf("algorithm")
+ }
+ data = data[2:]
+ if len(data) < 8 {
+ return fmt.Errorf("random fingerprint")
+ }
+ data = data[8:]
+ if len(data) != len(dst) {
+ return fmt.Errorf("data length")
+ }
+
+ copy(dst[:], data)
+ return nil
+}