diff --git a/address/address_test.go b/address/address_test.go index 119fc5c..5b631a5 100644 --- a/address/address_test.go +++ b/address/address_test.go @@ -2,12 +2,11 @@ package address import "testing" - -func TestDecodeAddress(t *testing.T) { +func TestDecodeAddressLBRYCrdMain(t *testing.T) { addr := "bUc9gyCJPKu2CBYpTvJ98MdmsLb68utjP6" correct := [25]byte{85, 174, 41, 64, 245, 110, 91, 239, 43, 208, 32, 73, 115, 20, 70, 204, 83, 199, 3, 206, 210, 176, 194, 188, 193} - result, err := DecodeAddress(addr) + result, err := DecodeAddress(addr, "lbrycrd_main") if err != nil { t.Error(err) } @@ -16,11 +15,11 @@ func TestDecodeAddress(t *testing.T) { } } -func TestEncodeAddress(t *testing.T) { +func TestEncodeAddressLBRYCrdMain(t *testing.T) { addr := [25]byte{85, 174, 41, 64, 245, 110, 91, 239, 43, 208, 32, 73, 115, 20, 70, 204, 83, 199, 3, 206, 210, 176, 194, 188, 193} correct := "bUc9gyCJPKu2CBYpTvJ98MdmsLb68utjP6" - result, err := EncodeAddress(addr) + result, err := EncodeAddress(addr, "lbrycrd_main") if err != nil { t.Error(err) } diff --git a/address/decode.go b/address/decode.go index fb99335..6d244fa 100644 --- a/address/decode.go +++ b/address/decode.go @@ -1,11 +1,11 @@ package address import ( - "errors" "./base58" + "errors" ) -func DecodeAddress(address string) ([address_length]byte, error) { +func DecodeAddress(address string, blockchainName string) ([address_length]byte, error) { decoded, err := base58.DecodeBase58(address, address_length) if err != nil { return [address_length]byte{}, errors.New("failed to decode") @@ -14,5 +14,5 @@ func DecodeAddress(address string) ([address_length]byte, error) { for i, b := range decoded { buf[i] = b } - return ValidateAddress(buf) + return ValidateAddress(buf, blockchainName) } diff --git a/address/encode.go b/address/encode.go index 3c6c4dc..59118af 100644 --- a/address/encode.go +++ b/address/encode.go @@ -4,8 +4,8 @@ import ( "./base58" ) -func EncodeAddress(address [address_length]byte) (string, error) { - buf, err := ValidateAddress(address) +func EncodeAddress(address [address_length]byte, blockchainName string) (string, error) { + buf, err := ValidateAddress(address, blockchainName) if err != nil { return "", err } diff --git a/address/validate.go b/address/validate.go index 29c954e..5b5a893 100644 --- a/address/validate.go +++ b/address/validate.go @@ -1,22 +1,37 @@ package address import ( - "errors" "crypto/sha256" + "errors" ) -const pubkey_prefix = byte(85) -const script_prefix = byte(122) +const lbrycrd_main_pubkey_prefix = byte(85) +const lbrycrd_main_script_prefix = byte(122) +const lbrycrd_testnet_pubkey_prefix = byte(111) +const lbrycrd_testnet_script_prefix = byte(196) +const lbrycrd_regtest_pubkey_prefix = byte(111) +const lbrycrd_regtest_script_prefix = byte(196) + const prefix_length = 1 const pubkey_length = 20 const checksum_length = 4 const address_length = prefix_length + pubkey_length + checksum_length -var address_prefixes = [2]byte {pubkey_prefix, script_prefix} +const lbrycrd_main = "lbrycrd_main" +const lbrycrd_testnet = "lbrycrd_testnet" +const lbrycrd_regtest = "lbrycrd_regtest" +var address_prefixes = map[string][2]byte{} -func PrefixIsValid(address [address_length]byte) bool { +func SetPrefixes() { + address_prefixes[lbrycrd_main] = [2]byte{lbrycrd_main_pubkey_prefix, lbrycrd_main_script_prefix} + address_prefixes[lbrycrd_testnet] = [2]byte{lbrycrd_testnet_pubkey_prefix, lbrycrd_testnet_script_prefix} + address_prefixes[lbrycrd_regtest] = [2]byte{lbrycrd_regtest_pubkey_prefix, lbrycrd_regtest_script_prefix} +} + +func PrefixIsValid(address [address_length]byte, blockchainName string) bool { + SetPrefixes() prefix := address[0] - for _, addr_prefix := range address_prefixes { + for _, addr_prefix := range address_prefixes[blockchainName] { if addr_prefix == prefix { return true } @@ -25,7 +40,7 @@ func PrefixIsValid(address [address_length]byte) bool { } func PubKeyIsValid(address [address_length]byte) bool { - pubkey := address[prefix_length:pubkey_length+prefix_length] + pubkey := address[prefix_length : pubkey_length+prefix_length] // TODO: validate this for real if len(pubkey) != pubkey_length { return false @@ -35,7 +50,9 @@ func PubKeyIsValid(address [address_length]byte) bool { func ChecksumIsValid(address [address_length]byte) bool { checksum := [checksum_length]byte{} - for i := range checksum {checksum[i] = address[prefix_length+pubkey_length+i]} + for i := range checksum { + checksum[i] = address[prefix_length+pubkey_length+i] + } real_checksum := sha256.Sum256(address[:prefix_length+pubkey_length]) real_checksum = sha256.Sum256(real_checksum[:]) for i, c := range checksum { @@ -46,8 +63,11 @@ func ChecksumIsValid(address [address_length]byte) bool { return true } -func ValidateAddress(address [address_length]byte) ([address_length]byte, error) { - if !PrefixIsValid(address) { +func ValidateAddress(address [address_length]byte, blockchainName string) ([address_length]byte, error) { + if blockchainName != lbrycrd_main && blockchainName != lbrycrd_testnet && blockchainName != lbrycrd_regtest { + return address, errors.New("invalid blockchain name") + } + if !PrefixIsValid(address, blockchainName) { return address, errors.New("invalid prefix") } if !PubKeyIsValid(address) { diff --git a/binding/lbryschema-python-binding.go b/binding/lbryschema-python-binding.go index 5b23071..2514dce 100644 --- a/binding/lbryschema-python-binding.go +++ b/binding/lbryschema-python-binding.go @@ -1,20 +1,21 @@ package main + import ( - "C" "../claim" + "C" ) //export VerifySignature -func VerifySignature(claimHex string, certificateHex string, claimAddress string, certificateId string) bool { - decodedClaim, err := claim.DecodeClaimHex(claimHex) +func VerifySignature(claimHex string, certificateHex string, claimAddress string, certificateId string, blockchainName string) bool { + decodedClaim, err := claim.DecodeClaimHex(claimHex, blockchainName) if err != nil { return false } - decodedCertificate, err := claim.DecodeClaimHex(certificateHex) + decodedCertificate, err := claim.DecodeClaimHex(certificateHex, blockchainName) if err != nil { return false } - result, err := decodedClaim.ValidateClaimSignature(decodedCertificate, claimAddress, certificateId) + result, err := decodedClaim.ValidateClaimSignature(decodedCertificate, claimAddress, certificateId, blockchainName) if err != nil { return false } @@ -25,8 +26,8 @@ func VerifySignature(claimHex string, certificateHex string, claimAddress string } //export DecodeClaimHex -func DecodeClaimHex(claimHex string) *C.char { - decodedClaim, err := claim.DecodeClaimHex(claimHex) +func DecodeClaimHex(claimHex string, blockchainName string) *C.char { + decodedClaim, err := claim.DecodeClaimHex(claimHex, blockchainName) if err != nil { return C.CString("decode error") } diff --git a/claim/claim.go b/claim/claim.go index 228a275..b6d403d 100644 --- a/claim/claim.go +++ b/claim/claim.go @@ -1,18 +1,41 @@ package claim import ( - "github.com/golang/protobuf/proto" - "encoding/hex" + "../address" "../pb" + "encoding/hex" "errors" + "github.com/golang/protobuf/proto" ) type ClaimHelper struct { *pb.Claim } -func (claim *ClaimHelper) LoadFromBytes(raw_claim []byte) (error) { - if claim.String() != "" { +func (c *ClaimHelper) ValidateAddresses(blockchainName string) error { + // check the validity of a fee address + if c.GetClaimType() == pb.Claim_streamType { + fee := c.GetStream().GetMetadata().GetFee() + if fee.String() != "" { + tmp_addr := fee.GetAddress() + if len(tmp_addr) != 25 { + return errors.New("invalid address length") + } + addr := [25]byte{} + for i := range addr { + addr[i] = tmp_addr[i] + } + _, err := address.EncodeAddress(addr, blockchainName) + if err != nil { + return err + } + } + } + return nil +} + +func (c *ClaimHelper) LoadFromBytes(raw_claim []byte, blockchainName string) error { + if c.String() != "" { return errors.New("already initialized") } if len(raw_claim) < 1 { @@ -24,53 +47,53 @@ func (claim *ClaimHelper) LoadFromBytes(raw_claim []byte) (error) { if err != nil { return err } - *claim = ClaimHelper{claim_pb} - + *c = ClaimHelper{claim_pb} + c.ValidateAddresses(blockchainName) return nil } -func (claim *ClaimHelper) LoadFromHexString(claim_hex string) (error) { +func (c *ClaimHelper) LoadFromHexString(claim_hex string, blockchainName string) error { buf, err := hex.DecodeString(claim_hex) if err != nil { return err } - return claim.LoadFromBytes(buf) + return c.LoadFromBytes(buf, blockchainName) } -func DecodeClaimBytes(serialized []byte) (*ClaimHelper, error) { +func DecodeClaimBytes(serialized []byte, blockchainName string) (*ClaimHelper, error) { claim := &ClaimHelper{&pb.Claim{}} - err := claim.LoadFromBytes(serialized) + err := claim.LoadFromBytes(serialized, blockchainName) if err != nil { return nil, err } return claim, nil } -func DecodeClaimHex(serialized string) (*ClaimHelper, error) { +func DecodeClaimHex(serialized string, blockchainName string) (*ClaimHelper, error) { claim_bytes, err := hex.DecodeString(serialized) if err != nil { return nil, err } - return DecodeClaimBytes(claim_bytes) + return DecodeClaimBytes(claim_bytes, blockchainName) } -func (m *ClaimHelper) GetStream() *pb.Stream { - if m != nil { - return m.Stream +func (c *ClaimHelper) GetStream() *pb.Stream { + if c != nil { + return c.Stream } return nil } -func (m *ClaimHelper) GetCertificate() *pb.Certificate { - if m != nil { - return m.Certificate +func (c *ClaimHelper) GetCertificate() *pb.Certificate { + if c != nil { + return c.Certificate } return nil } -func (m *ClaimHelper) GetPublisherSignature() *pb.Signature { - if m != nil { - return m.PublisherSignature +func (c *ClaimHelper) GetPublisherSignature() *pb.Signature { + if c != nil { + return c.PublisherSignature } return nil } diff --git a/claim/decode_test.go b/claim/decode_test.go index 8ea2a0a..ef30acd 100644 --- a/claim/decode_test.go +++ b/claim/decode_test.go @@ -1,20 +1,19 @@ package claim import ( - "testing" "encoding/hex" + "testing" ) var raw_claims = []string{ -"08011002225e0801100322583056301006072a8648ce3d020106052b8104000a03420004d015365a40f3e5c03c87227168e5851f44659837bcf6a3398ae633bc37d04ee19baeb26dc888003bd728146dbea39f5344bf8c52cedaf1a3a1623a0166f4a367", -"080110011ad7010801128f01080410011a0c47616d65206f66206c696665221047616d65206f66206c696665206769662a0b4a6f686e20436f6e776179322e437265617469766520436f6d6d6f6e73204174747269627574696f6e20342e3020496e7465726e6174696f6e616c38004224080110011a195569c917f18bf5d2d67f1346aa467b218ba90cdbf2795676da250000803f4a0052005a001a41080110011a30b6adf6e2a62950407ea9fb045a96127b67d39088678d2f738c359894c88d95698075ee6203533d3c204330713aa7acaf2209696d6167652f6769662a5c080110031a40c73fe1be4f1743c2996102eec6ce0509e03744ab940c97d19ddb3b25596206367ab1a3d2583b16c04d2717eeb983ae8f84fee2a46621ffa5c4726b30174c6ff82214251305ca93d4dbedb50dceb282ebcb7b07b7ac65", -"080110011ad7010801128f01080410011a0c47616d65206f66206c696665221047616d65206f66206c696665206769662a0b4a6f686e20436f6e776179322e437265617469766520436f6d6d6f6e73204174747269627574696f6e20342e3020496e7465726e6174696f6e616c38004224080110011a195569c917f18bf5d2d67f1346aa467b218ba90cdbf2795676da250000803f4a0052005a001a41080110011a30b6adf6e2a62950407ea9fb045a96127b67d39088678d2f738c359894c88d95698075ee6203533d3c204330713aa7acaf2209696d6167652f676966", + "08011002225e0801100322583056301006072a8648ce3d020106052b8104000a03420004d015365a40f3e5c03c87227168e5851f44659837bcf6a3398ae633bc37d04ee19baeb26dc888003bd728146dbea39f5344bf8c52cedaf1a3a1623a0166f4a367", + "080110011ad7010801128f01080410011a0c47616d65206f66206c696665221047616d65206f66206c696665206769662a0b4a6f686e20436f6e776179322e437265617469766520436f6d6d6f6e73204174747269627574696f6e20342e3020496e7465726e6174696f6e616c38004224080110011a195569c917f18bf5d2d67f1346aa467b218ba90cdbf2795676da250000803f4a0052005a001a41080110011a30b6adf6e2a62950407ea9fb045a96127b67d39088678d2f738c359894c88d95698075ee6203533d3c204330713aa7acaf2209696d6167652f6769662a5c080110031a40c73fe1be4f1743c2996102eec6ce0509e03744ab940c97d19ddb3b25596206367ab1a3d2583b16c04d2717eeb983ae8f84fee2a46621ffa5c4726b30174c6ff82214251305ca93d4dbedb50dceb282ebcb7b07b7ac65", + "080110011ad7010801128f01080410011a0c47616d65206f66206c696665221047616d65206f66206c696665206769662a0b4a6f686e20436f6e776179322e437265617469766520436f6d6d6f6e73204174747269627574696f6e20342e3020496e7465726e6174696f6e616c38004224080110011a195569c917f18bf5d2d67f1346aa467b218ba90cdbf2795676da250000803f4a0052005a001a41080110011a30b6adf6e2a62950407ea9fb045a96127b67d39088678d2f738c359894c88d95698075ee6203533d3c204330713aa7acaf2209696d6167652f676966", } - func TestDecodeClaims(t *testing.T) { - for _, claim_hex := range(raw_claims) { - claim, err := DecodeClaimHex(claim_hex) + for _, claim_hex := range raw_claims { + claim, err := DecodeClaimHex(claim_hex, "lbrycrd_main") if err != nil { t.Error(err) } @@ -30,7 +29,7 @@ func TestDecodeClaims(t *testing.T) { func TestStripSignature(t *testing.T) { claim_hex := raw_claims[1] - claim, err := DecodeClaimHex(claim_hex) + claim, err := DecodeClaimHex(claim_hex, "lbrycrd_main") if err != nil { t.Error(err) } diff --git a/claim/pretty.go b/claim/pretty.go index 295651e..a2d4155 100644 --- a/claim/pretty.go +++ b/claim/pretty.go @@ -1,16 +1,28 @@ package claim import ( + "encoding/json" + "fmt" "github.com/golang/protobuf/jsonpb" ) -func marshalToString(claim *ClaimHelper) (string, error) { +func marshalToString(c *ClaimHelper) (string, error) { m_pb := &jsonpb.Marshaler{} - return m_pb.MarshalToString(claim) + return m_pb.MarshalToString(c) } -func (claim *ClaimHelper) RenderJSON() (string, error) { - return marshalToString(claim) +func (c *ClaimHelper) RenderJSON() (string, error) { + r, err := marshalToString(c) + if err != nil { + fmt.Println("err") + return "", err + } + var dat map[string]interface{} + err = json.Unmarshal([]byte(r), &dat) + if err != nil { + return "", err + } + return r, nil } -//TODO: encode byte arrays with b58 for addresses and b16 for source hashes instead of the default of b64 \ No newline at end of file +//TODO: encode byte arrays with b58 for addresses and b16 for source hashes instead of the default of b64 diff --git a/claim/validator.go b/claim/validator.go index 593918e..ac565d6 100644 --- a/claim/validator.go +++ b/claim/validator.go @@ -2,14 +2,14 @@ package claim import ( "../address" + "crypto/ecdsa" "crypto/sha256" - "errors" - "encoding/asn1" "crypto/x509/pkix" + "encoding/asn1" + "encoding/hex" + "errors" "github.com/btcsuite/btcd/btcec" "math/big" - "crypto/ecdsa" - "encoding/hex" ) type publicKeyInfo struct { @@ -21,10 +21,16 @@ type publicKeyInfo struct { const SECP256k1 = "SECP256k1" func GetClaimSignatureDigest(claimAddress [25]byte, certificateId [20]byte, serializedNoSig []byte) [32]byte { - 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)} + 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) + } digest := sha256.Sum256(combined) return [32]byte(digest) } @@ -57,7 +63,7 @@ func (claim *ClaimHelper) VerifyDigest(certificate *ClaimHelper, signature [64]b return false } -func (claim *ClaimHelper) ValidateClaimSignatureBytes(certificate *ClaimHelper, claimAddress [25]byte, certificateId [20]byte) (bool, error) { +func (claim *ClaimHelper) ValidateClaimSignatureBytes(certificate *ClaimHelper, claimAddress [25]byte, certificateId [20]byte, blockchainName string) (bool, error) { signature := claim.GetPublisherSignature() if signature == nil { return false, errors.New("claim does not have a signature") @@ -68,7 +74,7 @@ func (claim *ClaimHelper) ValidateClaimSignatureBytes(certificate *ClaimHelper, signatureBytes[i] = signatureSlice[i] } - claimAddress, err := address.ValidateAddress(claimAddress) + claimAddress, err := address.ValidateAddress(claimAddress, blockchainName) if err != nil { return false, errors.New("invalid address") } @@ -82,8 +88,8 @@ func (claim *ClaimHelper) ValidateClaimSignatureBytes(certificate *ClaimHelper, return claim.VerifyDigest(certificate, signatureBytes, claimDigest), nil } -func (claim *ClaimHelper) ValidateClaimSignature(certificate *ClaimHelper, claimAddress string, certificateId string) (bool, error) { - addressBytes, err := address.DecodeAddress(claimAddress) +func (claim *ClaimHelper) ValidateClaimSignature(certificate *ClaimHelper, claimAddress string, certificateId string, blockchainName string) (bool, error) { + addressBytes, err := address.DecodeAddress(claimAddress, blockchainName) if err != nil { return false, err } @@ -95,5 +101,5 @@ func (claim *ClaimHelper) ValidateClaimSignature(certificate *ClaimHelper, claim for i := range certificateIdBytes { certificateIdBytes[i] = certificateIdSlice[i] } - return claim.ValidateClaimSignatureBytes(certificate, addressBytes, certificateIdBytes) + return claim.ValidateClaimSignatureBytes(certificate, addressBytes, certificateIdBytes, blockchainName) } diff --git a/claim/validator_test.go b/claim/validator_test.go index 15d68b6..58b68d4 100644 --- a/claim/validator_test.go +++ b/claim/validator_test.go @@ -8,13 +8,13 @@ func TestValidateClaimSignature(t *testing.T) { cert_claim_hex := "08011002225e0801100322583056301006072a8648ce3d020106052b8104000a03420004d015365a40f3e5c03c87227168e5851f44659837bcf6a3398ae633bc37d04ee19baeb26dc888003bd728146dbea39f5344bf8c52cedaf1a3a1623a0166f4a367" signed_claim_hex := "080110011ad7010801128f01080410011a0c47616d65206f66206c696665221047616d65206f66206c696665206769662a0b4a6f686e20436f6e776179322e437265617469766520436f6d6d6f6e73204174747269627574696f6e20342e3020496e7465726e6174696f6e616c38004224080110011a195569c917f18bf5d2d67f1346aa467b218ba90cdbf2795676da250000803f4a0052005a001a41080110011a30b6adf6e2a62950407ea9fb045a96127b67d39088678d2f738c359894c88d95698075ee6203533d3c204330713aa7acaf2209696d6167652f6769662a5c080110031a40c73fe1be4f1743c2996102eec6ce0509e03744ab940c97d19ddb3b25596206367ab1a3d2583b16c04d2717eeb983ae8f84fee2a46621ffa5c4726b30174c6ff82214251305ca93d4dbedb50dceb282ebcb7b07b7ac65" - signed_claim, _ := DecodeClaimHex(signed_claim_hex) - cert_claim, _ := DecodeClaimHex(cert_claim_hex) + signed_claim, _ := DecodeClaimHex(signed_claim_hex, "lbrycrd_main") + cert_claim, _ := DecodeClaimHex(cert_claim_hex, "lbrycrd_main") claim_addr := "bSkUov7HMWpYBiXackDwRnR5ishhGHvtJt" cert_id := "251305ca93d4dbedb50dceb282ebcb7b07b7ac65" - result, err := signed_claim.ValidateClaimSignature(cert_claim, claim_addr, cert_id) + result, err := signed_claim.ValidateClaimSignature(cert_claim, claim_addr, cert_id, "lbrycrd_main") if err != nil { t.Error(err) } @@ -27,13 +27,13 @@ func TestFailToValidateClaimSignature(t *testing.T) { cert_claim_hex := "08011002225e0801100322583056301006072a8648ce3d020106052b8104000a03420004d015365a40f3e5c03c87227168e5851f44659837bcf6a3398ae633bc37d04ee19baeb26dc888003bd728146dbea39f5344bf8c52cedaf1a3a1623a0166f4a367" signed_claim_hex := "080110011ad7010801128f01080410011a0c47616d65206f66206c696665221047616d65206f66206c696665206769662a0b4a6f686e20436f6e776179322e437265617469766520436f6d6d6f6e73204174747269627574696f6e20342e3020496e7465726e6174696f6e616c38004224080110011a195569c917f18bf5d2d67f1346aa467b218ba90cdbf2795676da250000803f4a0052005a001a41080110011a30b6adf6e2a62950407ea9fb045a96127b67d39088678d2f738c359894c88d95698075ee6203533d3c204330713aa7acaf2209696d6167652f6769662a5c080110031a40c73fe1be4f1743c2996102eec6ce0509e03744ab940c97d19ddb3b25596206367ab1a3d2583b16c04d2717eeb983ae8f84fee2a46621ffa5c4726b30174c6ff82214251305ca93d4dbedb50dceb282ebcb7b07b7ac65" - signed_claim, _ := DecodeClaimHex(signed_claim_hex) - cert_claim, _ := DecodeClaimHex(cert_claim_hex) + signed_claim, _ := DecodeClaimHex(signed_claim_hex, "lbrycrd_main") + cert_claim, _ := DecodeClaimHex(cert_claim_hex, "lbrycrd_main") claim_addr := "bSkUov7HMWpYBiXackDwRnR5ishhGHvtJt" cert_id := "251305ca93d4dbedb50dceb282ebcb7b07b7ac64" - result, err := signed_claim.ValidateClaimSignature(cert_claim, claim_addr, cert_id) + result, err := signed_claim.ValidateClaimSignature(cert_claim, claim_addr, cert_id, "lbrycrd_main") if err != nil { t.Error(err) } diff --git a/cli/lbryschema-cli.go b/cli/lbryschema-cli.go index e49bd9e..96322fa 100644 --- a/cli/lbryschema-cli.go +++ b/cli/lbryschema-cli.go @@ -1,16 +1,16 @@ package main import ( - "os" "../claim" "fmt" + "os" ) -func main() { +func main() { args := os.Args[1:] if len(args) == 1 { claim_bytes := []byte(args[0]) - decoded, err := claim.DecodeClaimBytes(claim_bytes) + decoded, err := claim.DecodeClaimBytes(claim_bytes, "lbrycrd_main") if err != nil { fmt.Println("Decoding error:", err) return @@ -24,7 +24,7 @@ func main() { return } else if (len(args) == 2) && (args[1] == "--decode_hex") { claim_hex := args[0] - decoded, err := claim.DecodeClaimHex(claim_hex) + decoded, err := claim.DecodeClaimHex(claim_hex, "lbrycrd_main") if err != nil { fmt.Println("Decoding error:", err) return