package lafsession import ( "crypto/ed25519" "crypto/rand" "crypto/sha256" "encoding/hex" "fmt" ) type Identity struct { Private ed25519.PrivateKey Public ed25519.PublicKey } func GenerateIdentity() (*Identity, error) { pub, priv, err := ed25519.GenerateKey(rand.Reader) if err != nil { return nil, err } return &Identity{Private: priv, Public: pub}, nil } func IdentityFromSeed(seed []byte) (*Identity, error) { if len(seed) != ed25519.SeedSize { return nil, fmt.Errorf("lafsession: seed must be %d bytes", ed25519.SeedSize) } priv := ed25519.NewKeyFromSeed(seed) return &Identity{Private: priv, Public: priv.Public().(ed25519.PublicKey)}, nil } func (id *Identity) PublicBytes() []byte { return append([]byte(nil), id.Public...) } func (id *Identity) Fingerprint() string { sum := sha256.Sum256(id.Public) return hex.EncodeToString(sum[:]) } func (id *Identity) ShortFingerprint() string { sum := sha256.Sum256(id.Public) h := hex.EncodeToString(sum[:20]) out := make([]byte, 0, 24+5) for i := 0; i < len(h); i += 4 { if i > 0 { out = append(out, ' ') } end := i + 4 if end > len(h) { end = len(h) } out = append(out, h[i:end]...) } return string(out) } func (id *Identity) Sign(msg []byte) []byte { return ed25519.Sign(id.Private, msg) } func (id *Identity) Verify(msg, sig []byte) bool { return ed25519.Verify(id.Public, msg, sig) } func VerifyPeer(peerPub, msg, sig []byte) bool { if len(peerPub) != ed25519.PublicKeySize { return false } return ed25519.Verify(peerPub, msg, sig) } func FingerprintOf(pub []byte) string { sum := sha256.Sum256(pub) return hex.EncodeToString(sum[:]) }