~whereswaldon/forest-go

ref: c7a4d89bc08753da0fc038d329bceed1d3285905 forest-go/signature_validator.go -rw-r--r-- 1.7 KiB
c7a4d89bChris Waldon Merge branch 'protonpgp' 4 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
package forest

import (
	"bytes"
	"fmt"

	"golang.org/x/crypto/openpgp"
	"golang.org/x/crypto/openpgp/packet"

	"git.sr.ht/~whereswaldon/forest-go/fields"
)

// SignatureValidator is a type that has a signature and can supply the ID of the node that signed it.
type SignatureValidator interface {
	MarshalSignedData() ([]byte, error)
	GetSignature() *fields.QualifiedSignature
	SignatureIdentityHash() *fields.QualifiedHash
	IsIdentity() bool
}

// ValidateSignature returns whether the signature contained in this SignatureValidator is a valid
// signature for the given Identity. When validating an Identity node, you should
// pass the same Identity as the second parameter.
func ValidateSignature(v SignatureValidator, identity *Identity) (bool, error) {
	sigIdHash := v.SignatureIdentityHash()
	if sigIdHash.Equals(fields.NullHash()) {
		if !v.IsIdentity() {
			return false, fmt.Errorf("Only Identity nodes can have the null hash as their Signature Authority")
		}
	} else if !sigIdHash.Equals(identity.ID()) {
		return false, fmt.Errorf("This node was signed by a different identity")
	}
	// get the key used to sign this node
	pubkeyBuf := bytes.NewBuffer([]byte(identity.PublicKey.Blob))
	pubkeyEntity, err := openpgp.ReadEntity(packet.NewReader(pubkeyBuf))
	if err != nil {
		return false, err
	}

	signedContent, err := v.MarshalSignedData()
	if err != nil {
		return false, err
	}
	signedContentBuf := bytes.NewBuffer(signedContent)

	signatureBuf := bytes.NewBuffer([]byte(v.GetSignature().Blob))
	keyring := openpgp.EntityList([]*openpgp.Entity{pubkeyEntity})
	_, err = openpgp.CheckDetachedSignature(keyring, signedContentBuf, signatureBuf, nil)
	if err != nil {
		return false, err
	}
	return true, nil
}