- Core library with SVG and PNG generation - CLI tool with generate and batch commands - Cross-platform path handling for Windows compatibility - Comprehensive test suite with integration tests
87 lines
3.0 KiB
Go
87 lines
3.0 KiB
Go
package util
|
|
|
|
import (
|
|
"crypto/sha1" // #nosec G505 -- SHA1 used for visual identity hashing (jdenticon compatibility), not cryptographic security
|
|
"fmt"
|
|
"strconv"
|
|
)
|
|
|
|
// ComputeHash generates a SHA1 hash from the input string.
|
|
// This matches the hash generation used by the JavaScript jdenticon library.
|
|
// Note: SHA1 is used here for visual identity generation (deterministic icon creation),
|
|
// not for cryptographic security purposes.
|
|
func ComputeHash(input string) string {
|
|
hasher := sha1.New() // #nosec G401 -- SHA1 used for visual identity hashing, not cryptographic security
|
|
hasher.Write([]byte(input))
|
|
hash := hasher.Sum(nil)
|
|
return fmt.Sprintf("%x", hash)
|
|
}
|
|
|
|
// ParseHex parses a hexadecimal value from the hash string with smart byte/character detection
|
|
// This implementation is shared between engine and jdenticon packages for consistency
|
|
func ParseHex(hash string, startPosition, octets int) (int, error) {
|
|
// Handle negative indices (count from end like JavaScript)
|
|
if startPosition < 0 {
|
|
startPosition = len(hash) + startPosition
|
|
}
|
|
|
|
// Ensure we don't go out of bounds
|
|
if startPosition < 0 || startPosition >= len(hash) {
|
|
return 0, fmt.Errorf("jdenticon: hash: parsing failed: position out of bounds: position %d out of bounds for hash length %d", startPosition, len(hash))
|
|
}
|
|
|
|
// If octets is 0 or negative, read from startPosition to end (like JavaScript default)
|
|
end := len(hash)
|
|
if octets > 0 {
|
|
end = startPosition + octets
|
|
if end > len(hash) {
|
|
end = len(hash)
|
|
}
|
|
}
|
|
|
|
// Extract substring and parse as hexadecimal
|
|
substr := hash[startPosition:end]
|
|
if len(substr) == 0 {
|
|
return 0, fmt.Errorf("jdenticon: hash: parsing failed: empty substring: empty substring at position %d", startPosition)
|
|
}
|
|
|
|
result, err := strconv.ParseInt(substr, 16, 0)
|
|
if err != nil {
|
|
return 0, fmt.Errorf("jdenticon: hash: parsing failed: invalid hex format: failed to parse hex '%s' at position %d: %w", substr, startPosition, err)
|
|
}
|
|
|
|
return int(result), nil
|
|
}
|
|
|
|
// ValidateHash validates a hash string and returns detailed error information
|
|
func ValidateHash(hash string) error {
|
|
if len(hash) < 11 {
|
|
return fmt.Errorf("jdenticon: hash: validation failed: insufficient length: hash too short: %d characters (minimum 11 required)", len(hash))
|
|
}
|
|
|
|
// Check if all characters are valid hexadecimal
|
|
for i, r := range hash {
|
|
if !((r >= '0' && r <= '9') || (r >= 'a' && r <= 'f') || (r >= 'A' && r <= 'F')) {
|
|
return fmt.Errorf("jdenticon: hash: validation failed: invalid character: invalid hexadecimal character '%c' at position %d", r, i)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// IsValidHash checks if a hash string is valid for jdenticon generation
|
|
// This implementation is shared between engine and jdenticon packages for consistency
|
|
func IsValidHash(hash string) bool {
|
|
return ValidateHash(hash) == nil
|
|
}
|
|
|
|
// ContainsInt checks if an integer slice contains a specific value
|
|
func ContainsInt(slice []int, value int) bool {
|
|
for _, item := range slice {
|
|
if item == value {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|