|
8 | 8 | "encoding/base64"
|
9 | 9 | "encoding/binary"
|
10 | 10 | "encoding/hex"
|
| 11 | + "fmt" |
11 | 12 | "io"
|
12 | 13 | "math/big"
|
13 | 14 |
|
@@ -124,6 +125,39 @@ func MagicSign(priv *ecdsa.PrivateKey, msg []byte) ([]byte, error) {
|
124 | 125 | return sig, nil
|
125 | 126 | }
|
126 | 127 |
|
| 128 | +// Base64 indicates that the given string should be Base64 encoded (std, with padding) |
| 129 | +type Base64 = string |
| 130 | + |
| 131 | +// Base58Check indicates that the given string should be in Base58Check encoded (coint type prefix on double hash of public key, BaseX-style Base58 encoding) |
| 132 | +type Base58Check = string |
| 133 | + |
| 134 | +// MagicVerify checks that the given public key hash payment address can be used to verify the given base64 signature and arbitrary message |
| 135 | +func MagicVerify(addr Base58Check, msg []byte, sig Base64) error { |
| 136 | + sigBytes, err := base64.StdEncoding.DecodeString(sig) |
| 137 | + if nil != err { |
| 138 | + return fmt.Errorf("could not decode signature: %w", err) |
| 139 | + } |
| 140 | + |
| 141 | + magichash := MagicHash(msg) |
| 142 | + pub, err := SigToPub(magichash, sigBytes) |
| 143 | + if nil != err { |
| 144 | + return fmt.Errorf("could not verify message: %w", err) |
| 145 | + } |
| 146 | + |
| 147 | + cointype, err := AddressToCointype(addr) |
| 148 | + if nil != err { |
| 149 | + // Neither a valid file nor string. Blast! |
| 150 | + return fmt.Errorf("can't detect coin type of %q: %v", addr, err) |
| 151 | + } |
| 152 | + |
| 153 | + guess := PublicKeyToAddress(cointype, *pub) |
| 154 | + if guess == addr { |
| 155 | + return nil |
| 156 | + } |
| 157 | + |
| 158 | + return fmt.Errorf("signature's public key hash payment address %q does not match given address %q", guess, addr) |
| 159 | +} |
| 160 | + |
127 | 161 | // SigToPub computes the public key from the message's magichash and the recovery signature (has the magic byte, a.k.a. "i" at the front of it)
|
128 | 162 | func SigToPub(magichash, dsig []byte) (*ecdsa.PublicKey, error) {
|
129 | 163 | rsig := make([]byte, 0, 65)
|
|
0 commit comments