121 lines
2.4 KiB
Go
121 lines
2.4 KiB
Go
package identity
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"encoding/base64"
|
|
"errors"
|
|
"fmt"
|
|
|
|
"somehole.com/common/security/signature"
|
|
)
|
|
|
|
const (
|
|
RetryCreateId = 3
|
|
)
|
|
|
|
type identity interface {
|
|
GetId() []byte
|
|
GetPublicKey() []byte
|
|
GetPublicKeySignature() []byte
|
|
}
|
|
|
|
type Id [8]byte
|
|
|
|
func (i Id) String() (out string) {
|
|
out = base64.StdEncoding.EncodeToString(i[:])
|
|
return
|
|
}
|
|
|
|
type Identity struct {
|
|
Id Id
|
|
PublicKey signature.PublicKey
|
|
PublicKeySignature signature.Signature
|
|
}
|
|
|
|
func NewIdentity(ident identity) (i Identity, err error) {
|
|
id := ident.GetId()
|
|
if len(id) != 8 {
|
|
err = errors.New("wrong size id")
|
|
return
|
|
}
|
|
pubKey := ident.GetPublicKey()
|
|
if len(pubKey) != 96 {
|
|
err = errors.New("wrong size public key")
|
|
return
|
|
}
|
|
pubKeySig := ident.GetPublicKeySignature()
|
|
if len(pubKeySig) != 48 {
|
|
err = errors.New("wrong size public key signature")
|
|
return
|
|
}
|
|
i = Identity{
|
|
Id: Id(id),
|
|
PublicKey: signature.PublicKey(pubKey),
|
|
PublicKeySignature: signature.Signature(pubKeySig),
|
|
}
|
|
return
|
|
}
|
|
|
|
func (i Identity) String() (out string) {
|
|
b := make([]byte, 0)
|
|
b = append(b, i.Id[:]...)
|
|
b = append(b, i.PublicKey[:]...)
|
|
b = append(b, i.PublicKeySignature[:]...)
|
|
out = base64.StdEncoding.EncodeToString(b)
|
|
return
|
|
}
|
|
|
|
func ParseIdentityString(in string) (i Identity, err error) {
|
|
var b []byte
|
|
b, err = base64.StdEncoding.DecodeString(in)
|
|
if err != nil {
|
|
return
|
|
}
|
|
if len(b) != 8+96+48 {
|
|
err = errors.New("wrong for size identity data in string")
|
|
return
|
|
}
|
|
i = Identity{
|
|
Id: Id(b[0:8]),
|
|
PublicKey: signature.PublicKey(b[8:104]),
|
|
PublicKeySignature: signature.Signature(b[104:152]),
|
|
}
|
|
return
|
|
}
|
|
|
|
type IdentityService struct {
|
|
identities map[Id]Identity
|
|
}
|
|
|
|
func NewIdentityService() (srv *IdentityService) {
|
|
srv = &IdentityService{
|
|
identities: make(map[Id]Identity),
|
|
}
|
|
return
|
|
}
|
|
|
|
func (srv *IdentityService) NewId() (id Id, err error) {
|
|
var idBytes = make([]byte, 8)
|
|
for i := 0; i < RetryCreateId; i++ {
|
|
rand.Read(idBytes)
|
|
if _, exists := srv.identities[id]; exists {
|
|
err = fmt.Errorf("could only creat colliding ids in %d tries", RetryCreateId)
|
|
continue
|
|
}
|
|
id = Id(idBytes)
|
|
err = nil
|
|
break
|
|
}
|
|
return
|
|
}
|
|
|
|
func (srv *IdentityService) AddIdentity(id Id, identity Identity) (err error) {
|
|
_, exists := srv.identities[id]
|
|
if exists {
|
|
err = fmt.Errorf("failed to add identity")
|
|
return
|
|
}
|
|
srv.identities[id] = identity
|
|
return
|
|
}
|