mirror of
https://github.com/DeBrosOfficial/orama.git
synced 2026-03-27 17:54:13 +00:00
53 lines
1.4 KiB
Go
53 lines
1.4 KiB
Go
package auth
|
|
|
|
import (
|
|
"encoding/hex"
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/ethereum/go-ethereum/crypto"
|
|
)
|
|
|
|
// VerifyEVM verifies an Ethereum personal_sign signature.
|
|
func VerifyEVM(wallet, message, signatureHex string) error {
|
|
// Remove 0x prefix if present
|
|
sigHex := strings.TrimPrefix(signatureHex, "0x")
|
|
sigBytes, err := hex.DecodeString(sigHex)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to decode signature hex: %w", err)
|
|
}
|
|
|
|
if len(sigBytes) != 65 {
|
|
return fmt.Errorf("invalid signature length: got %d, want 65", len(sigBytes))
|
|
}
|
|
|
|
// Ethereum personal_sign prefix
|
|
prefixed := fmt.Sprintf("\x19Ethereum Signed Message:\n%d%s", len(message), message)
|
|
hash := crypto.Keccak256Hash([]byte(prefixed))
|
|
|
|
// Fix recovery ID: some wallets return v=27/28, need v=0/1
|
|
if sigBytes[64] >= 27 {
|
|
sigBytes[64] -= 27
|
|
}
|
|
|
|
pubKeyBytes, err := crypto.Ecrecover(hash.Bytes(), sigBytes)
|
|
if err != nil {
|
|
return fmt.Errorf("ecrecover failed: %w", err)
|
|
}
|
|
|
|
pubKey, err := crypto.UnmarshalPubkey(pubKeyBytes)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to unmarshal public key: %w", err)
|
|
}
|
|
|
|
recoveredAddr := crypto.PubkeyToAddress(*pubKey)
|
|
expectedAddr := strings.ToLower(strings.TrimPrefix(wallet, "0x"))
|
|
recoveredHex := strings.ToLower(recoveredAddr.Hex()[2:])
|
|
|
|
if recoveredHex != expectedAddr {
|
|
return fmt.Errorf("signature verification failed: recovered %s, expected %s", recoveredHex, expectedAddr)
|
|
}
|
|
|
|
return nil
|
|
}
|