33
This commit is contained in:
86
identity.go
Normal file
86
identity.go
Normal file
@@ -0,0 +1,86 @@
|
||||
package lafsession
|
||||
|
||||
import (
|
||||
"crypto/ed25519"
|
||||
"crypto/rand"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// Identity is a long-term Ed25519 key pair used for mutual authentication.
|
||||
type Identity struct {
|
||||
Private ed25519.PrivateKey
|
||||
Public ed25519.PublicKey
|
||||
}
|
||||
|
||||
// GenerateIdentity creates a new random identity key pair.
|
||||
func GenerateIdentity() (*Identity, error) {
|
||||
pub, priv, err := ed25519.GenerateKey(rand.Reader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Identity{Private: priv, Public: pub}, nil
|
||||
}
|
||||
|
||||
// IdentityFromSeed derives an identity from a 32-byte seed (deterministic).
|
||||
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
|
||||
}
|
||||
|
||||
// PublicBytes returns the 32-byte public key.
|
||||
func (id *Identity) PublicBytes() []byte {
|
||||
return append([]byte(nil), id.Public...)
|
||||
}
|
||||
|
||||
// Fingerprint returns a SHA-256 hex fingerprint of the public key (full 32 bytes hex).
|
||||
func (id *Identity) Fingerprint() string {
|
||||
sum := sha256.Sum256(id.Public)
|
||||
return hex.EncodeToString(sum[:])
|
||||
}
|
||||
|
||||
// ShortFingerprint returns the first 20 bytes of SHA-256 as spaced hex groups (display).
|
||||
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)
|
||||
}
|
||||
|
||||
// Sign signs a transcript with the identity private key.
|
||||
func (id *Identity) Sign(msg []byte) []byte {
|
||||
return ed25519.Sign(id.Private, msg)
|
||||
}
|
||||
|
||||
// Verify checks a signature under this identity public key.
|
||||
func (id *Identity) Verify(msg, sig []byte) bool {
|
||||
return ed25519.Verify(id.Public, msg, sig)
|
||||
}
|
||||
|
||||
// VerifyPeer checks a signature under an arbitrary peer public key.
|
||||
func VerifyPeer(peerPub, msg, sig []byte) bool {
|
||||
if len(peerPub) != ed25519.PublicKeySize {
|
||||
return false
|
||||
}
|
||||
return ed25519.Verify(ed25519.PublicKey(peerPub), msg, sig)
|
||||
}
|
||||
|
||||
// FingerprintOf returns SHA-256 hex of a raw public key.
|
||||
func FingerprintOf(pub []byte) string {
|
||||
sum := sha256.Sum256(pub)
|
||||
return hex.EncodeToString(sum[:])
|
||||
}
|
||||
Reference in New Issue
Block a user