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  }