spark-server/internal/module/device/logic/fingerprint.go

69 lines
1.5 KiB
Go

package logic
import (
"crypto/sha256"
"encoding/binary"
"encoding/hex"
"fmt"
"strings"
deviceentity "spark-server/internal/module/device/entity"
)
// FingerprintInput is the physical identity for one login/register.
type FingerprintInput struct {
DeviceType deviceentity.DeviceType
IDFV string
AndroidID string
}
func fingerprintHash(in FingerprintInput) (string, error) {
if !in.DeviceType.Valid() {
return "", fmt.Errorf("device_type")
}
idfv := strings.TrimSpace(in.IDFV)
androidID := strings.TrimSpace(in.AndroidID)
var tail string
switch in.DeviceType {
case deviceentity.TypeIOS, deviceentity.TypeMacOS:
if idfv == "" {
return "", fmt.Errorf("idfv")
}
tail = idfv
case deviceentity.TypeAndroid, deviceentity.TypeHarmony:
if androidID == "" {
return "", fmt.Errorf("android_id")
}
tail = androidID
default:
switch {
case idfv != "":
tail = idfv
case androidID != "":
tail = androidID
default:
return "", fmt.Errorf("device_id")
}
}
payload := fmt.Sprintf("%d:%s", in.DeviceType, tail)
sum := sha256.Sum256([]byte(payload))
return hex.EncodeToString(sum[:]), nil
}
// DeviceIDFromFingerprint derives the stable business device id.
func DeviceIDFromFingerprint(in FingerprintInput) (uint64, string, error) {
hash, err := fingerprintHash(in)
if err != nil {
return 0, "", err
}
sum := sha256.Sum256([]byte(hash))
id := binary.BigEndian.Uint64(sum[:8])
if id == 0 {
id = binary.BigEndian.Uint64(sum[1:9])
}
if id == 0 {
id = 1
}
return id, hash, nil
}