Add checksum validation for Ethereum address (#630)

pull/671/head
Elias Rodrigues 4 years ago committed by GitHub
parent 8941cbd00e
commit 4407f4dea0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 21
      baked_in.go
  2. 3
      doc.go
  3. 1
      go.mod
  4. 7
      go.sum
  5. 26
      validator_test.go

@ -4,6 +4,7 @@ import (
"bytes" "bytes"
"context" "context"
"crypto/sha256" "crypto/sha256"
"encoding/hex"
"encoding/json" "encoding/json"
"fmt" "fmt"
"net" "net"
@ -16,6 +17,8 @@ import (
"time" "time"
"unicode/utf8" "unicode/utf8"
"golang.org/x/crypto/sha3"
urn "github.com/leodido/go-urn" urn "github.com/leodido/go-urn"
) )
@ -532,7 +535,7 @@ func isISBN10(fl FieldLevel) bool {
return checksum%11 == 0 return checksum%11 == 0
} }
// IsEthereumAddress is the validation function for validating if the field's value is a valid ethereum address based currently only on the format // IsEthereumAddress is the validation function for validating if the field's value is a valid Ethereum address.
func isEthereumAddress(fl FieldLevel) bool { func isEthereumAddress(fl FieldLevel) bool {
address := fl.Field().String() address := fl.Field().String()
@ -544,7 +547,21 @@ func isEthereumAddress(fl FieldLevel) bool {
return true return true
} }
// checksum validation is blocked by https://github.com/golang/crypto/pull/28 // Checksum validation. Reference: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-55.md
address = address[2:] // Skip "0x" prefix.
h := sha3.NewLegacyKeccak256()
// hash.Hash's io.Writer implementation says it never returns an error. https://golang.org/pkg/hash/#Hash
_, _ = h.Write([]byte(strings.ToLower(address)))
hash := hex.EncodeToString(h.Sum(nil))
for i := 0; i < len(address); i++ {
if address[i] <= '9' { // Skip 0-9 digits: they don't have upper/lower-case.
continue
}
if hash[i] > '7' && address[i] >= 'a' || hash[i] <= '7' && address[i] <= 'F' {
return false
}
}
return true return true
} }

@ -879,8 +879,7 @@ Special thanks to Pieter Wuille for providng reference implementations.
Ethereum Address Ethereum Address
This validates that a string value contains a valid ethereum address. This validates that a string value contains a valid ethereum address.
The format of the string is checked to ensure it matches the standard Ethereum address format The format of the string is checked to ensure it matches the standard Ethereum address format.
Full validation is blocked by https://github.com/golang/crypto/pull/28
Usage: eth_addr Usage: eth_addr

@ -7,4 +7,5 @@ require (
github.com/go-playground/locales v0.13.0 github.com/go-playground/locales v0.13.0
github.com/go-playground/universal-translator v0.17.0 github.com/go-playground/universal-translator v0.17.0
github.com/leodido/go-urn v1.2.0 github.com/leodido/go-urn v1.2.0
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9
) )

@ -13,6 +13,13 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=

@ -5207,11 +5207,29 @@ func TestEthereumAddressValidation(t *testing.T) {
param string param string
expected bool expected bool
}{ }{
{"", false}, // All caps.
{"0x02F9AE5f22EA3fA88F05780B30385bEC", false}, {"0x52908400098527886E0F7030069857D2E4169EE7", true},
{"123f681646d4a755815f9cb19e1acc8565a0c2ac", false}, {"0x8617E340B3D01FA5F11F306F4090FD50E238070D", true},
{"0x02F9AE5f22EA3fA88F05780B30385bECFacbf130", true},
// All lower.
{"0xde709f2102306220921060314715629080e2fb77", true},
{"0x27b1fdb04752bbc536007a920d24acb045561c26", true},
{"0x123f681646d4a755815f9cb19e1acc8565a0c2ac", true}, {"0x123f681646d4a755815f9cb19e1acc8565a0c2ac", true},
// Mixed case: runs checksum validation.
{"0x02F9AE5f22EA3fA88F05780B30385bECFacbf130", true},
{"0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed", true},
{"0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359", true},
{"0xdbF03B407c01E7cD3CBea99509d93f8DDDC8C6FB", true},
{"0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb", true},
{"0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDB", false}, // Invalid checksum.
// Other.
{"", false},
{"D1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb", false}, // Missing "0x" prefix.
{"0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDbc", false}, // More than 40 hex digits.
{"0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aD", false}, // Less than 40 hex digits.
{"0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDw", false}, // Invalid hex digit "w".
} }
for i, test := range tests { for i, test := range tests {

Loading…
Cancel
Save