auth

package
v0.0.0-...-e228ced Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 30, 2020 License: Apache-2.0 Imports: 11 Imported by: 2

README

Taask Core Security

Security is the top priority of Taask Core. It is built into the foundation, and every feature and design decision revolves around it. We believe that every layer of the software stack should be secure by default, and the Taask Core maintainers are committed to ensuring the security of the entire system.

  • ✅ Task and result data is opaque and encrypted in transit and at rest.
  • ✅ After task completion, the server loses its ability to decrypt the task or result data
  • ✅ Task and result data is never decrypted until it reaches the runner, only task keys are re-encrypted for runner access to task data

Taask authentication and encryption

A high-level overview

Please note that while this is the spec, it is not yet entirely implemented. Unimplemented portions are denoted with an asterix

Groups
  • Every client authenticates with a group. When a client submits a task, it belongs to the group it is authenticated with.
    • At startup there exists an admin group, whose keys are generated by the admin deploying Taask Core.
    • The admin group can create and delete additional groups, the admin group cannot be deleted. *
Auth (server)
  • Each group has a join code and a passphrase. The passphrase is never known by taask-server.
    • The join code is generated by the server, and the passphrase is generated or chosen by the user.
    • The groups passphrase is put through PBKDF2 to derive the group key.
    • The group key is used to encrypt the task key, described below.
    • The group join code and the group passphrase are combined and then hashed to create the group auth hash. This is known to the server.
Auth (client)
  • Client libraries at startup, generate a client keypair, used to authenticate with taask-server.
    • To authenticate, the client combines the group auth hash with a nonce (the current unix timestamp), and signs it with its client keypair.
    • This signature, along with the public portion of the signing key and some metadata, constitutes an auth attempt.
    • The attempt is sent to the server, where the signature is verified with the public key against the auth hash stored on the server.
    • The public half is stored on the server to verify later requests.
    • If the attempt is successful, a session challenge is generated (and stored) by the server, encrypted with the public key, and sent back to the client.
    • Clients include a signature (from the same keypair) of the session challenge with future requests to prove it has a valid session.
Task encryption (client)
  • When submitting a task, clients encrypt task data with a unique symmetric task key, and then encrypts the task key with the group key.
    • The group key encrypted task key is included in the task metadata such that a different client authenticated with the same group can decrypt the result.
  • The task key is also encrypted with the master runner public key. This encrypted key is also included in the task metadata.
    • The master runner public key is generated by the server at startup, and the private portion is only ever held in memory.
    • The server is able to decrypt the task key. This is important, but you will see that the concequences of this are mitigated by the handling of task results.
Task encryption (runner)
  • Every runner generates a runner keypair at startup, used to authenticate with taask-server and decrypt task data.
    • The authentication scheme for runners is identical to clients, except that runner connections are persistent and therefore each session is invalidated after the stream is terminated.
  • When a task is assigned to a runner, taask-server re-encrypts the task key using the runner's runner public key
    • The runner decrypts the task key and then uses it to decrypt the task data.
  • The task key is then used to encrypt the task result data, and the result is returned to the client.
    • Before the result is sent back to the server, the master runner encrypted copy of the task key is deleted, ensuring that the server can no longer decrypt the task data, and can never decrypt the result data. *

Documentation

Index

Constants

View Source
const (
	DefaultGroupUUID = "defaultgroupuuid"
	AdminGroupUUID   = "admingroupuuid"
	PartnerGroupUUID = "partnergroupuuid"
)

DefaultGroupUUID and others are consts for the internal (memory) auth manager

View Source
const (
	GroupKeyIterations = 100000
	GroupKeySaltString = "to there and back again" // TODO: store the salt with the group
)

GroupKeyIterations and others are the consts for member auth

Variables

This section is empty.

Functions

func GenerateJoinCode

func GenerateJoinCode() string

GenerateJoinCode generates a runner join code

func GroupAuthHash

func GroupAuthHash(joinCode, passphrase string) []byte

GroupAuthHash generates the auth hash from a Join Code and a passphrase

func GroupDerivedKey

func GroupDerivedKey(passphrase string) (*simplcrypto.SymKey, error)

GroupDerivedKey derives a symmetric key from a passphrase

Types

type Attempt

type Attempt struct {
	MemberUUID           string                          `protobuf:"bytes,1,opt,name=MemberUUID,proto3" json:"MemberUUID,omitempty"`
	GroupUUID            string                          `protobuf:"bytes,2,opt,name=GroupUUID,proto3" json:"GroupUUID,omitempty"`
	PubKey               *simplcrypto.SerializablePubKey `protobuf:"bytes,3,opt,name=PubKey,proto3" json:"PubKey,omitempty"`
	AuthHashSignature    *simplcrypto.Signature          `protobuf:"bytes,4,opt,name=AuthHashSignature,proto3" json:"AuthHashSignature,omitempty"`
	Timestamp            int64                           `protobuf:"varint,5,opt,name=Timestamp,proto3" json:"Timestamp,omitempty"`
	XXX_NoUnkeyedLiteral struct{}                        `json:"-"`
	XXX_unrecognized     []byte                          `json:"-"`
	XXX_sizecache        int32                           `json:"-"`
}

func (*Attempt) Descriptor

func (*Attempt) Descriptor() ([]byte, []int)

func (*Attempt) GetAuthHashSignature

func (m *Attempt) GetAuthHashSignature() *simplcrypto.Signature

func (*Attempt) GetGroupUUID

func (m *Attempt) GetGroupUUID() string

func (*Attempt) GetMemberUUID

func (m *Attempt) GetMemberUUID() string

func (*Attempt) GetPubKey

func (m *Attempt) GetPubKey() *simplcrypto.SerializablePubKey

func (*Attempt) GetTimestamp

func (m *Attempt) GetTimestamp() int64

func (*Attempt) ProtoMessage

func (*Attempt) ProtoMessage()

func (*Attempt) Reset

func (m *Attempt) Reset()

func (*Attempt) String

func (m *Attempt) String() string

func (*Attempt) XXX_DiscardUnknown

func (m *Attempt) XXX_DiscardUnknown()

func (*Attempt) XXX_Marshal

func (m *Attempt) XXX_Marshal(b []byte, deterministic bool) ([]byte, error)

func (*Attempt) XXX_Merge

func (m *Attempt) XXX_Merge(src proto.Message)

func (*Attempt) XXX_Size

func (m *Attempt) XXX_Size() int

func (*Attempt) XXX_Unmarshal

func (m *Attempt) XXX_Unmarshal(b []byte) error

type AttemptResponse

type AttemptResponse struct {
	EncChallenge         *simplcrypto.Message            `protobuf:"bytes,1,opt,name=EncChallenge,proto3" json:"EncChallenge,omitempty"`
	MasterPubKey         *simplcrypto.SerializablePubKey `protobuf:"bytes,2,opt,name=MasterPubKey,proto3" json:"MasterPubKey,omitempty"`
	XXX_NoUnkeyedLiteral struct{}                        `json:"-"`
	XXX_unrecognized     []byte                          `json:"-"`
	XXX_sizecache        int32                           `json:"-"`
}

func (*AttemptResponse) Descriptor

func (*AttemptResponse) Descriptor() ([]byte, []int)

func (*AttemptResponse) GetEncChallenge

func (m *AttemptResponse) GetEncChallenge() *simplcrypto.Message

func (*AttemptResponse) GetMasterPubKey

func (m *AttemptResponse) GetMasterPubKey() *simplcrypto.SerializablePubKey

func (*AttemptResponse) ProtoMessage

func (*AttemptResponse) ProtoMessage()

func (*AttemptResponse) Reset

func (m *AttemptResponse) Reset()

func (*AttemptResponse) String

func (m *AttemptResponse) String() string

func (*AttemptResponse) XXX_DiscardUnknown

func (m *AttemptResponse) XXX_DiscardUnknown()

func (*AttemptResponse) XXX_Marshal

func (m *AttemptResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error)

func (*AttemptResponse) XXX_Merge

func (m *AttemptResponse) XXX_Merge(src proto.Message)

func (*AttemptResponse) XXX_Size

func (m *AttemptResponse) XXX_Size() int

func (*AttemptResponse) XXX_Unmarshal

func (m *AttemptResponse) XXX_Unmarshal(b []byte) error

type EncMemberSession

type EncMemberSession struct {
	EncSessionChallenge *simplcrypto.Message
}

EncMemberSession is sent back to the member as an auth challenge

type InternalAuthManager

type InternalAuthManager struct {
	// contains filtered or unexported fields
}

InternalAuthManager manages the auth of members, with in-memory storage

func NewInternalAuthManager

func NewInternalAuthManager(keyservice keyservice.KeyService) (*InternalAuthManager, error)

NewInternalAuthManager returns a new InternalAuthManager

func (*InternalAuthManager) AddGroup

func (am *InternalAuthManager) AddGroup(group *MemberGroup) error

AddGroup adds a member group

func (*InternalAuthManager) AttemptAuth

func (am *InternalAuthManager) AttemptAuth(attempt *Attempt) (*EncMemberSession, error)

AttemptAuth checks the auth request for a member TODO: consider including the group UUID in the crypto meat grinder?

func (*InternalAuthManager) CheckAuth

func (am *InternalAuthManager) CheckAuth(session *Session) error

CheckAuth verifies a challenge signature is legit

func (*InternalAuthManager) CheckAuthEnsureAdmin

func (am *InternalAuthManager) CheckAuthEnsureAdmin(session *Session) error

CheckAuthEnsureAdmin checks the auth against the admin group

func (*InternalAuthManager) DeleteMemberAuth

func (am *InternalAuthManager) DeleteMemberAuth(memberUUID string) error

DeleteMemberAuth deletes a member's pubkey after it's been unregistered

func (*InternalAuthManager) EncryptForMember

func (am *InternalAuthManager) EncryptForMember(memberUUID string, msg []byte) (*simplcrypto.Message, error)

EncryptForMember allows messages to be encrypted for members

func (*InternalAuthManager) MemberPubkey

func (am *InternalAuthManager) MemberPubkey(uuid string) (*simplcrypto.KeyPair, error)

MemberPubkey returns the pubkey for an active member

func (*InternalAuthManager) VerifySignatureFromMember

func (am *InternalAuthManager) VerifySignatureFromMember(memberUUID string, msg []byte, sig *simplcrypto.Signature) error

VerifySignatureFromMember allows messages to be encrypted for members

type Manager

type Manager interface {
	AttemptAuth(attempt *Attempt) (*EncMemberSession, error)
	CheckAuth(session *Session) error
	CheckAuthEnsureAdmin(session *Session) error
	DeleteMemberAuth(uuid string) error
	AddGroup(group *MemberGroup) error
	MemberPubkey(uuid string) (*simplcrypto.KeyPair, error)
	EncryptForMember(memberUUID string, msg []byte) (*simplcrypto.Message, error)
	VerifySignatureFromMember(memberUUID string, msg []byte, sig *simplcrypto.Signature) error
}

Manager describes the interface for things that are able to manage auth

type MemberAuth

type MemberAuth struct {
	UUID             string
	GroupUUID        string
	SessionChallenge []byte
	PubKey           *simplcrypto.KeyPair
}

MemberAuth represents an existing member session

type MemberGroup

type MemberGroup struct {
	UUID                 string   `protobuf:"bytes,1,opt,name=UUID,proto3" json:"UUID,omitempty"`
	Name                 string   `protobuf:"bytes,2,opt,name=Name,proto3" json:"Name,omitempty"`
	JoinCode             string   `protobuf:"bytes,3,opt,name=JoinCode,proto3" json:"JoinCode,omitempty"`
	AuthHash             []byte   `protobuf:"bytes,4,opt,name=AuthHash,proto3" json:"AuthHash,omitempty"`
	XXX_NoUnkeyedLiteral struct{} `json:"-"`
	XXX_unrecognized     []byte   `json:"-"`
	XXX_sizecache        int32    `json:"-"`
}

func (*MemberGroup) Descriptor

func (*MemberGroup) Descriptor() ([]byte, []int)

func (*MemberGroup) GetAuthHash

func (m *MemberGroup) GetAuthHash() []byte

func (*MemberGroup) GetJoinCode

func (m *MemberGroup) GetJoinCode() string

func (*MemberGroup) GetName

func (m *MemberGroup) GetName() string

func (*MemberGroup) GetUUID

func (m *MemberGroup) GetUUID() string

func (*MemberGroup) ProtoMessage

func (*MemberGroup) ProtoMessage()

func (*MemberGroup) Reset

func (m *MemberGroup) Reset()

func (*MemberGroup) String

func (m *MemberGroup) String() string

func (*MemberGroup) XXX_DiscardUnknown

func (m *MemberGroup) XXX_DiscardUnknown()

func (*MemberGroup) XXX_Marshal

func (m *MemberGroup) XXX_Marshal(b []byte, deterministic bool) ([]byte, error)

func (*MemberGroup) XXX_Merge

func (m *MemberGroup) XXX_Merge(src proto.Message)

func (*MemberGroup) XXX_Size

func (m *MemberGroup) XXX_Size() int

func (*MemberGroup) XXX_Unmarshal

func (m *MemberGroup) XXX_Unmarshal(b []byte) error

type Session

type Session struct {
	MemberUUID           string                 `protobuf:"bytes,1,opt,name=MemberUUID,proto3" json:"MemberUUID,omitempty"`
	GroupUUID            string                 `protobuf:"bytes,2,opt,name=GroupUUID,proto3" json:"GroupUUID,omitempty"`
	SessionChallengeSig  *simplcrypto.Signature `protobuf:"bytes,3,opt,name=SessionChallengeSig,proto3" json:"SessionChallengeSig,omitempty"`
	XXX_NoUnkeyedLiteral struct{}               `json:"-"`
	XXX_unrecognized     []byte                 `json:"-"`
	XXX_sizecache        int32                  `json:"-"`
}

func (*Session) Descriptor

func (*Session) Descriptor() ([]byte, []int)

func (*Session) GetGroupUUID

func (m *Session) GetGroupUUID() string

func (*Session) GetMemberUUID

func (m *Session) GetMemberUUID() string

func (*Session) GetSessionChallengeSig

func (m *Session) GetSessionChallengeSig() *simplcrypto.Signature

func (*Session) ProtoMessage

func (*Session) ProtoMessage()

func (*Session) Reset

func (m *Session) Reset()

func (*Session) String

func (m *Session) String() string

func (*Session) XXX_DiscardUnknown

func (m *Session) XXX_DiscardUnknown()

func (*Session) XXX_Marshal

func (m *Session) XXX_Marshal(b []byte, deterministic bool) ([]byte, error)

func (*Session) XXX_Merge

func (m *Session) XXX_Merge(src proto.Message)

func (*Session) XXX_Size

func (m *Session) XXX_Size() int

func (*Session) XXX_Unmarshal

func (m *Session) XXX_Unmarshal(b []byte) error

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL