go-libp2p-core/crypto/envelope.go

101 lines
2.3 KiB
Go
Raw Normal View History

2019-11-07 01:24:34 +08:00
package crypto
import (
"bytes"
"encoding/binary"
"errors"
"github.com/golang/protobuf/proto"
pb "github.com/libp2p/go-libp2p-core/crypto/pb"
"github.com/libp2p/go-libp2p-core/peer"
2019-11-07 01:24:34 +08:00
)
type SignedEnvelope struct {
PublicKey PubKey
TypeHint []byte
contents []byte
signature []byte
}
2019-11-07 01:24:34 +08:00
func MakeEnvelope(privateKey PrivKey, domain string, typeHint []byte, contents []byte) (*SignedEnvelope, error) {
2019-11-07 01:24:34 +08:00
toSign := makeSigBuffer(domain, typeHint, contents)
sig, err := privateKey.Sign(toSign)
if err != nil {
return nil, err
}
return &SignedEnvelope{
PublicKey: privateKey.GetPublic(),
TypeHint: typeHint,
contents: contents,
signature: sig,
2019-11-07 01:24:34 +08:00
}, nil
}
func UnmarshalEnvelope(serializedEnvelope []byte) (*SignedEnvelope, error) {
e := pb.SignedEnvelope{}
if err := proto.Unmarshal(serializedEnvelope, &e); err != nil {
return nil, err
}
key, err := PublicKeyFromProto(e.PublicKey)
2019-11-07 01:24:34 +08:00
if err != nil {
return nil, err
2019-11-07 01:24:34 +08:00
}
return &SignedEnvelope{
PublicKey: key,
TypeHint: e.TypeHint,
contents: e.Contents,
signature: e.Signature,
}, nil
2019-11-07 01:24:34 +08:00
}
func (e *SignedEnvelope) SignerID() (peer.ID, error) {
return peer.IDFromPublicKey(e.PublicKey)
2019-11-07 01:24:34 +08:00
}
func (e *SignedEnvelope) Validate(domain string) (bool, error) {
toVerify := makeSigBuffer(domain, e.TypeHint, e.contents)
return e.PublicKey.Verify(toVerify, e.signature)
}
func (e *SignedEnvelope) Marshal() ([]byte, error) {
key, err := PublicKeyToProto(e.PublicKey)
if err != nil {
2019-11-07 01:24:34 +08:00
return nil, err
}
msg := pb.SignedEnvelope{
PublicKey: key,
TypeHint: e.TypeHint,
Contents: e.contents,
Signature: e.signature,
}
return proto.Marshal(&msg)
2019-11-07 01:24:34 +08:00
}
func (e *SignedEnvelope) Open(domain string) ([]byte, error) {
valid, err := e.Validate(domain)
2019-11-07 01:24:34 +08:00
if err != nil {
return nil, err
}
if !valid {
return nil, errors.New("invalid signature or incorrect domain")
2019-11-07 01:24:34 +08:00
}
return e.contents, nil
2019-11-07 01:24:34 +08:00
}
func makeSigBuffer(domain string, typeHint []byte, content []byte) []byte {
b := bytes.Buffer{}
domainBytes := []byte(domain)
b.Write(encodedSize(domainBytes))
b.Write(domainBytes)
b.Write(encodedSize(typeHint))
b.Write(typeHint)
b.Write(encodedSize(content))
b.Write(content)
return b.Bytes()
}
func encodedSize(content []byte) []byte {
b := make([]byte, 8)
binary.BigEndian.PutUint64(b, uint64(len(content)))
return b
}