mirror of
https://github.com/selfxyz/self.git
synced 2026-01-15 01:28:18 -05:00
* feat: helper functions and constant for go-sdk * feat: formatRevealedDataPacked in go * chore: refactor * feat: define struct for selfBackendVerifier * feat: verify function for selfBackendVerifier * feat(wip): custom hasher * feat: SelfVerifierBacked in go * test(wip): scope and userContextHash is failing * test: zk proof verified * fix: MockConfigStore getactionId function * chore: refactor * chore: remove abi duplicate files * chore: move configStore to utils * chore: modified VcAndDiscloseProof struct * chore: more review changes * feat: impl DefaultConfig and InMemoryConfigStore * chore: refactor and export functions * fix: module import and README * chore: remove example folder * chore: remove pointers from VerificationConfig * chore: coderabbit review fixes * chore: more coderabbit review fix * chore: add license * fix: convert attestationIdd to int * chore: remove duplicate code --------- Co-authored-by: ayman <aymanshaik1015@gmail.com>
123 lines
3.2 KiB
Go
123 lines
3.2 KiB
Go
package common
|
|
|
|
import (
|
|
"fmt"
|
|
"math/big"
|
|
"regexp"
|
|
"strings"
|
|
|
|
"github.com/iden3/go-iden3-crypto/poseidon"
|
|
)
|
|
|
|
func FlexiblePoseidon(inputs []*big.Int) (*big.Int, error) {
|
|
if len(inputs) == 0 {
|
|
return nil, fmt.Errorf("no inputs provided")
|
|
}
|
|
|
|
if len(inputs) > 17 {
|
|
return nil, fmt.Errorf("unsupported number of inputs: %d", len(inputs))
|
|
}
|
|
|
|
result, err := poseidon.Hash(inputs)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("poseidon hash failed: %w", err)
|
|
}
|
|
|
|
return result, nil
|
|
}
|
|
|
|
// StringToBigInt converts a string to a big.Int by treating each character as a byte
|
|
// Validates input contains only ASCII characters and doesn't exceed 31 bytes
|
|
func StringToBigInt(str string) (*big.Int, error) {
|
|
// Validate input contains only ASCII characters (0-127)
|
|
for _, char := range str {
|
|
if char > 127 {
|
|
return nil, fmt.Errorf("input must contain only ASCII characters (0-127)")
|
|
}
|
|
}
|
|
|
|
result := big.NewInt(0)
|
|
for i := 0; i < len(str); i++ {
|
|
// Shift left by 8 bits and add the character code
|
|
result.Lsh(result, 8)
|
|
result.Add(result, big.NewInt(int64(str[i])))
|
|
}
|
|
|
|
// Check size limit (31 bytes = 248 bits)
|
|
maxValue := new(big.Int)
|
|
maxValue.Lsh(big.NewInt(1), 248)
|
|
maxValue.Sub(maxValue, big.NewInt(1))
|
|
|
|
if result.Cmp(maxValue) > 0 {
|
|
return nil, fmt.Errorf("resulting BigInt exceeds maximum size of 31 bytes")
|
|
}
|
|
|
|
return result, nil
|
|
}
|
|
|
|
// FormatEndpoint removes protocol and path from URL, keeping only the domain
|
|
func FormatEndpoint(endpoint string) string {
|
|
if endpoint == "" {
|
|
return ""
|
|
}
|
|
|
|
// Remove protocol (http:// or https://)
|
|
re := regexp.MustCompile(`^https?://`)
|
|
formatted := re.ReplaceAllString(endpoint, "")
|
|
|
|
// Split by '/' and take only the first part (domain)
|
|
parts := strings.Split(formatted, "/")
|
|
return parts[0]
|
|
}
|
|
|
|
// HashEndpointWithScope implements the hashEndpointWithScope function from TypeScript
|
|
func HashEndpointWithScope(endpoint, scope string) (string, error) {
|
|
formattedEndpoint := FormatEndpoint(endpoint)
|
|
|
|
// Split endpoint into 31-character chunks (different from ts)
|
|
var endpointChunks []string
|
|
remaining := formattedEndpoint
|
|
for len(remaining) > 0 {
|
|
// Take up to 31 characters (safe slicing)
|
|
if len(remaining) > 31 {
|
|
chunk := remaining[:31]
|
|
endpointChunks = append(endpointChunks, chunk)
|
|
remaining = remaining[31:]
|
|
} else {
|
|
endpointChunks = append(endpointChunks, remaining)
|
|
remaining = ""
|
|
}
|
|
}
|
|
|
|
if len(endpointChunks) > 16 {
|
|
return "", fmt.Errorf("endpoint must be less than 496 characters")
|
|
}
|
|
|
|
chunkedEndpointBigInts := make([]*big.Int, len(endpointChunks))
|
|
for i, chunk := range endpointChunks {
|
|
bigInt, err := StringToBigInt(chunk)
|
|
if err != nil {
|
|
return "", fmt.Errorf("failed to convert chunk to BigInt: %w", err)
|
|
}
|
|
chunkedEndpointBigInts[i] = bigInt
|
|
}
|
|
|
|
endpointHash, err := FlexiblePoseidon(chunkedEndpointBigInts)
|
|
if err != nil {
|
|
return "", fmt.Errorf("failed to hash endpoint chunks: %w", err)
|
|
}
|
|
|
|
|
|
scopeBigInt, err := StringToBigInt(scope)
|
|
if err != nil {
|
|
return "", fmt.Errorf("failed to convert scope to BigInt: %w", err)
|
|
}
|
|
|
|
finalResult, err := poseidon.Hash([]*big.Int{endpointHash, scopeBigInt})
|
|
if err != nil {
|
|
return "", fmt.Errorf("failed to hash endpoint with scope: %w", err)
|
|
}
|
|
|
|
return finalResult.String(), nil
|
|
}
|