lbryschema.go/claim/sign.go
Mark Beamer Jr 9159c7602d
added support for proto3 metadata definitions
added signing capabilities
all with unit tests
2019-04-07 00:29:12 -04:00

112 lines
2.6 KiB
Go

package claim
import (
"crypto/sha256"
"encoding/hex"
"github.com/lbryio/lbry.go/extras/errors"
"github.com/lbryio/lbryschema.go/address"
"github.com/btcsuite/btcd/btcec"
)
func Sign(privKey btcec.PrivateKey, channel ClaimHelper, claim ClaimHelper, k string) (*Signature, error) {
if channel.GetChannel() == nil {
return nil, errors.Err("claim as channel is not of type channel")
}
if claim.LegacyClaim != nil {
return claim.signV1(privKey, channel, k)
}
return claim.sign(privKey, channel, k)
}
func (c *ClaimHelper) sign(privKey btcec.PrivateKey, channel ClaimHelper, firstInputTxID string) (*Signature, error) {
txidBytes, err := hex.DecodeString(firstInputTxID)
if err != nil {
return nil, errors.Err(err)
}
metadataBytes, err := c.serialized()
if err != nil {
return nil, errors.Err(err)
}
var digest []byte
digest = append(digest, txidBytes...)
digest = append(digest, c.ClaimID...)
digest = append(digest, metadataBytes...)
hash := sha256.Sum256(digest)
hashBytes := make([]byte, len(hash))
for i, b := range hash {
hashBytes[i] = b
}
sig, err := privKey.Sign(hashBytes)
if err != nil {
return nil, errors.Err(err)
}
return &Signature{*sig}, nil
}
func (c *ClaimHelper) signV1(privKey btcec.PrivateKey, channel ClaimHelper, claimAddress string) (*Signature, error) {
metadataBytes, err := c.serializedNoSignature()
if err != nil {
return nil, errors.Err(err)
}
addressBytes, err := address.DecodeAddress(claimAddress, "lbrycrd_main")
if err != nil {
return nil, errors.Prefix("V1 signing requires claim address and the decode failed with: ", err)
}
var digest []byte
address := make([]byte, len(addressBytes))
for i, b := range addressBytes {
address[i] = b
}
digest = append(digest, address...)
digest = append(digest, metadataBytes...)
digest = append(digest, channel.ClaimID...)
hash := sha256.Sum256(digest)
hashBytes := make([]byte, len(hash))
for i, b := range hash {
hashBytes[i] = b
}
sig, err := privKey.Sign(hashBytes)
if err != nil {
return nil, errors.Err(err)
}
return &Signature{*sig}, nil
}
type Signature struct {
btcec.Signature
}
func (s *Signature) LBRYSDKEncode() ([]byte, error) {
if s.R == nil || s.S == nil {
return nil, errors.Err("invalid signature, both S & R are nil")
}
rBytes := s.R.Bytes()
sBytes := s.S.Bytes()
return append(rBytes, sBytes...), nil
}
// rev reverses a byte slice. useful for switching endian-ness
func reverseBytes(b []byte) []byte {
r := make([]byte, len(b))
for left, right := 0, len(b)-1; left < right; left, right = left+1, right-1 {
r[left], r[right] = b[right], b[left]
}
return r
}