github.com/code-to-go/safepool.lib@v0.0.0-20221205180519-ee25e63c226e/security/identity.go (about) 1 package security 2 3 import ( 4 "bytes" 5 "crypto/ed25519" 6 "crypto/rand" 7 "encoding/base64" 8 "encoding/json" 9 "time" 10 11 "github.com/code-to-go/safepool.lib/core" 12 13 "github.com/patrickmn/go-cache" 14 15 eciesgo "github.com/ecies/go/v2" 16 ) 17 18 const ( 19 Secp256k1 = "secp256k1" 20 Ed25519 = "ed25519" 21 ) 22 23 var knownIdentities = cache.New(time.Hour, 10*time.Hour) 24 25 type Key struct { 26 Public []byte `json:"pu"` 27 Private []byte `json:"pr,omitempty"` 28 } 29 30 type Identity struct { 31 Nick string `json:"n"` 32 Email string `json:"m"` 33 SignatureKey Key `json:"s"` 34 EncryptionKey Key `json:"e"` 35 } 36 37 func NewIdentity(nick string) (Identity, error) { 38 var identity Identity 39 40 identity.Nick = nick 41 privateCrypt, err := eciesgo.GenerateKey() 42 if core.IsErr(err, "cannot generate secp256k1 key: %v") { 43 return identity, err 44 } 45 identity.EncryptionKey = Key{ 46 Public: privateCrypt.PublicKey.Bytes(true), 47 Private: privateCrypt.Bytes(), 48 } 49 50 publicSign, privateSign, err := ed25519.GenerateKey(rand.Reader) 51 if core.IsErr(err, "cannot generate ed25519 key: %v") { 52 return identity, err 53 } 54 identity.SignatureKey = Key{ 55 Public: publicSign[:], 56 Private: privateSign[:], 57 } 58 return identity, nil 59 } 60 61 func (i Identity) Public() Identity { 62 return Identity{ 63 Nick: i.Nick, 64 Email: i.Email, 65 EncryptionKey: Key{ 66 Public: i.EncryptionKey.Public, 67 }, 68 SignatureKey: Key{ 69 Public: i.SignatureKey.Public, 70 }, 71 } 72 } 73 74 func IdentityFromBase64(b64 string) (Identity, error) { 75 var i Identity 76 data, err := base64.StdEncoding.DecodeString(b64) 77 if core.IsErr(err, "cannot decode Identity string in base64: %v") { 78 return i, err 79 } 80 81 err = json.Unmarshal(data, &i) 82 if core.IsErr(err, "cannot decode Identity string from json: %v") { 83 return i, err 84 } 85 return i, nil 86 } 87 88 func (i Identity) Base64() (string, error) { 89 data, err := json.Marshal(i) 90 if core.IsErr(err, "cannot marshal identity: %v") { 91 return "", err 92 } 93 94 return base64.StdEncoding.EncodeToString(data), nil 95 } 96 97 func (i Identity) Id() string { 98 return base64.StdEncoding.EncodeToString(i.SignatureKey.Public) 99 } 100 101 func SameIdentity(a, b Identity) bool { 102 return bytes.Equal(a.SignatureKey.Public, b.SignatureKey.Public) && 103 bytes.Equal(a.EncryptionKey.Public, b.EncryptionKey.Public) 104 } 105 106 func SetIdentity(i Identity) error { 107 k := string(append(i.SignatureKey.Public, i.EncryptionKey.Public...)) 108 if _, found := knownIdentities.Get(k); found { 109 return nil 110 } 111 return sqlSetIdentity(i) 112 } 113 114 func Trust(i Identity, trusted bool) error { 115 return sqlSetTrust(i, trusted) 116 }