lbry.go/claim/validator.go

109 lines
3 KiB
Go
Raw Normal View History

2017-09-12 18:02:30 +02:00
package claim
import (
"crypto/ecdsa"
2017-09-12 18:02:30 +02:00
"crypto/sha256"
2017-11-08 03:39:08 +01:00
"crypto/x509/pkix"
"encoding/asn1"
"encoding/hex"
"errors"
2017-11-08 03:39:08 +01:00
"github.com/btcsuite/btcd/btcec"
2018-02-15 20:51:51 +01:00
"github.com/lbryio/lbryschema.go/address"
2017-11-08 03:39:08 +01:00
"math/big"
2017-09-12 18:02:30 +02:00
)
2017-11-08 03:39:08 +01:00
type publicKeyInfo struct {
Raw asn1.RawContent
Algorithm pkix.AlgorithmIdentifier
PublicKey asn1.BitString
}
const SECP256k1 = "SECP256k1"
2018-02-15 20:51:51 +01:00
//const NIST256p = "NIST256p"
//const NIST384p = "NIST384p"
2017-11-08 03:39:08 +01:00
func GetClaimSignatureDigest(claimAddress [25]byte, certificateId [20]byte, serializedNoSig []byte) [32]byte {
var combined []byte
for _, c := range claimAddress {
combined = append(combined, c)
}
for _, c := range serializedNoSig {
combined = append(combined, c)
}
for _, c := range certificateId {
combined = append(combined, c)
}
2017-09-12 18:02:30 +02:00
digest := sha256.Sum256(combined)
return [32]byte(digest)
}
2017-11-27 16:22:04 +01:00
func (c *ClaimHelper) GetCertificatePublicKey() (*btcec.PublicKey, error) {
derBytes := c.GetCertificate().GetPublicKey()
2017-11-08 03:39:08 +01:00
pub := publicKeyInfo{}
asn1.Unmarshal(derBytes, &pub)
2018-02-15 20:51:51 +01:00
pubkeyBytes := []byte(pub.PublicKey.Bytes)
p, err := btcec.ParsePubKey(pubkeyBytes, btcec.S256())
2017-11-08 03:39:08 +01:00
if err != nil {
2017-11-13 16:11:19 +01:00
return &btcec.PublicKey{}, err
2017-11-08 03:39:08 +01:00
}
2017-11-13 16:11:19 +01:00
return p, err
2017-11-08 03:39:08 +01:00
}
2017-11-27 16:22:04 +01:00
func (c *ClaimHelper) VerifyDigest(certificate *ClaimHelper, signature [64]byte, digest [32]byte) bool {
2018-02-15 20:51:51 +01:00
publicKey, err := certificate.GetCertificatePublicKey()
2017-11-08 03:39:08 +01:00
if err != nil {
return false
}
2017-11-27 16:22:04 +01:00
if c.PublisherSignature.SignatureType.String() == SECP256k1 {
2017-11-08 03:39:08 +01:00
R := &big.Int{}
S := &big.Int{}
R.SetBytes(signature[0:32])
S.SetBytes(signature[32:64])
2018-02-15 20:51:51 +01:00
return ecdsa.Verify(publicKey.ToECDSA(), digest[:], R, S)
2017-11-08 03:39:08 +01:00
}
return false
}
2017-11-27 16:22:04 +01:00
func (c *ClaimHelper) ValidateClaimSignatureBytes(certificate *ClaimHelper, claimAddress [25]byte, certificateId [20]byte, blockchainName string) (bool, error) {
signature := c.GetPublisherSignature()
2017-11-08 03:39:08 +01:00
if signature == nil {
return false, errors.New("claim does not have a signature")
}
signatureSlice := signature.GetSignature()
signatureBytes := [64]byte{}
for i := range signatureBytes {
signatureBytes[i] = signatureSlice[i]
}
claimAddress, err := address.ValidateAddress(claimAddress, blockchainName)
2017-11-08 03:39:08 +01:00
if err != nil {
return false, errors.New("invalid address")
}
2017-11-27 16:22:04 +01:00
serializedNoSig, err := c.SerializedNoSignature()
2017-11-08 03:39:08 +01:00
if err != nil {
return false, errors.New("serialization error")
}
claimDigest := GetClaimSignatureDigest(claimAddress, certificateId, serializedNoSig)
2017-11-27 16:22:04 +01:00
return c.VerifyDigest(certificate, signatureBytes, claimDigest), nil
2017-09-12 18:02:30 +02:00
}
2017-11-27 16:22:04 +01:00
func (c *ClaimHelper) ValidateClaimSignature(certificate *ClaimHelper, claimAddress string, certificateId string, blockchainName string) (bool, error) {
addressBytes, err := address.DecodeAddress(claimAddress, blockchainName)
2017-11-08 03:39:08 +01:00
if err != nil {
return false, err
}
certificateIdSlice, err := hex.DecodeString(certificateId)
if err != nil {
return false, err
}
certificateIdBytes := [20]byte{}
for i := range certificateIdBytes {
certificateIdBytes[i] = certificateIdSlice[i]
}
2017-11-27 16:22:04 +01:00
return c.ValidateClaimSignatureBytes(certificate, addressBytes, certificateIdBytes, blockchainName)
2017-09-12 18:02:30 +02:00
}