diff --git a/api/authenticatedChannel.go b/api/authenticatedChannel.go index 9d26304009a4be8bc55471edca3c66da1f9ef5ec..c37c49d0f0f1e5a938eb2c1557b6e80315042d53 100644 --- a/api/authenticatedChannel.go +++ b/api/authenticatedChannel.go @@ -114,7 +114,7 @@ func (c *Client) MakePrecannedContact(precannedID uint) contact.Contact { partnerPubKey := e2eGrp.ExpG(precanned.E2eDhPrivateKey, e2eGrp.NewInt(1)) return contact.Contact{ - ID: precanned.ID, + ID: precanned.ReceptionID, DhPubKey: partnerPubKey, OwnershipProof: nil, Facts: make([]fact.Fact, 0), diff --git a/api/client.go b/api/client.go index 776eec62d319c141c33ad949c7bf256eb58c01ab..c47a4eb5f7e495ca3a24c5c66264c80a1f74e86e 100644 --- a/api/client.go +++ b/api/client.go @@ -194,10 +194,10 @@ func Login(storageDir string, password []byte, parameters params.Network) (*Clie cryptoUser := u.GetCryptographicIdentity() //start comms - c.comms, err = client.NewClientComms(cryptoUser.GetUserID(), - rsa.CreatePublicKeyPem(cryptoUser.GetRSA().GetPublic()), - rsa.CreatePrivateKeyPem(cryptoUser.GetRSA()), - cryptoUser.GetSalt()) + c.comms, err = client.NewClientComms(cryptoUser.GetTransmissionID(), + rsa.CreatePublicKeyPem(cryptoUser.GetTransmissionRSA().GetPublic()), + rsa.CreatePrivateKeyPem(cryptoUser.GetTransmissionRSA()), + cryptoUser.GetTransmissionSalt()) if err != nil { return nil, errors.WithMessage(err, "failed to load client") } @@ -346,7 +346,7 @@ func (c *Client) GetHealth() interfaces.HealthTracker { return c.network.GetHealthTracker() } -// Returns the switchboard for Registration +// Returns the switchboard for Identity func (c *Client) GetSwitchboard() interfaces.Switchboard { jww.INFO.Printf("GetSwitchboard()") return c.switchboard diff --git a/api/permissioning.go b/api/permissioning.go index c9d018d89f1b94df03aefd20f9b6c4dfd6daebab..b4691291befcb12e7b28b06948980ecc76143c78 100644 --- a/api/permissioning.go +++ b/api/permissioning.go @@ -16,7 +16,8 @@ import ( func (c *Client) registerWithPermissioning() error { userData := c.storage.User() //get the users public key - pubKey := userData.GetCryptographicIdentity().GetRSA().GetPublic() + transmissionPubKey := userData.GetCryptographicIdentity().GetTransmissionRSA().GetPublic() + receptionPubKey := userData.GetCryptographicIdentity().GetReceptionRSA().GetPublic() //load the registration code regCode, err := c.storage.GetRegCode() @@ -26,14 +27,15 @@ func (c *Client) registerWithPermissioning() error { } //register with permissioning - regValidationSignature, err := c.permissioning.Register(pubKey, regCode) + transmissionRegValidationSignature, receptionRegValidationSignature, err := c.permissioning.Register(transmissionPubKey, receptionPubKey, regCode) if err != nil { return errors.WithMessage(err, "failed to register with "+ "permissioning") } //store the signature - userData.SetRegistrationValidationSignature(regValidationSignature) + userData.SetTransmissionRegistrationValidationSignature(transmissionRegValidationSignature) + userData.SetReceptionRegistrationValidationSignature(receptionRegValidationSignature) //update the registration status err = c.storage.ForwardRegistrationStatus(storage.PermissioningComplete) diff --git a/api/user.go b/api/user.go index 604aa796cf3f4cc4d4402b0fdbd5d75a03ab3a25..892d84c63c8fb0e29001774c6c645f351b3d00b8 100644 --- a/api/user.go +++ b/api/user.go @@ -26,12 +26,6 @@ const ( // createNewUser generates an identity for cMix func createNewUser(rng csprng.Source, cmix, e2e *cyclic.Group) user.User { - // RSA Keygen (4096 bit defaults) - rsaKey, err := rsa.GenerateKey(rng, rsa.DefaultRSABitLen) - if err != nil { - jww.FATAL.Panicf(err.Error()) - } - // CMIX Keygen // FIXME: Why 256 bits? -- this is spec but not explained, it has // to do with optimizing operations on one side and still preserves @@ -50,24 +44,51 @@ func createNewUser(rng csprng.Source, cmix, e2e *cyclic.Group) user.User { jww.FATAL.Panicf(err.Error()) } + // RSA Keygen (4096 bit defaults) + transmissionRsaKey, err := rsa.GenerateKey(rng, rsa.DefaultRSABitLen) + if err != nil { + jww.FATAL.Panicf(err.Error()) + } + receptionRsaKey, err := rsa.GenerateKey(rng, rsa.DefaultRSABitLen) + if err != nil { + jww.FATAL.Panicf(err.Error()) + } + // Salt, UID, etc gen - salt := make([]byte, SaltSize) - n, err := csprng.NewSystemRNG().Read(salt) + transmissionSalt := make([]byte, SaltSize) + n, err := csprng.NewSystemRNG().Read(transmissionSalt) if err != nil { jww.FATAL.Panicf(err.Error()) } if n != SaltSize { - jww.FATAL.Panicf("salt size too small: %d", n) + jww.FATAL.Panicf("transmissionSalt size too small: %d", n) } - userID, err := xx.NewID(rsaKey.GetPublic(), salt, id.User) + transmissionID, err := xx.NewID(transmissionRsaKey.GetPublic(), transmissionSalt, id.User) + if err != nil { + jww.FATAL.Panicf(err.Error()) + } + + // Salt, UID, etc gen + receptionSalt := make([]byte, SaltSize) + n, err = csprng.NewSystemRNG().Read(receptionSalt) + if err != nil { + jww.FATAL.Panicf(err.Error()) + } + if n != SaltSize { + jww.FATAL.Panicf("receptionSalt size too small: %d", n) + } + receptionID, err := xx.NewID(receptionRsaKey.GetPublic(), receptionSalt, id.User) if err != nil { jww.FATAL.Panicf(err.Error()) } return user.User{ - ID: userID.DeepCopy(), - Salt: salt, - RSA: rsaKey, + TransmissionID: transmissionID.DeepCopy(), + TransmissionSalt: transmissionSalt, + TransmissionRSA: transmissionRsaKey, + ReceptionID: receptionID.DeepCopy(), + ReceptionSalt: receptionSalt, + ReceptionRSA: receptionRsaKey, Precanned: false, CmixDhPrivateKey: cmix.NewIntFromBytes(cMixKeyBytes), E2eDhPrivateKey: e2e.NewIntFromBytes(e2eKeyBytes), @@ -101,12 +122,15 @@ func createPrecannedUser(precannedID uint, rng csprng.Source, cmix, e2e *cyclic. } return user.User{ - ID: userID.DeepCopy(), - Salt: salt, - Precanned: true, - E2eDhPrivateKey: e2e.NewIntFromBytes(e2eKeyBytes), + TransmissionID: &userID, + TransmissionSalt: salt, + ReceptionID: &userID, + ReceptionSalt: salt, + Precanned: true, + E2eDhPrivateKey: e2e.NewIntFromBytes(e2eKeyBytes), // NOTE: These are dummy/not used CmixDhPrivateKey: cmix.NewInt(1), - RSA: rsaKey, + TransmissionRSA: rsaKey, + ReceptionRSA: rsaKey, } } diff --git a/auth/request.go b/auth/request.go index 906aa953995afd3af8b24cc028fe7aaac7dec5e0..5ba9d412b60f9b4a7129fc967f963b9d297ffcc9 100644 --- a/auth/request.go +++ b/auth/request.go @@ -47,7 +47,7 @@ func RequestAuth(partner, me contact.Contact, message string, rng io.Reader, } // check that the request is being sent from the proper ID - if !me.ID.Cmp(storage.GetUser().ID) { + if !me.ID.Cmp(storage.GetUser().TransmissionID) { return errors.Errorf("Authenticated channel request " + "can only be sent from user's identity") } @@ -116,7 +116,7 @@ func RequestAuth(partner, me contact.Contact, message string, rng io.Reader, jww.INFO.Printf("RequestAuth THEIRPUBKEY: %v", partner.DhPubKey.Bytes()) /*encrypt payload*/ - requestFmt.SetID(storage.GetUser().ID) + requestFmt.SetID(storage.GetUser().TransmissionID) requestFmt.SetMsgPayload(msgPayloadBytes) ecrFmt.SetOwnership(ownership) ecrPayload, mac := cAuth.Encrypt(newPrivKey, partner.DhPubKey, diff --git a/bindings/ud.go b/bindings/ud.go index bae84a46f6b040a7a366cd51396f0c433278da0a..643066a2ad2417ab444698c63b717101454ea53c 100644 --- a/bindings/ud.go +++ b/bindings/ud.go @@ -44,7 +44,7 @@ func NewUserDiscovery(client *Client)(*UserDiscovery, error){ // network signatures are malformed or if the username is taken. Usernames // cannot be changed after registration at this time. Will fail if the user is // already registered. -// Registration does not go over cmix, it occurs over normal communications +// Identity does not go over cmix, it occurs over normal communications func (ud *UserDiscovery)Register(username string)error{ return ud.ud.Register(username) } diff --git a/bindings/user.go b/bindings/user.go index 56942464027782001a5d242f90818ef50e7a1f40..722fe6af8dd48a3c80ef102750a3110ec48ff54d 100644 --- a/bindings/user.go +++ b/bindings/user.go @@ -16,20 +16,36 @@ type User struct { u *user.User } -func (u *User) GetID() []byte { - return u.u.ID.Marshal() +func (u *User) GetTransmissionID() []byte { + return u.u.TransmissionID.Marshal() } -func (u *User) GetSalt() []byte { - return u.u.Salt +func (u *User) GetReceptionID() []byte { + return u.u.ReceptionID.Marshal() } -func (u *User) GetRSAPrivateKeyPem() []byte { - return rsa.CreatePrivateKeyPem(u.u.RSA) +func (u *User) GetTransmissionSalt() []byte { + return u.u.TransmissionSalt } -func (u *User) GetRSAPublicKeyPem() []byte { - return rsa.CreatePublicKeyPem(u.u.RSA.GetPublic()) +func (u *User) GetReceptionSalt() []byte { + return u.u.ReceptionSalt +} + +func (u *User) GetTransmissionRSAPrivateKeyPem() []byte { + return rsa.CreatePrivateKeyPem(u.u.TransmissionRSA) +} + +func (u *User) GetTransmissionRSAPublicKeyPem() []byte { + return rsa.CreatePublicKeyPem(u.u.TransmissionRSA.GetPublic()) +} + +func (u *User) GetReceptionRSAPrivateKeyPem() []byte { + return rsa.CreatePrivateKeyPem(u.u.ReceptionRSA) +} + +func (u *User) GetReceptionRSAPublicKeyPem() []byte { + return rsa.CreatePublicKeyPem(u.u.ReceptionRSA.GetPublic()) } func (u *User) IsPrecanned() bool { diff --git a/cmd/init.go b/cmd/init.go index 19bde0e0e71f990674eb69d49414d3dd4f605b1a..d5d3b91ae04cdc134ea76879eace806e3f765ff4 100644 --- a/cmd/init.go +++ b/cmd/init.go @@ -22,9 +22,9 @@ var initCmd = &cobra.Command{ Run: func(cmd *cobra.Command, args []string) { client := createClient() user := client.GetUser() - jww.INFO.Printf("User: %s", user.ID) + jww.INFO.Printf("User: %s", user.TransmissionID) writeContact(user.GetContact()) - fmt.Printf("%s\n", user.ID) + fmt.Printf("%s\n", user.TransmissionID) }, } diff --git a/cmd/root.go b/cmd/root.go index 216eac07878059ffb05e20b5f6d538036bc4b6e3..8cda85052b6764ef2d01960989bf34d5e626c5be 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -49,7 +49,7 @@ var rootCmd = &cobra.Command{ client := initClient() user := client.GetUser() - jww.INFO.Printf("User: %s", user.ID) + jww.INFO.Printf("User: %s", user.TransmissionID) writeContact(user.GetContact()) // Set up reception handler @@ -103,7 +103,7 @@ var rootCmd = &cobra.Command{ // Set it to myself if recipientID == nil { jww.INFO.Printf("sending message to self") - recipientID = user.ID + recipientID = user.ReceptionID recipientContact = user.GetContact() } @@ -565,7 +565,7 @@ func init() { viper.BindPFlag("log", rootCmd.PersistentFlags().Lookup("log")) rootCmd.Flags().StringP("regcode", "", "", - "Registration code (optional)") + "Identity code (optional)") viper.BindPFlag("regcode", rootCmd.Flags().Lookup("regcode")) rootCmd.Flags().StringP("message", "m", "", "Message to send") diff --git a/cmd/ud.go b/cmd/ud.go index be41ca41e050e25ec85b781de0562b2341b45fd2..c5c59666f7f44a5cc2ec622c2dafa42af96cafbe 100644 --- a/cmd/ud.go +++ b/cmd/ud.go @@ -34,7 +34,7 @@ var udCmd = &cobra.Command{ Run: func(cmd *cobra.Command, args []string) { client := initClient() user := client.GetUser() - jww.INFO.Printf("User: %s", user.ID) + jww.INFO.Printf("User: %s", user.TransmissionID) writeContact(user.GetContact()) // Set up reception handler diff --git a/globals/statusEvents.go b/globals/statusEvents.go index 9695871da46a8252d42bd838996b1bb7a30330c2..fdf8d6ff99f6ac0c5cbc155eebe1a9c645c0ab8f 100644 --- a/globals/statusEvents.go +++ b/globals/statusEvents.go @@ -7,9 +7,9 @@ package globals -//Registration +//Identity const REG_KEYGEN = 1 //Generating Cryptographic Keys -const REG_PRECAN = 2 //Doing a Precanned Registration (Not Secure) +const REG_PRECAN = 2 //Doing a Precanned Identity (Not Secure) const REG_UID_GEN = 3 //Generating User ID const REG_PERM = 4 //Validating User Identity With Permissioning Server const REG_NODE = 5 //Registering with Nodes diff --git a/interfaces/user/user.go b/interfaces/user/user.go index 0f59bf81bbf4ec509d62ff99e933403736eab784..1aaea8a31d67d0dd1facb50cbb7170a0055abf92 100644 --- a/interfaces/user/user.go +++ b/interfaces/user/user.go @@ -17,10 +17,13 @@ import ( type User struct { //General Identity - ID *id.ID - Salt []byte - RSA *rsa.PrivateKey - Precanned bool + TransmissionID *id.ID + TransmissionSalt []byte + TransmissionRSA *rsa.PrivateKey + ReceptionID *id.ID + ReceptionSalt []byte + ReceptionRSA *rsa.PrivateKey + Precanned bool //cmix Identity CmixDhPrivateKey *cyclic.Int @@ -33,7 +36,7 @@ type User struct { func (u User) GetContact() contact.Contact { return contact.Contact{ - ID: u.ID.DeepCopy(), + ID: u.ReceptionID.DeepCopy(), DhPubKey: u.E2eDhPublicKey, Facts: make([]fact.Fact, 0), } diff --git a/network/manager.go b/network/manager.go index fff66d50055f45ad80cbe27c9dd6b0542d7141bf..d10622db534a2050750235d79421e1f05410855f 100644 --- a/network/manager.go +++ b/network/manager.go @@ -77,7 +77,7 @@ func NewManager(session *storage.Session, switchboard *switchboard.Switchboard, Health: health.Init(instance, params.NetworkHealthTimeout), NodeRegistration: make(chan network.NodeGateway, params.RegNodesBufferLen), Instance: instance, - Uid: session.User().GetCryptographicIdentity().GetUserID(), + Uid: session.User().GetCryptographicIdentity().GetReceptionID(), } //create sub managers diff --git a/network/message/sendCmix.go b/network/message/sendCmix.go index 4addcb7e8998f00301d0c8d9800e6e92b6c37fd8..cdc25ed105c68c9ad0b553e5758098ca9d89f45a 100644 --- a/network/message/sendCmix.go +++ b/network/message/sendCmix.go @@ -142,7 +142,7 @@ func (m *Manager) SendCMIX(msg format.Message, param params.CMIX) (id.Round, err } // Signals to the node registration thread to register a node if keys are -// missing. Registration is triggered automatically when the node is first seen, +// missing. Identity is triggered automatically when the node is first seen, // so this should on trigger on rare events. func handleMissingNodeKeys(instance *network.Instance, newNodeChan chan network.NodeGateway, nodes []*id.ID) { diff --git a/network/message/sendUnsafe.go b/network/message/sendUnsafe.go index c313ef8c57f27c74bd5575c3e080da907d3a011d..8975309dc25b884b35b599c56f88ce53e9fadcea 100644 --- a/network/message/sendUnsafe.go +++ b/network/message/sendUnsafe.go @@ -52,7 +52,7 @@ func (m *Manager) SendUnsafe(msg message.Send, param params.Unsafe) ([]id.Round, msgCmix := format.NewMessage(m.Session.Cmix().GetGroup().GetP().ByteLen()) msgCmix.SetContents(p) msgCmix.SetRecipientID(msg.Recipient) - e2e.SetUnencrypted(msgCmix, m.Session.User().GetCryptographicIdentity().GetUserID()) + e2e.SetUnencrypted(msgCmix, m.Session.User().GetCryptographicIdentity().GetTransmissionID()) wg.Add(1) go func(i int) { var err error diff --git a/network/node/register.go b/network/node/register.go index b0a32b611a9948b2d5677080a036e2e925dc3e5b..00b6d4d469c9065e2737764738ccf412c960da30 100644 --- a/network/node/register.go +++ b/network/node/register.go @@ -55,7 +55,7 @@ func StartRegistration(instance *network.Instance, session *storage.Session, rng func registerNodes(session *storage.Session, rngGen *fastRNG.StreamGenerator, comms RegisterNodeCommsInterface, stop *stoppable.Single, c chan network.NodeGateway) { u := session.User() - regSignature := u.GetRegistrationValidationSignature() + regSignature := u.GetTransmissionRegistrationValidationSignature() uci := u.GetCryptographicIdentity() cmix := session.Cmix() @@ -104,7 +104,7 @@ func registerWithNode(comms RegisterNodeCommsInterface, ngw network.NodeGateway, var transmissionKey *cyclic.Int // TODO: should move this to a precanned user initialization if uci.IsPrecanned() { - userNum := int(uci.GetUserID().Bytes()[7]) + userNum := int(uci.GetTransmissionID().Bytes()[7]) h := sha256.New() h.Reset() h.Write([]byte(strconv.Itoa(int(4000 + userNum)))) @@ -126,8 +126,8 @@ func registerWithNode(comms RegisterNodeCommsInterface, ngw network.NodeGateway, // Confirm received nonce jww.INFO.Println("Register: Confirming received nonce") - err = confirmNonce(comms, uci.GetUserID().Bytes(), - nonce, uci.GetRSA(), gatewayID) + err = confirmNonce(comms, uci.GetTransmissionID().Bytes(), + nonce, uci.GetTransmissionRSA(), gatewayID) if err != nil { errMsg := fmt.Sprintf("Register: Unable to confirm nonce: %v", err) return errors.New(errMsg) @@ -154,7 +154,7 @@ func requestNonce(comms RegisterNodeCommsInterface, gwId *id.ID, regHash []byte, data := h.Sum(nil) // Sign DH pubkey - clientSig, err := rsa.Sign(rng, uci.GetRSA(), sha, data, opts) + clientSig, err := rsa.Sign(rng, uci.GetTransmissionRSA(), sha, data, opts) if err != nil { return nil, nil, err } @@ -169,8 +169,8 @@ func requestNonce(comms RegisterNodeCommsInterface, gwId *id.ID, regHash []byte, } nonceResponse, err := comms.SendRequestNonceMessage(host, &pb.NonceRequest{ - Salt: uci.GetSalt(), - ClientRSAPubKey: string(rsa.CreatePublicKeyPem(uci.GetRSA().GetPublic())), + Salt: uci.GetTransmissionSalt(), + ClientRSAPubKey: string(rsa.CreatePublicKeyPem(uci.GetTransmissionRSA().GetPublic())), ClientSignedByServer: &messages.RSASignature{ Signature: regHash, }, diff --git a/permissioning/register.go b/permissioning/register.go index 5d50680539098fe8eb140ed93af26477e9b2aa9d..1a64e54798560b270ab0d62267f7b2704a2c8ae1 100644 --- a/permissioning/register.go +++ b/permissioning/register.go @@ -14,8 +14,8 @@ import ( "gitlab.com/xx_network/crypto/signature/rsa" ) -func (perm *Permissioning) Register(publicKey *rsa.PublicKey, registrationCode string) ([]byte, error) { - return register(perm.comms, perm.host, publicKey, registrationCode) +func (perm *Permissioning) Register(transmissionPublicKey, receptionPublicKey *rsa.PublicKey, registrationCode string) ([]byte, []byte, error) { + return register(perm.comms, perm.host, transmissionPublicKey, receptionPublicKey, registrationCode) } // client.Comms should implement this interface @@ -26,20 +26,21 @@ type registrationMessageSender interface { //register registers the user with optional registration code // Returns an error if registration fails. func register(comms registrationMessageSender, host *connect.Host, - publicKey *rsa.PublicKey, registrationCode string) ([]byte, error) { + transmissionPublicKey, receptionPublicKey *rsa.PublicKey, registrationCode string) ([]byte, []byte, error) { response, err := comms. SendRegistrationMessage(host, &pb.UserRegistration{ - RegistrationCode: registrationCode, - ClientRSAPubKey: string(rsa.CreatePublicKeyPem(publicKey)), + RegistrationCode: registrationCode, + ClientRSAPubKey: string(rsa.CreatePublicKeyPem(transmissionPublicKey)), + ClientReceptionRSAPubKey: string(rsa.CreatePublicKeyPem(receptionPublicKey)), }) if err != nil { - err = errors.Wrap(err, "sendRegistrationMessage: Unable to contact Registration Server!") - return nil, err + err = errors.Wrap(err, "sendRegistrationMessage: Unable to contact Identity Server!") + return nil, nil, err } if response.Error != "" { - return nil, errors.Errorf("sendRegistrationMessage: error handling message: %s", response.Error) + return nil, nil, errors.Errorf("sendRegistrationMessage: error handling message: %s", response.Error) } - return response.ClientSignedByServer.Signature, nil + return response.ClientSignedByServer.Signature, response.ClientReceptionSignedByServer.Signature, nil } diff --git a/permissioning/register_test.go b/permissioning/register_test.go index 3f63afff2a290a393a699c969223c9a99d104684..52dcb46e948b42fdd54a8f45ca6e2f751bf8a85e 100644 --- a/permissioning/register_test.go +++ b/permissioning/register_test.go @@ -38,6 +38,10 @@ func (s *MockRegistrationSender) SendRegistrationMessage(host *connect.Host, mes Nonce: []byte("nonce"), Signature: []byte("sig"), }, + ClientReceptionSignedByServer: &messages.RSASignature{ + Nonce: []byte("receptionnonce"), + Signature: []byte("receptionsig"), + }, Error: s.errInReply, }, s.errSendRegistration } @@ -64,13 +68,16 @@ func TestRegisterWithPermissioning(t *testing.T) { } regCode := "flooble doodle" - sig, err := register(&sender, sender.getHost, key.GetPublic(), regCode) + sig1, sig2, err := register(&sender, sender.getHost, key.GetPublic(), key.GetPublic(), regCode) if err != nil { t.Error(err) } - if string(sig) != "sig" { + if string(sig1) != "sig" { t.Error("expected signature to be 'sig'") } + if string(sig2) != "receptionsig" { + t.Error("expected signature to be 'receptionsig'") + } if sender.host.String() != sender.getHost.String() { t.Errorf("hosts differed. expected %v, got %v", sender.host, sender.getHost) } @@ -98,7 +105,7 @@ func TestRegisterWithPermissioning_ResponseErr(t *testing.T) { var sender MockRegistrationSender sender.succeedGetHost = true sender.errInReply = "failure occurred on permissioning" - _, err = register(&sender, nil, key.GetPublic(), "") + _, _, err = register(&sender, nil, key.GetPublic(), key.GetPublic(), "") if err == nil { t.Error("no error if registration fails on permissioning") } @@ -115,7 +122,7 @@ func TestRegisterWithPermissioning_ConnectionErr(t *testing.T) { var sender MockRegistrationSender sender.succeedGetHost = true sender.errSendRegistration = errors.New("connection problem") - _, err = register(&sender, nil, key.GetPublic(), "") + _, _, err = register(&sender, nil, key.GetPublic(), key.GetPublic(), "") if err == nil { t.Error("no error if e.g. context deadline exceeded") } diff --git a/storage/ephemeral/store.go b/storage/ephemeral/store.go new file mode 100644 index 0000000000000000000000000000000000000000..8cbbfc7b827de361a6761db4fd241f8827b5a2e5 --- /dev/null +++ b/storage/ephemeral/store.go @@ -0,0 +1,138 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright © 2021 xx network SEZC // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file // +/////////////////////////////////////////////////////////////////////////////// +package ephemeral + +import ( + "github.com/pkg/errors" + jww "github.com/spf13/jwalterweatherman" + "gitlab.com/elixxir/client/storage/versioned" + "sync" + "time" +) + +const ( + storePrefix = "ephemeralTimestamp" + ephemeralVersion = 0 + timestampKey = "timestampKeyStore" +) + +type Store struct { + kv *versioned.KV + // Timestamp of last check for ephemeral Ids + timestamp time.Time + mux sync.RWMutex +} + +// NewStore creates a new store. +func NewStore(kv *versioned.KV) (*Store, error) { + kv = kv.Prefix(storePrefix) + s := &Store{ + kv: kv, + timestamp: time.Time{}, + } + + return s, s.save() +} + +// loads the ephemeral storage object +func LoadStore(kv *versioned.KV) (*Store, error) { + kv = kv.Prefix(storePrefix) + s := &Store{ + timestamp: time.Time{}, + kv: kv, + } + + obj, err := kv.Get(timestampKey) + if err != nil { + return nil, err + } + + if err = s.unmarshal(obj.Data); err != nil { + return nil, err + } + + return s, nil +} + +// Returns the stored timestamp. If a timestamp is empty, we check disk. +// If the disk's timestamp is empty. we return an error. +// Otherwise, we return the valid timestamp found +func (s *Store) GetTimestamp() (time.Time, error) { + s.mux.RLock() + defer s.mux.RUnlock() + + ts := s.timestamp + + // Check that t + if ts.Equal(time.Time{}) { + obj, err := s.kv.Get(timestampKey) + if err != nil { + return time.Time{}, err + } + + ts = time.Time{} + if err := ts.UnmarshalBinary(obj.Data); err != nil { + return time.Time{}, err + } + + // If still an empty time object, then no timestamp exists + if ts.Equal(time.Time{}) { + return time.Time{}, errors.Errorf("No timestamp has been found") + } + } + + return ts, nil +} + +// Updates the stored time stamp with the time passed in +func (s *Store) UpdateTimestamp(ts time.Time) error { + s.mux.Lock() + defer s.mux.Unlock() + + + s.timestamp = ts + + if err := s.save(); err != nil { + jww.FATAL.Panicf("Failed to update timestamp of last check for ephemeral IDs") + } + + return nil +} + +// stores the ephemeral store +func (s *Store) save() error { + + data, err := s.marshal() + if err != nil { + return err + } + + obj := versioned.Object{ + Version: ephemeralVersion, + Timestamp: time.Now(), + Data: data, + } + + return s.kv.Set(timestampKey, &obj) +} + +// builds a byte representation of the store +func (s *Store) marshal() ([]byte, error) { + return s.timestamp.MarshalBinary() +} + +// restores the data for a store from the byte representation of the store +func (s *Store) unmarshal(b []byte) error { + ts := time.Time{} + if err := ts.UnmarshalBinary(b); err != nil { + return err + } + + s.timestamp = ts + + return nil +} diff --git a/storage/ephemeral/store_test.go b/storage/ephemeral/store_test.go new file mode 100644 index 0000000000000000000000000000000000000000..5ee0fb85bfc360fe2692a94f25606db8b0a31a47 --- /dev/null +++ b/storage/ephemeral/store_test.go @@ -0,0 +1,9 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright © 2021 xx network SEZC // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file // +/////////////////////////////////////////////////////////////////////////////// +package ephemeral + + diff --git a/storage/reception/IdentityUse.go b/storage/reception/IdentityUse.go new file mode 100644 index 0000000000000000000000000000000000000000..5a96aef576898cf072ad0bf3af612e833e820392 --- /dev/null +++ b/storage/reception/IdentityUse.go @@ -0,0 +1,63 @@ +package reception + +import ( + "github.com/pkg/errors" + "gitlab.com/elixxir/crypto/hash" + "gitlab.com/elixxir/primitives/knownRounds" + "gitlab.com/xx_network/crypto/randomness" + "gitlab.com/xx_network/primitives/id" + "io" + "math/big" + "time" +) + +type IdentityUse struct{ + Identity + + //randomly generated time to poll between + StartRequest time.Time //timestamp to request the start of bloom filters + EndRequest time.Time //timestamp to request the End of bloom filters + + // denotes if the identity is fake, in which case we do not process + // messages + Fake bool + + //rounds data + KR KnownRounds +} + +func (iu IdentityUse)SetSamplingPeriod(rng io.Reader)(IdentityUse, error){ + + //generate the seed + seed := make([]byte,32) + if _, err := rng.Read(seed);err!=nil{ + return IdentityUse{}, errors.WithMessage(err, "Failed to " + + "choose id due to rng failure") + } + + h, err := hash.NewCMixHash() + if err==nil{ + return IdentityUse{}, err + } + + //calculate the period offset + periodOffset := + randomness.RandInInterval(big.NewInt(iu.RequestMask.Nanoseconds()), + seed,h).Uint64() + iu.StartRequest = iu.StartValid.Add(-time.Duration(periodOffset)* + time.Nanosecond) + iu.EndRequest = iu.EndValid.Add(iu.RequestMask - + time.Duration(periodOffset)*time.Nanosecond) + return iu, nil +} + +type KnownRounds interface{ + Checked(rid id.Round) bool + Check(rid id.Round) + Forward(rid id.Round) + RangeUnchecked(newestRid id.Round, roundCheck func(id id.Round) bool) + RangeUncheckedMasked(mask *knownRounds.KnownRounds, + roundCheck knownRounds.RoundCheckFunc, maxChecked int) + RangeUncheckedMaskedRange(mask *knownRounds.KnownRounds, + roundCheck knownRounds.RoundCheckFunc, start, end id.Round, maxChecked int) +} \ No newline at end of file diff --git a/storage/reception/fake.go b/storage/reception/fake.go new file mode 100644 index 0000000000000000000000000000000000000000..bc72c6157b119ebe9c32626c065447c3985fd7d4 --- /dev/null +++ b/storage/reception/fake.go @@ -0,0 +1,43 @@ +package reception + +import ( + "github.com/pkg/errors" + "gitlab.com/xx_network/primitives/id" + "gitlab.com/xx_network/primitives/id/ephemeral" + "io" + "time" +) + +func generateFakeIdentity(rng io.Reader, idSize uint)(IdentityUse, error){ + randIDbytes := make([]byte, id.ArrIDLen-1) + if _, err := rng.Read(randIDbytes); err!=nil{ + return IdentityUse{}, errors.WithMessage(err, "failed to " + + "generate a random identity when none is available") + } + + randID := &id.ID{} + copy(randID[:id.ArrIDLen-1], randIDbytes) + randID.SetType(id.User) + + ephID, start, end, err := ephemeral.GetId(randID, idSize, + time.Now().UnixNano()) + if err!=nil{ + return IdentityUse{}, errors.WithMessage(err, "failed to " + + "generate an ephemral ID for random identity when none is " + + "available") + } + + return IdentityUse{ + Identity: Identity{ + EphId: ephID, + Source: randID, + End: end, + ExtraChecks: 0, + StartValid: start, + EndValid: end, + RequestMask: 24 * time.Hour, + Ephemeral: true, + }, + Fake: true, + }, nil +} diff --git a/storage/reception/identity.go b/storage/reception/identity.go new file mode 100644 index 0000000000000000000000000000000000000000..7ec0a33a33dfe91dd1b3bd17c1e532a71c5e16e6 --- /dev/null +++ b/storage/reception/identity.go @@ -0,0 +1,85 @@ +package reception + +import ( + "encoding/json" + "github.com/pkg/errors" + "gitlab.com/elixxir/client/storage/versioned" + "gitlab.com/xx_network/primitives/id" + "gitlab.com/xx_network/primitives/id/ephemeral" + "time" +) + +const identityStorageKey = "IdentityStorage" +const identityStorageVersion = 0 + +type Identity struct{ + //identity + EphId ephemeral.Id + Source *id.ID + + //usage variables + End time.Time // timestamp when active polling will stop + ExtraChecks uint // number of extra checks executed as active + // after the id exits active + + //polling parameters + StartValid time.Time // timestamp when the ephID begins being valid + EndValid time.Time // timestamp when the ephID stops being valid + RequestMask time.Duration // amount of extra time requested for the poll + // in order to mask the exact valid time for + // the id + + //makes the identity not store on disk + Ephemeral bool +} + +func loadIdentity(kv *versioned.KV)(Identity, error){ + obj, err := kv.Get(identityStorageKey) + if err!=nil{ + return Identity{}, errors.WithMessage(err, "Failed to load Identity") + } + + r := Identity{} + err = json.Unmarshal(obj.Data, &r) + if err!=nil{ + return Identity{}, errors.WithMessage(err, "Failed to unmarshal Identity") + } + return r, nil +} + + +func (i Identity)store(kv *versioned.KV)error{ + //marshal the registration + regStr, err := json.Marshal(&i) + if err!=nil{ + return errors.WithMessage(err, "Failed to marshal Identity") + } + + // Create versioned object with data + obj := &versioned.Object{ + Version: identityStorageVersion, + Timestamp: time.Now(), + Data: regStr, + } + + //store the data + err = kv.Set(identityStorageKey, obj) + if err!=nil{ + return errors.WithMessage(err, "Failed to store Identity") + } + + return nil +} + +func (i Identity)delete(kv *versioned.KV)error{ + return kv.Delete(identityStorageKey) +} + +func (i Identity)calculateKrSize()int{ + return int(i.EndValid.Sub(i.StartValid).Seconds()+1)*maxRoundsPerSecond +} + +func (i *Identity)String()string{ + return string(i.EphId.Int64()) + " " + i.String() +} + diff --git a/storage/reception/identity_test.go b/storage/reception/identity_test.go new file mode 100644 index 0000000000000000000000000000000000000000..2117f731f24b3a1ca5059879df871b094933820d --- /dev/null +++ b/storage/reception/identity_test.go @@ -0,0 +1,68 @@ +package reception + +import ( + "gitlab.com/elixxir/client/storage/versioned" + "gitlab.com/elixxir/ekv" + "gitlab.com/xx_network/primitives/id" + "gitlab.com/xx_network/primitives/id/ephemeral" + "reflect" + "testing" + "time" +) + +func TestIdentityEncodeDecode(t *testing.T) { + + kv := versioned.NewKV(make(ekv.Memstore)) + r := Identity{ + EphId: ephemeral.Id{}, + Source: &id.Permissioning, + End: time.Now().Round(0), + ExtraChecks: 12, + StartValid: time.Now().Round(0), + EndValid: time.Now().Round(0), + RequestMask: 2*time.Hour, + Ephemeral: false, + } + err := r.store(kv) + if err!=nil{ + t.Errorf("Failed to store: %s", err) + } + + rLoad, err := loadIdentity(kv) + if err!=nil{ + t.Errorf("Failed to load: %s", err) + } + + if !reflect.DeepEqual(r, rLoad){ + t.Errorf("The two registrations are not the same\n saved: %+v\n loaded: %+v", r, rLoad) + } +} + +func TestIdentityDelete(t *testing.T) { + + kv := versioned.NewKV(make(ekv.Memstore)) + r := Identity{ + EphId: ephemeral.Id{}, + Source: &id.Permissioning, + End: time.Now().Round(0), + ExtraChecks: 12, + StartValid: time.Now().Round(0), + EndValid: time.Now().Round(0), + RequestMask: 2 * time.Hour, + Ephemeral: false, + } + err := r.store(kv) + if err != nil { + t.Errorf("Failed to store: %s", err) + } + + err = r.delete(kv) + if err != nil { + t.Errorf("Failed to delete: %s", err) + } + + _, err = loadIdentity(kv) + if err == nil { + t.Errorf("Load after delete succeded") + } +} diff --git a/storage/reception/registration.go b/storage/reception/registration.go new file mode 100644 index 0000000000000000000000000000000000000000..f010b46b05e0d61b7baf929f97f613412b904b53 --- /dev/null +++ b/storage/reception/registration.go @@ -0,0 +1,115 @@ +package reception + +import ( + "github.com/pkg/errors" + "gitlab.com/elixxir/client/storage/utility" + "gitlab.com/elixxir/client/storage/versioned" + "gitlab.com/elixxir/primitives/knownRounds" + "gitlab.com/xx_network/primitives/id" + "gitlab.com/xx_network/primitives/id/ephemeral" + "time" + +) + +const maxRoundsPerSecond = 100 +const knownRoundsStorageKey = "krStorage" + + +type registration struct{ + Identity + knownRounds *knownRounds.KnownRounds + knownRoundsStorage *utility.KnownRounds + kv *versioned.KV +} + +func newRegistration(reg Identity, kv *versioned.KV)(*registration, error){ + //round the times to remove the monotic clocks for future saving + reg.StartValid = reg.StartValid.Round(0) + reg.EndValid = reg.EndValid.Round(0) + reg.End = reg.End.Round(0) + + now := time.Now() + + //do edge checks to determine if the identity is valid + if now.After(reg.End) && reg.ExtraChecks<1{ + return nil, errors.New("Cannot create a registration for an " + + "identity which has expired") + } + + //set the prefix + kv = kv.Prefix(regPrefix(reg.EphId, reg.Source)) + + + r := ®istration{ + Identity: reg, + knownRounds: knownRounds.NewKnownRound(reg.calculateKrSize()), + kv: kv, + } + + //if this isn't ephemeral, store everything + if !reg.Ephemeral{ + //store known rounds + var err error + r.knownRoundsStorage, err = utility.NewKnownRounds(kv, knownRoundsStorageKey, r.knownRounds) + if err!=nil{ + return nil, errors.WithMessage(err, "failed to store known rounds") + } + //store the registration + if err = reg.store(kv); err!=nil{ + return nil, errors.WithMessage(err, "failed to store registration") + } + } + + return r, nil +} + +func loadRegistration(EphId ephemeral.Id, Source *id.ID, kv *versioned.KV)(*registration, error){ + kv = kv.Prefix(regPrefix(EphId, Source)) + + reg, err := loadIdentity(kv) + if err!=nil{ + return nil, errors.WithMessagef(err, "Failed to load identity " + + "for %s", regPrefix(EphId, Source)) + } + + kr, err := utility.LoadKnownRounds(kv,knownRoundsStorageKey, reg.calculateKrSize()) + if err!=nil{ + return nil, errors.WithMessagef(err, "Failed to load known " + + "rounds for %s", regPrefix(EphId, Source)) + } + + r := ®istration{ + Identity: reg, + knownRoundsStorage: kr, + kv: kv, + } + + return r, nil +} + + +func (r *registration)Delete()error{ + if !r.Ephemeral{ + if err:=r.knownRoundsStorage.Delete(); err!=nil{ + return errors.WithMessagef(err, "Failed to delete " + + "registration known rounds %s", r) + } + if err:=r.delete(r.kv); err!=nil{ + return errors.WithMessagef(err, "Failed to delete " + + "registration public data %s", r) + } + } + return nil +} + +func (r registration)getKR()KnownRounds{ + if r.Ephemeral{ + return r.knownRounds + }else{ + return r.knownRoundsStorage + } +} + +func regPrefix(EphId ephemeral.Id, Source *id.ID)string{ + return "receptionRegistration_" + string(EphId.Int64()) + Source.String() +} \ No newline at end of file diff --git a/storage/reception/store.go b/storage/reception/store.go new file mode 100644 index 0000000000000000000000000000000000000000..36353924eb21c2dbd5a3e4797a40596a11494d25 --- /dev/null +++ b/storage/reception/store.go @@ -0,0 +1,303 @@ +package reception + +import ( + "bytes" + "encoding/json" + "github.com/pkg/errors" + jww "github.com/spf13/jwalterweatherman" + "gitlab.com/elixxir/client/storage/versioned" + "gitlab.com/elixxir/crypto/hash" + "gitlab.com/xx_network/crypto/randomness" + "gitlab.com/xx_network/primitives/id" + "gitlab.com/xx_network/primitives/id/ephemeral" + "io" + "math/big" + "strconv" + "sync" + "time" +) + +const receptionPrefix = "reception" +const receptionStoreStorageKey = "receptionStoreKey" +const receptionStoreStorageVersion = 0 +const receptionIDSizeStorageKey = "receptionIDSizeKey" +const receptionIDSizeStorageVersion = 0 +const defaultIDSize = 12 + +type Store struct{ + // identities which are being actively checked + active []*registration + idSize int + + kv *versioned.KV + + mux sync.Mutex +} + +type storedReference struct { + Eph ephemeral.Id + Source *id.ID +} + +//creates a new reception store. It starts empty +func NewStore(kv *versioned.KV)*Store{ + kv = kv.Prefix(receptionPrefix) + s := &Store{ + active: make([]*registration, 0), + idSize: defaultIDSize, + kv: kv, + } + + //store the empty list + if err := s.save(); err!=nil{ + jww.FATAL.Panicf("Failed to save new reception store: %+v", err) + } + + //update the size so queries can be made + s.UpdateIDSize(defaultIDSize) + + return s +} + +func LoadStore(kv *versioned.KV)*Store{ + kv = kv.Prefix(receptionPrefix) + s := &Store{ + kv: kv, + } + + // Load the versioned object for the reception list + vo, err := kv.Get(receptionStoreStorageKey) + if err != nil { + jww.FATAL.Panicf("Failed to get the reception storage list: %+v", + err) + } + + identities := make([]storedReference, len(s.active)) + err = json.Unmarshal(vo.Data, &identities) + if err!=nil{ + jww.FATAL.Panicf("Failed to unmarshal the reception storage " + + "list: %+v", err) + } + + s.active = make([]*registration, len(identities)) + for i, sr := range identities{ + s.active[i], err = loadRegistration(sr.Eph, sr.Source, s.kv) + if err!=nil{ + jww.FATAL.Panicf("Failed to load registration for %s: %+v", + regPrefix(sr.Eph, sr.Source), err) + } + } + + //load the ephmemeral ID length + vo, err = kv.Get(receptionIDSizeStorageKey) + if err != nil { + jww.FATAL.Panicf("Failed to get the reception id size: %+v", + err) + } + + if s.idSize, err = strconv.Atoi(string(vo.Data)); err!=nil{ + jww.FATAL.Panicf("Failed to unmarshal the reception id size: %+v", + err) + } + + return s +} + +func (s *Store) save()error{ + identities := make([]storedReference, len(s.active)) + i := 0 + for _, reg := range s.active{ + if !reg.Ephemeral{ + identities[i] = storedReference{ + Eph: reg.EphId, + Source: reg.Source, + } + i++ + } + } + identities = identities[:i] + + data, err := json.Marshal(&identities) + if err!=nil{ + return errors.WithMessage(err, "failed to store reception " + + "store") + } + + // Create versioned object with data + obj := &versioned.Object{ + Version: receptionStoreStorageVersion, + Timestamp: time.Now(), + Data: data, + } + + err = s.kv.Set(receptionStoreStorageKey, obj) + if err!=nil{ + return errors.WithMessage(err, "Failed to store reception store") + } + + return nil +} + +func (s *Store)GetIdentity(rng io.Reader)(IdentityUse, error){ + s.mux.Lock() + defer s.mux.Unlock() + + now := time.Now() + + //remove any now expired identities + s.prune(now) + + var identity IdentityUse + var err error + + // if the list is empty, we return a randomly generated identity to poll + // with so we can continue tracking the network and to further obfuscate + // network identities + if len(s.active)==0{ + identity, err = generateFakeIdentity(rng, uint(s.idSize)) + if err!=nil{ + jww.FATAL.Panicf("Failed to generate a new ID when none " + + "available: %+v", err) + } + }else{ + identity, err = s.selectIdentity(rng, now) + if err!=nil{ + jww.FATAL.Panicf("Failed to select an id: %+v", err) + } + } + + //calculate the sampling period + identity, err = identity.SetSamplingPeriod(rng) + if err!=nil{ + jww.FATAL.Panicf("Failed to caluclate the sampling period: " + + "%+v", err) + } + + return identity, nil +} + +func (s *Store)AddIdentity(identity Identity)error { + s.mux.Lock() + defer s.mux.Unlock() + + reg, err := newRegistration(identity, s.kv) + if err!=nil{ + return errors.WithMessage(err,"failed to add new identity to " + + "reception store") + } + + s.active = append(s.active, reg) + if !identity.Ephemeral{ + if err := s.save(); err!=nil{ + jww.FATAL.Panicf("Failed to save reception store after identity " + + "addition") + } + } + + return nil +} + +func (s *Store)RemoveIdentity(ephID ephemeral.Id)bool { + s.mux.Lock() + defer s.mux.Unlock() + + for i:=0;i<len(s.active);i++{ + inQuestion := s.active[i] + if bytes.Equal(inQuestion.EphId[:],ephID[:]){ + s.active = append(s.active[:i], s.active[i+1:]...) + err := inQuestion.Delete() + if err!=nil{ + jww.FATAL.Panicf("Failed to delete identity %s") + } + if !inQuestion.Ephemeral{ + if err := s.save(); err!=nil{ + jww.FATAL.Panicf("Failed to save reception store after " + + "identity removal") + } + } + + return true + } + } + + return false +} + +func (s *Store)UpdateIDSize(idSize uint){ + s.mux.Lock() + defer s.mux.Unlock() + s.idSize = int(idSize) + //store the id size + obj := &versioned.Object{ + Version: receptionIDSizeStorageVersion, + Timestamp: time.Now(), + Data: []byte(strconv.Itoa(s.idSize)), + } + + err := s.kv.Set(receptionIDSizeStorageKey, obj) + if err!=nil{ + jww.FATAL.Panicf("Failed to store reception ID size: %+v", err) + } +} + +func (s *Store)prune(now time.Time) { + lengthBefore := len(s.active) + + //prune the list + for i:=0;i<len(s.active);i++{ + inQuestion := s.active[i] + if now.After(inQuestion.End) && inQuestion.ExtraChecks ==0{ + if err := inQuestion.Delete(); err!=nil{ + jww.ERROR.Printf("Failed to delete Identity for %s: " + + "%+v", inQuestion, err) + } + + s.active = append(s.active[:i-1], s.active[i:]...) + + i-- + } + } + + //save the list if it changed + if lengthBefore!=len(s.active){ + if err := s.save(); err!=nil{ + jww.FATAL.Panicf("Failed to store reception storage") + } + } +} + +func (s *Store)selectIdentity(rng io.Reader, now time.Time)(IdentityUse, error) { + + //choose a member from the list + var selected *registration + + if len(s.active)==1{ + selected= s.active[0] + }else{ + + seed := make([]byte,32) + if _, err := rng.Read(seed);err!=nil{ + return IdentityUse{}, errors.WithMessage(err, "Failed to " + + "choose id due to rng failure") + } + + h, err := hash.NewCMixHash() + if err==nil{ + return IdentityUse{}, err + } + + selectedNum := randomness.RandInInterval( + big.NewInt(int64(len(s.active)-1)),seed,h) + selected = s.active[selectedNum.Uint64()] + } + + if now.After(selected.End){ + selected.ExtraChecks-- + } + + return IdentityUse{ + Identity: selected.Identity, + Fake: false, + KR: selected.getKR(), + }, nil +} \ No newline at end of file diff --git a/storage/regStatus.go b/storage/regStatus.go index 52f74dd10bf98631892237b1820ba31b105c8ecd..ec18a0cfcb92aaa9c154f23528a40a96f202273f 100644 --- a/storage/regStatus.go +++ b/storage/regStatus.go @@ -27,7 +27,7 @@ const ( UDBComplete RegistrationStatus = 30000 // Set upon completion of RegisterWithUdb ) -// stringer for Registration Status +// stringer for Identity Status func (rs RegistrationStatus) String() string { switch rs { case NotStarted: @@ -35,9 +35,9 @@ func (rs RegistrationStatus) String() string { case KeyGenComplete: return "Key Generation Complete" case PermissioningComplete: - return "Permissioning Registration Complete" + return "Permissioning Identity Complete" case UDBComplete: - return "User Discovery Registration Complete" + return "User Discovery Identity Complete" default: return fmt.Sprintf("Unknown registration state %v", uint32(rs)) } diff --git a/storage/session.go b/storage/session.go index d3b8677b057a9f23da6c0e6e31e773799e27c9f5..44278489c94d868f1b76556c2375c8fe8981d298 100644 --- a/storage/session.go +++ b/storage/session.go @@ -90,11 +90,11 @@ func New(baseDir, password string, u userInterface.User, cmixGrp, "Create new session") } - s.user, err = user.NewUser(s.kv, u.ID, u.Salt, u.RSA, u.Precanned) + s.user, err = user.NewUser(s.kv, u.TransmissionID, u.ReceptionID, u.TransmissionSalt, u.ReceptionSalt, u.TransmissionRSA, u.ReceptionRSA, u.Precanned) if err != nil { return nil, errors.WithMessage(err, "Failed to create user") } - uid := s.user.GetCryptographicIdentity().GetUserID() + uid := s.user.GetCryptographicIdentity().GetReceptionID() s.cmix, err = cmix.NewStore(cmixGrp, s.kv, u.CmixDhPrivateKey) if err != nil { @@ -161,7 +161,7 @@ func Load(baseDir, password string, rng *fastRNG.StreamGenerator) (*Session, err return nil, errors.WithMessage(err, "Failed to load Session") } - uid := s.user.GetCryptographicIdentity().GetUserID() + uid := s.user.GetCryptographicIdentity().GetReceptionID() s.e2e, err = e2e.LoadStore(s.kv, uid, rng) if err != nil { @@ -294,11 +294,12 @@ func InitTestingSession(i interface{}) *Session { kv := versioned.NewKV(store) s := &Session{kv: kv} uid := id.NewIdFromString("zezima", id.User, i) - u, err := user.NewUser(kv, uid, []byte("salt"), privKey, false) + u, err := user.NewUser(kv, uid, uid, []byte("salt"), []byte("salt"), privKey, privKey, false) if err != nil { globals.Log.FATAL.Panicf("InitTestingSession failed to create dummy user: %+v", err) } - u.SetRegistrationValidationSignature([]byte("sig")) + u.SetTransmissionRegistrationValidationSignature([]byte("sig")) + u.SetReceptionRegistrationValidationSignature([]byte("sig")) s.user = u cmixGrp := cyclic.NewGroup( large.NewIntFromString("9DB6FB5951B66BB6FE1E140F1D2CE5502374161FD6538DF1648218642F0B5C48"+ diff --git a/storage/user.go b/storage/user.go index b6003cdba1a5eb4fe1d9f9a69549e16632513eb4..df1d9055e3490a3290d9ad378b3857bc16ca7cc4 100644 --- a/storage/user.go +++ b/storage/user.go @@ -14,9 +14,12 @@ func (s *Session) GetUser() user.User { defer s.mux.RUnlock() ci := s.user.GetCryptographicIdentity() return user.User{ - ID: ci.GetUserID().DeepCopy(), - Salt: copySlice(ci.GetSalt()), - RSA: ci.GetRSA(), + TransmissionID: ci.GetTransmissionID().DeepCopy(), + TransmissionSalt: copySlice(ci.GetTransmissionSalt()), + TransmissionRSA: ci.GetReceptionRSA(), + ReceptionID: ci.GetReceptionID().DeepCopy(), + ReceptionSalt: copySlice(ci.GetReceptionSalt()), + ReceptionRSA: ci.GetReceptionRSA(), Precanned: ci.IsPrecanned(), CmixDhPrivateKey: s.cmix.GetDHPrivateKey().DeepCopy(), CmixDhPublicKey: s.cmix.GetDHPublicKey().DeepCopy(), diff --git a/storage/user/cryptographic.go b/storage/user/cryptographic.go index 2790d4d72b2d15785023ba16083b0bbaf3167168..b444ea7190f10f1ee935ebe573a71fbe46648593 100644 --- a/storage/user/cryptographic.go +++ b/storage/user/cryptographic.go @@ -22,27 +22,36 @@ const currentCryptographicIdentityVersion = 0 const cryptographicIdentityKey = "cryptographicIdentity" type CryptographicIdentity struct { - userID *id.ID - salt []byte - rsaKey *rsa.PrivateKey - isPrecanned bool + transmissionID *id.ID + transmissionSalt []byte + transmissionRsaKey *rsa.PrivateKey + receptionID *id.ID + receptionSalt []byte + receptionRsaKey *rsa.PrivateKey + isPrecanned bool } type ciDisk struct { - UserID *id.ID - Salt []byte - RsaKey *rsa.PrivateKey - IsPrecanned bool + TransmissionID *id.ID + TransmissionSalt []byte + TransmissionRsaKey *rsa.PrivateKey + ReceptionID *id.ID + ReceptionSalt []byte + ReceptionRsaKey *rsa.PrivateKey + IsPrecanned bool } -func newCryptographicIdentity(uid *id.ID, salt []byte, rsaKey *rsa.PrivateKey, +func newCryptographicIdentity(transmissionID, receptionID *id.ID, transmissionSalt, receptionSalt []byte, transmissionRsa, receptionRsa *rsa.PrivateKey, isPrecanned bool, kv *versioned.KV) *CryptographicIdentity { ci := &CryptographicIdentity{ - userID: uid, - salt: salt, - rsaKey: rsaKey, - isPrecanned: isPrecanned, + transmissionID: transmissionID, + transmissionSalt: transmissionSalt, + transmissionRsaKey: transmissionRsa, + receptionID: receptionID, + receptionSalt: receptionSalt, + receptionRsaKey: receptionRsa, + isPrecanned: isPrecanned, } if err := ci.save(kv); err != nil { @@ -70,9 +79,12 @@ func loadCryptographicIdentity(kv *versioned.KV) (*CryptographicIdentity, error) if decodable != nil { result.isPrecanned = decodable.IsPrecanned - result.rsaKey = decodable.RsaKey - result.salt = decodable.Salt - result.userID = decodable.UserID + result.receptionRsaKey = decodable.ReceptionRsaKey + result.transmissionRsaKey = decodable.TransmissionRsaKey + result.transmissionSalt = decodable.TransmissionSalt + result.transmissionID = decodable.TransmissionID + result.receptionID = decodable.ReceptionID + result.receptionSalt = decodable.ReceptionSalt } return result, err @@ -82,10 +94,13 @@ func (ci *CryptographicIdentity) save(kv *versioned.KV) error { var userDataBuffer bytes.Buffer encodable := &ciDisk{ - UserID: ci.userID, - Salt: ci.salt, - RsaKey: ci.rsaKey, - IsPrecanned: ci.isPrecanned, + TransmissionID: ci.transmissionID, + TransmissionSalt: ci.transmissionSalt, + TransmissionRsaKey: ci.transmissionRsaKey, + ReceptionID: ci.receptionID, + ReceptionSalt: ci.receptionSalt, + ReceptionRsaKey: ci.receptionRsaKey, + IsPrecanned: ci.isPrecanned, } enc := gob.NewEncoder(&userDataBuffer) @@ -103,16 +118,28 @@ func (ci *CryptographicIdentity) save(kv *versioned.KV) error { return kv.Set(cryptographicIdentityKey, obj) } -func (ci *CryptographicIdentity) GetUserID() *id.ID { - return ci.userID.DeepCopy() +func (ci *CryptographicIdentity) GetTransmissionID() *id.ID { + return ci.transmissionID.DeepCopy() } -func (ci *CryptographicIdentity) GetSalt() []byte { - return ci.salt +func (ci *CryptographicIdentity) GetTransmissionSalt() []byte { + return ci.transmissionSalt } -func (ci *CryptographicIdentity) GetRSA() *rsa.PrivateKey { - return ci.rsaKey +func (ci *CryptographicIdentity) GetReceptionID() *id.ID { + return ci.receptionID.DeepCopy() +} + +func (ci *CryptographicIdentity) GetReceptionSalt() []byte { + return ci.receptionSalt +} + +func (ci *CryptographicIdentity) GetReceptionRSA() *rsa.PrivateKey { + return ci.receptionRsaKey +} + +func (ci *CryptographicIdentity) GetTransmissionRSA() *rsa.PrivateKey { + return ci.transmissionRsaKey } func (ci *CryptographicIdentity) IsPrecanned() bool { diff --git a/storage/user/cryptographic_test.go b/storage/user/cryptographic_test.go index 19c9034cd6c554d0b2274b4a57b4e6a6cc66575e..b1d80bb46187f5d63f240d2afaee0ce76b3311c4 100644 --- a/storage/user/cryptographic_test.go +++ b/storage/user/cryptographic_test.go @@ -21,7 +21,8 @@ import ( func TestNewCryptographicIdentity(t *testing.T) { kv := versioned.NewKV(make(ekv.Memstore)) uid := id.NewIdFromString("zezima", id.User, t) - _ = newCryptographicIdentity(uid, []byte("salt"), &rsa.PrivateKey{}, false, kv) + salt := []byte("salt") + _ = newCryptographicIdentity(uid, uid, salt, salt, &rsa.PrivateKey{}, &rsa.PrivateKey{}, false, kv) _, err := kv.Get(cryptographicIdentityKey) if err != nil { @@ -33,7 +34,8 @@ func TestNewCryptographicIdentity(t *testing.T) { func TestLoadCryptographicIdentity(t *testing.T) { kv := versioned.NewKV(make(ekv.Memstore)) uid := id.NewIdFromString("zezima", id.User, t) - ci := newCryptographicIdentity(uid, []byte("salt"), &rsa.PrivateKey{}, false, kv) + salt := []byte("salt") + ci := newCryptographicIdentity(uid, uid, salt, salt, &rsa.PrivateKey{}, &rsa.PrivateKey{}, false, kv) err := ci.save(kv) if err != nil { @@ -44,43 +46,94 @@ func TestLoadCryptographicIdentity(t *testing.T) { if err != nil { t.Errorf("Failed to load cryptographic identity: %+v", err) } - if !ci.userID.Cmp(newCi.userID) { - t.Errorf("Did not load expected ci. Expected: %+v, Received: %+v", ci.userID, newCi.userID) + if !ci.transmissionID.Cmp(newCi.transmissionID) { + t.Errorf("Did not load expected ci. Expected: %+v, Received: %+v", ci.transmissionID, newCi.transmissionID) } } -// Happy path for GetRSA function -func TestCryptographicIdentity_GetRSA(t *testing.T) { +// Happy path for GetReceptionRSA function +func TestCryptographicIdentity_GetReceptionRSA(t *testing.T) { kv := versioned.NewKV(make(ekv.Memstore)) uid := id.NewIdFromString("zezima", id.User, t) - pk, err := rsa.GenerateKey(rand.Reader, 64) + pk1, err := rsa.GenerateKey(rand.Reader, 64) if err != nil { - t.Errorf("Failed to generate pk") + t.Errorf("Failed to generate pk1") } - ci := newCryptographicIdentity(uid, []byte("salt"), pk, false, kv) - if ci.GetRSA().D != pk.D { - t.Errorf("Did not receive expected RSA key. Expected: %+v, Received: %+v", pk, ci.GetRSA()) + pk2, err := rsa.GenerateKey(rand.Reader, 64) + if err != nil { + t.Errorf("Failed to generate pk2") + } + salt := []byte("salt") + ci := newCryptographicIdentity(uid, uid, salt, salt, pk1, pk2, false, kv) + if ci.GetReceptionRSA().D != pk2.D { + t.Errorf("Did not receive expected RSA key. Expected: %+v, Received: %+v", pk2, ci.GetReceptionRSA()) + } +} + +// Happy path for GetTransmissionRSA function +func TestCryptographicIdentity_GetTransmissionRSA(t *testing.T) { + kv := versioned.NewKV(make(ekv.Memstore)) + uid := id.NewIdFromString("zezima", id.User, t) + pk1, err := rsa.GenerateKey(rand.Reader, 64) + if err != nil { + t.Errorf("Failed to generate pk1") + } + pk2, err := rsa.GenerateKey(rand.Reader, 64) + if err != nil { + t.Errorf("Failed to generate pk2") + } + salt := []byte("salt") + ci := newCryptographicIdentity(uid, uid, salt, salt, pk1, pk2, false, kv) + if ci.GetTransmissionRSA().D != pk1.D { + t.Errorf("Did not receive expected RSA key. Expected: %+v, Received: %+v", pk1, ci.GetTransmissionRSA()) } } // Happy path for GetSalt function -func TestCryptographicIdentity_GetSalt(t *testing.T) { +func TestCryptographicIdentity_GetTransmissionSalt(t *testing.T) { kv := versioned.NewKV(make(ekv.Memstore)) uid := id.NewIdFromString("zezima", id.User, t) - salt := []byte("NaCl") - ci := newCryptographicIdentity(uid, salt, &rsa.PrivateKey{}, false, kv) - if bytes.Compare(ci.GetSalt(), salt) != 0 { - t.Errorf("Did not get expected salt. Expected: %+v, Received: %+v", salt, ci.GetSalt()) + ts := []byte("transmission salt") + rs := []byte("reception salt") + ci := newCryptographicIdentity(uid, uid, ts, rs, &rsa.PrivateKey{}, &rsa.PrivateKey{}, false, kv) + if bytes.Compare(ci.GetTransmissionSalt(), ts) != 0 { + t.Errorf("Did not get expected salt. Expected: %+v, Received: %+v", ts, ci.GetTransmissionSalt()) } } -// Happy path for GetUserID function -func TestCryptographicIdentity_GetUserID(t *testing.T) { +// Happy path for GetSalt function +func TestCryptographicIdentity_GetReceptionSalt(t *testing.T) { kv := versioned.NewKV(make(ekv.Memstore)) uid := id.NewIdFromString("zezima", id.User, t) - ci := newCryptographicIdentity(uid, []byte("salt"), &rsa.PrivateKey{}, false, kv) - if !ci.GetUserID().Cmp(uid) { - t.Errorf("Did not receive expected user ID. Expected: %+v, Received: %+v", uid, ci.GetUserID()) + ts := []byte("transmission salt") + rs := []byte("reception salt") + ci := newCryptographicIdentity(uid, uid, ts, rs, &rsa.PrivateKey{}, &rsa.PrivateKey{}, false, kv) + if bytes.Compare(ci.GetReceptionSalt(), rs) != 0 { + t.Errorf("Did not get expected salt. Expected: %+v, Received: %+v", rs, ci.GetReceptionSalt()) + } +} + +// Happy path for GetUserID function +func TestCryptographicIdentity_GetTransmissionID(t *testing.T) { + kv := versioned.NewKV(make(ekv.Memstore)) + rid := id.NewIdFromString("zezima", id.User, t) + tid := id.NewIdFromString("jakexx360", id.User, t) + salt := []byte("salt") + ci := newCryptographicIdentity(tid, rid, salt, salt, &rsa.PrivateKey{}, &rsa.PrivateKey{}, false, kv) + if !ci.GetTransmissionID().Cmp(tid) { + t.Errorf("Did not receive expected user ID. Expected: %+v, Received: %+v", tid, ci.GetTransmissionID()) + } +} + +// Happy path for GetUserID function +func TestCryptographicIdentity_GetReceptionID(t *testing.T) { + kv := versioned.NewKV(make(ekv.Memstore)) + rid := id.NewIdFromString("zezima", id.User, t) + tid := id.NewIdFromString("jakexx360", id.User, t) + salt := []byte("salt") + ci := newCryptographicIdentity(tid, rid, salt, salt, &rsa.PrivateKey{}, &rsa.PrivateKey{}, false, kv) + if !ci.GetReceptionID().Cmp(rid) { + t.Errorf("Did not receive expected user ID. Expected: %+v, Received: %+v", rid, ci.GetReceptionID()) } } @@ -88,7 +141,8 @@ func TestCryptographicIdentity_GetUserID(t *testing.T) { func TestCryptographicIdentity_IsPrecanned(t *testing.T) { kv := versioned.NewKV(make(ekv.Memstore)) uid := id.NewIdFromString("zezima", id.User, t) - ci := newCryptographicIdentity(uid, []byte("salt"), &rsa.PrivateKey{}, true, kv) + salt := []byte("salt") + ci := newCryptographicIdentity(uid, uid, salt, salt, &rsa.PrivateKey{}, &rsa.PrivateKey{}, true, kv) if !ci.IsPrecanned() { t.Error("I really don't know how this could happen") } diff --git a/storage/user/regValidationSig.go b/storage/user/regValidationSig.go index e70b636d2ac4ba1be168c18b069ce07bfddc6bc1..a64b33d4d713acefe6dad14eb8d1c3a056188d66 100644 --- a/storage/user/regValidationSig.go +++ b/storage/user/regValidationSig.go @@ -14,35 +14,80 @@ import ( ) const currentRegValidationSigVersion = 0 -const regValidationSigKey = "registrationValidationSignature" +const transmissionRegValidationSigKey = "transmissionRegistrationValidationSignature" +const receptionRegValidationSigKey = "receptionRegistrationValidationSignature" -// Returns the Registration Validation Signature stored in RAM. May return +// Returns the transmission Identity Validation Signature stored in RAM. May return // nil of no signature is stored -func (u *User) GetRegistrationValidationSignature() []byte { +func (u *User) GetTransmissionRegistrationValidationSignature() []byte { u.rvsMux.RLock() defer u.rvsMux.RUnlock() - return u.regValidationSig + return u.transmissionRegValidationSig } -// Loads the Registration Validation Signature if it exists in the ekv -func (u *User) loadRegistrationValidationSignature() { +// Returns the reception Identity Validation Signature stored in RAM. May return +// nil of no signature is stored +func (u *User) GetReceptionRegistrationValidationSignature() []byte { + u.rvsMux.RLock() + defer u.rvsMux.RUnlock() + return u.receptionRegValidationSig +} + +// Loads the transmission Identity Validation Signature if it exists in the ekv +func (u *User) loadTransmissionRegistrationValidationSignature() { u.rvsMux.Lock() - obj, err := u.kv.Get(regValidationSigKey) + obj, err := u.kv.Get(transmissionRegValidationSigKey) if err == nil { - u.regValidationSig = obj.Data + u.transmissionRegValidationSig = obj.Data } u.rvsMux.Unlock() } -// Sets the Registration Validation Signature if it is not set and stores it in +// Loads the reception Identity Validation Signature if it exists in the ekv +func (u *User) loadReceptionRegistrationValidationSignature() { + u.rvsMux.Lock() + obj, err := u.kv.Get(receptionRegValidationSigKey) + if err == nil { + u.receptionRegValidationSig = obj.Data + } + u.rvsMux.Unlock() +} + +// Sets the Identity Validation Signature if it is not set and stores it in +// the ekv +func (u *User) SetTransmissionRegistrationValidationSignature(b []byte) { + u.rvsMux.Lock() + defer u.rvsMux.Unlock() + + //check if the signature already exists + if u.transmissionRegValidationSig != nil { + jww.FATAL.Panicf("cannot overwrite existing transmission Identity Validation Signature") + } + + obj := &versioned.Object{ + Version: currentRegValidationSigVersion, + Timestamp: time.Now(), + Data: b, + } + + err := u.kv.Set(transmissionRegValidationSigKey, obj) + if err != nil { + jww.FATAL.Panicf("Failed to store the transmission Identity Validation "+ + "Signature: %s", err) + } + + u.transmissionRegValidationSig = b +} + +// Sets the Identity Validation Signature if it is not set and stores it in // the ekv -func (u *User) SetRegistrationValidationSignature(b []byte) { +func (u *User) SetReceptionRegistrationValidationSignature(b []byte) { u.rvsMux.Lock() defer u.rvsMux.Unlock() //check if the signature already exists - if u.regValidationSig != nil { - jww.FATAL.Panicf("cannot overwrite existing Registration Validation Signature") + if u.receptionRegValidationSig != nil { + jww.FATAL.Panicf("cannot overwrite existing reception Identity Validation Signature") } obj := &versioned.Object{ @@ -51,11 +96,11 @@ func (u *User) SetRegistrationValidationSignature(b []byte) { Data: b, } - err := u.kv.Set(regValidationSigKey, obj) + err := u.kv.Set(receptionRegValidationSigKey, obj) if err != nil { - jww.FATAL.Panicf("Failed to store the Registration Validation "+ + jww.FATAL.Panicf("Failed to store the reception Identity Validation "+ "Signature: %s", err) } - u.regValidationSig = b + u.receptionRegValidationSig = b } diff --git a/storage/user/regValidationSig_test.go b/storage/user/regValidationSig_test.go index 09c73fdd9ccd92cf02b9a8064dcb23968c5c2269..84cde96f59cc16f230231ac1bf9a5054476b0ecb 100644 --- a/storage/user/regValidationSig_test.go +++ b/storage/user/regValidationSig_test.go @@ -21,21 +21,34 @@ import ( func TestUser_GetRegistrationValidationSignature(t *testing.T) { kv := versioned.NewKV(make(ekv.Memstore)) uid := id.NewIdFromString("test", id.User, t) - u, err := NewUser(kv, uid, []byte("salt"), &rsa.PrivateKey{}, false) + salt := []byte("salt") + u, err := NewUser(kv, uid, uid, salt, salt, &rsa.PrivateKey{}, &rsa.PrivateKey{}, false) if err != nil || u == nil { t.Errorf("Failed to create new user: %+v", err) } - sig := []byte("testsignature") - u.SetRegistrationValidationSignature(sig) - if bytes.Compare(sig, u.regValidationSig) != 0 { + sig := []byte("testreceptionsignature") + u.SetReceptionRegistrationValidationSignature(sig) + if bytes.Compare(sig, u.receptionRegValidationSig) != 0 { t.Errorf("Failed to set user object signature field. Expected: %+v, Received: %+v", - sig, u.regValidationSig) + sig, u.receptionRegValidationSig) } - if bytes.Compare(u.GetRegistrationValidationSignature(), sig) != 0 { + if bytes.Compare(u.GetReceptionRegistrationValidationSignature(), sig) != 0 { t.Errorf("Did not receive expected result from GetRegistrationValidationSignature. "+ - "Expected: %+v, Received: %+v", sig, u.GetRegistrationValidationSignature()) + "Expected: %+v, Received: %+v", sig, u.GetReceptionRegistrationValidationSignature()) + } + + sig = []byte("testtransmissionsignature") + u.SetTransmissionRegistrationValidationSignature(sig) + if bytes.Compare(sig, u.transmissionRegValidationSig) != 0 { + t.Errorf("Failed to set user object signature field. Expected: %+v, Received: %+v", + sig, u.transmissionRegValidationSig) + } + + if bytes.Compare(u.GetTransmissionRegistrationValidationSignature(), sig) != 0 { + t.Errorf("Did not receive expected result from GetRegistrationValidationSignature. "+ + "Expected: %+v, Received: %+v", sig, u.GetTransmissionRegistrationValidationSignature()) } } @@ -43,19 +56,36 @@ func TestUser_GetRegistrationValidationSignature(t *testing.T) { func TestUser_SetRegistrationValidationSignature(t *testing.T) { kv := versioned.NewKV(make(ekv.Memstore)) uid := id.NewIdFromString("test", id.User, t) - u, err := NewUser(kv, uid, []byte("salt"), &rsa.PrivateKey{}, false) + salt := []byte("salt") + u, err := NewUser(kv, uid, uid, salt, salt, &rsa.PrivateKey{}, &rsa.PrivateKey{}, false) if err != nil || u == nil { t.Errorf("Failed to create new user: %+v", err) } - sig := []byte("testsignature") - u.SetRegistrationValidationSignature(sig) - if bytes.Compare(sig, u.regValidationSig) != 0 { + sig := []byte("testtransmissionsignature") + u.SetTransmissionRegistrationValidationSignature(sig) + if bytes.Compare(sig, u.transmissionRegValidationSig) != 0 { t.Errorf("Failed to set user object signature field. Expected: %+v, Received: %+v", - sig, u.regValidationSig) + sig, u.transmissionRegValidationSig) } - obj, err := u.kv.Get(regValidationSigKey) + obj, err := u.kv.Get(transmissionRegValidationSigKey) + if err != nil { + t.Errorf("Failed to get reg vaildation signature key: %+v", err) + } + if bytes.Compare(obj.Data, sig) != 0 { + t.Errorf("Did not properly set reg validation signature key in kv store.\nExpected: %+v, Received: %+v", + sig, obj.Data) + } + + sig = []byte("testreceptionsignature") + u.SetReceptionRegistrationValidationSignature(sig) + if bytes.Compare(sig, u.receptionRegValidationSig) != 0 { + t.Errorf("Failed to set user object signature field. Expected: %+v, Received: %+v", + sig, u.receptionRegValidationSig) + } + + obj, err = u.kv.Get(receptionRegValidationSigKey) if err != nil { t.Errorf("Failed to get reg vaildation signature key: %+v", err) } @@ -69,13 +99,29 @@ func TestUser_SetRegistrationValidationSignature(t *testing.T) { func TestUser_loadRegistrationValidationSignature(t *testing.T) { kv := versioned.NewKV(make(ekv.Memstore)) uid := id.NewIdFromString("test", id.User, t) - u, err := NewUser(kv, uid, []byte("salt"), &rsa.PrivateKey{}, false) + salt := []byte("salt") + u, err := NewUser(kv, uid, uid, salt, salt, &rsa.PrivateKey{}, &rsa.PrivateKey{}, false) if err != nil || u == nil { t.Errorf("Failed to create new user: %+v", err) } - sig := []byte("signature") - err = kv.Set(regValidationSigKey, &versioned.Object{ + sig := []byte("transmissionsignature") + err = kv.Set(transmissionRegValidationSigKey, &versioned.Object{ + Version: currentRegValidationSigVersion, + Timestamp: time.Now(), + Data: sig, + }) + if err != nil { + t.Errorf("Failed to set reg validation sig key in kv store: %+v", err) + } + + u.loadTransmissionRegistrationValidationSignature() + if bytes.Compare(u.transmissionRegValidationSig, sig) != 0 { + t.Errorf("Expected sig did not match loaded. Expected: %+v, Received: %+v", sig, u.transmissionRegValidationSig) + } + + sig = []byte("receptionsignature") + err = kv.Set(receptionRegValidationSigKey, &versioned.Object{ Version: currentRegValidationSigVersion, Timestamp: time.Now(), Data: sig, @@ -84,8 +130,8 @@ func TestUser_loadRegistrationValidationSignature(t *testing.T) { t.Errorf("Failed to set reg validation sig key in kv store: %+v", err) } - u.loadRegistrationValidationSignature() - if bytes.Compare(u.regValidationSig, sig) != 0 { - t.Errorf("Expected sig did not match loaded. Expected: %+v, Received: %+v", sig, u.regValidationSig) + u.loadReceptionRegistrationValidationSignature() + if bytes.Compare(u.receptionRegValidationSig, sig) != 0 { + t.Errorf("Expected sig did not match loaded. Expected: %+v, Received: %+v", sig, u.receptionRegValidationSig) } } diff --git a/storage/user/user.go b/storage/user/user.go index e79928d93b55c2787604fbd9d44fb31b0b20e9ec..a55830ff131620f7f9f499b2a6932d616675ccda 100644 --- a/storage/user/user.go +++ b/storage/user/user.go @@ -18,8 +18,9 @@ import ( type User struct { ci *CryptographicIdentity - regValidationSig []byte - rvsMux sync.RWMutex + transmissionRegValidationSig []byte + receptionRegValidationSig []byte + rvsMux sync.RWMutex username string usernameMux sync.RWMutex @@ -28,10 +29,10 @@ type User struct { } // builds a new user. -func NewUser(kv *versioned.KV, uid *id.ID, salt []byte, rsaKey *rsa.PrivateKey, - isPrecanned bool) (*User, error) { +func NewUser(kv *versioned.KV, transmissionID, receptionID *id.ID, transmissionSalt, + receptionSalt []byte, transmissionRsa, receptionRsa *rsa.PrivateKey, isPrecanned bool) (*User, error) { - ci := newCryptographicIdentity(uid, salt, rsaKey, isPrecanned, kv) + ci := newCryptographicIdentity(transmissionID, receptionID, transmissionSalt, receptionSalt, transmissionRsa, receptionRsa, isPrecanned, kv) return &User{ci: ci, kv: kv}, nil } @@ -44,7 +45,8 @@ func LoadUser(kv *versioned.KV) (*User, error) { } u := &User{ci: ci, kv: kv} - u.loadRegistrationValidationSignature() + u.loadTransmissionRegistrationValidationSignature() + u.loadReceptionRegistrationValidationSignature() u.loadUsername() return u, nil diff --git a/storage/user/user_test.go b/storage/user/user_test.go index 0473138dc7eaea4ef806dfcbc7ecc76fd0a66f2b..0fd3d8d1819163dcadac0d7bed29f183f45acd32 100644 --- a/storage/user/user_test.go +++ b/storage/user/user_test.go @@ -26,7 +26,8 @@ func TestLoadUser(t *testing.T) { } uid := id.NewIdFromString("test", id.User, t) - ci := newCryptographicIdentity(uid, []byte("salt"), &rsa.PrivateKey{}, false, kv) + salt := []byte("salt") + ci := newCryptographicIdentity(uid, uid, salt, salt, &rsa.PrivateKey{}, &rsa.PrivateKey{}, false, kv) err = ci.save(kv) if err != nil { t.Errorf("Failed to save ci to kv: %+v", err) @@ -42,7 +43,8 @@ func TestLoadUser(t *testing.T) { func TestNewUser(t *testing.T) { kv := versioned.NewKV(make(ekv.Memstore)) uid := id.NewIdFromString("test", id.User, t) - u, err := NewUser(kv, uid, []byte("salt"), &rsa.PrivateKey{}, false) + salt := []byte("salt") + u, err := NewUser(kv, uid, uid, salt, salt, &rsa.PrivateKey{}, &rsa.PrivateKey{}, false) if err != nil || u == nil { t.Errorf("Failed to create new user: %+v", err) } @@ -52,13 +54,15 @@ func TestNewUser(t *testing.T) { func TestUser_GetCryptographicIdentity(t *testing.T) { kv := versioned.NewKV(make(ekv.Memstore)) uid := id.NewIdFromString("test", id.User, t) - u, err := NewUser(kv, uid, []byte("salt"), &rsa.PrivateKey{}, false) + rsalt := []byte("reception salt") + tsalt := []byte("transmission salt") + u, err := NewUser(kv, uid, uid, tsalt, rsalt, &rsa.PrivateKey{}, &rsa.PrivateKey{}, false) if err != nil || u == nil { t.Errorf("Failed to create new user: %+v", err) } ci := u.GetCryptographicIdentity() - if bytes.Compare(ci.salt, []byte("salt")) != 0 { + if bytes.Compare(ci.transmissionSalt, tsalt) != 0 { t.Errorf("Cryptographic Identity not retrieved properly") } } diff --git a/storage/user/username_test.go b/storage/user/username_test.go index db2f399c313e8038dd9ce33709f7a256373b6481..486234153ccb16c08589435c4f5ad40039df2165 100644 --- a/storage/user/username_test.go +++ b/storage/user/username_test.go @@ -19,8 +19,11 @@ import ( // Test normal function and errors for User's SetUsername function func TestUser_SetUsername(t *testing.T) { kv := versioned.NewKV(make(ekv.Memstore)) - uid := id.NewIdFromString("test", id.User, t) - u, err := NewUser(kv, uid, []byte("salt"), &rsa.PrivateKey{}, false) + tid := id.NewIdFromString("trans", id.User, t) + rid := id.NewIdFromString("recv", id.User, t) + tsalt := []byte("tsalt") + rsalt := []byte("rsalt") + u, err := NewUser(kv, tid, rid, tsalt, rsalt, &rsa.PrivateKey{}, &rsa.PrivateKey{}, false) if err != nil || u == nil { t.Errorf("Failed to create new user: %+v", err) } @@ -50,8 +53,11 @@ func TestUser_SetUsername(t *testing.T) { // Test functionality of User's GetUsername function func TestUser_GetUsername(t *testing.T) { kv := versioned.NewKV(make(ekv.Memstore)) - uid := id.NewIdFromString("test", id.User, t) - u, err := NewUser(kv, uid, []byte("salt"), &rsa.PrivateKey{}, false) + tid := id.NewIdFromString("trans", id.User, t) + rid := id.NewIdFromString("recv", id.User, t) + tsalt := []byte("tsalt") + rsalt := []byte("rsalt") + u, err := NewUser(kv, tid, rid, tsalt, rsalt, &rsa.PrivateKey{}, &rsa.PrivateKey{}, false) if err != nil || u == nil { t.Errorf("Failed to create new user: %+v", err) } @@ -75,8 +81,11 @@ func TestUser_GetUsername(t *testing.T) { // Test the loadUsername helper function func TestUser_loadUsername(t *testing.T) { kv := versioned.NewKV(make(ekv.Memstore)) - uid := id.NewIdFromString("test", id.User, t) - u, err := NewUser(kv, uid, []byte("salt"), &rsa.PrivateKey{}, false) + tid := id.NewIdFromString("trans", id.User, t) + rid := id.NewIdFromString("recv", id.User, t) + tsalt := []byte("tsalt") + rsalt := []byte("rsalt") + u, err := NewUser(kv, tid, rid, tsalt, rsalt, &rsa.PrivateKey{}, &rsa.PrivateKey{}, false) if err != nil || u == nil { t.Errorf("Failed to create new user: %+v", err) } diff --git a/storage/utility/knownRounds.go b/storage/utility/knownRounds.go index 767ad917c4e57f7e8040deb58713e069fd2b6596..72f4833d7158483fb88c881434a7ed8f4009852b 100644 --- a/storage/utility/knownRounds.go +++ b/storage/utility/knownRounds.go @@ -35,10 +35,10 @@ type KnownRounds struct { // NewKnownRounds creates a new empty KnownRounds and saves it to the passed // in key value store at the specified key. An error is returned on an // unsuccessful save. -func NewKnownRounds(kv *versioned.KV, key string, size int) (*KnownRounds, error) { +func NewKnownRounds(kv *versioned.KV, key string, known *knownRounds.KnownRounds) (*KnownRounds, error) { // Create new empty struct kr := &KnownRounds{ - rounds: knownRounds.NewKnownRound(size), + rounds: known, kv: kv.Prefix(knownRoundsPrefix), key: key, } @@ -107,6 +107,15 @@ func (kr *KnownRounds) load() error { return nil } +// Deletes a known rounds object from disk and memory +func (kr *KnownRounds) Delete() error { + err := kr.kv.Delete(kr.key) + if err != nil { + return err + } + return nil +} + // Checked determines if the round has been checked. func (kr *KnownRounds) Checked(rid id.Round) bool { kr.mux.RLock() @@ -158,7 +167,7 @@ func (kr *KnownRounds) RangeUnchecked(newestRid id.Round, // RangeUncheckedMasked checks rounds based off the provided mask. func (kr *KnownRounds) RangeUncheckedMasked(mask *knownRounds.KnownRounds, - roundCheck func(id id.Round) bool, maxChecked int) { + roundCheck knownRounds.RoundCheckFunc, maxChecked int) { kr.mux.Lock() defer kr.mux.Unlock() @@ -169,3 +178,17 @@ func (kr *KnownRounds) RangeUncheckedMasked(mask *knownRounds.KnownRounds, jww.FATAL.Panicf("Error saving list of checked rounds: %v", err) } } + +// RangeUncheckedMasked checks rounds based off the provided mask. +func (kr *KnownRounds) RangeUncheckedMaskedRange(mask *knownRounds.KnownRounds, + roundCheck knownRounds.RoundCheckFunc, start, end id.Round, maxChecked int) { + kr.mux.Lock() + defer kr.mux.Unlock() + + kr.rounds.RangeUncheckedMaskedRange(mask, roundCheck, start, end, maxChecked) + + err := kr.save() + if err != nil { + jww.FATAL.Panicf("Error saving list of checked rounds: %v", err) + } +} diff --git a/storage/utility/knownRounds_test.go b/storage/utility/knownRounds_test.go index 73f0cb5a38d2ef39b33d57ea1ae2892d335d015c..653025dbb46282006abdafdbf6733e591ade0705 100644 --- a/storage/utility/knownRounds_test.go +++ b/storage/utility/knownRounds_test.go @@ -28,7 +28,8 @@ func TestNewKnownRounds(t *testing.T) { } // Create new KnownRounds - kr, err := NewKnownRounds(rootKv, expectedKR.key, size) + k := knownRounds.NewKnownRound(size) + kr, err := NewKnownRounds(rootKv, expectedKR.key, k) if err != nil { t.Errorf("NewKnownRounds() returned an error."+ "\n\texpected: %v\n\treceived: %v", nil, err) @@ -154,7 +155,8 @@ func TestKnownRounds_save(t *testing.T) { // } func TestKnownRounds_Smoke(t *testing.T) { - kr, err := NewKnownRounds(versioned.NewKV(make(ekv.Memstore)), "testKey", 10) + k := knownRounds.NewKnownRound(10) + kr, err := NewKnownRounds(versioned.NewKV(make(ekv.Memstore)), "testKey", k) if err != nil { t.Fatalf("Failed to create new KnownRounds: %v", err) } diff --git a/ud/addFact.go b/ud/addFact.go index 11bf3395658b8e07073a44e6dc0ec1c4edd1ea83..6b2cd3b43e481dbb8e2bad98b76c5dad7d80c099 100644 --- a/ud/addFact.go +++ b/ud/addFact.go @@ -3,6 +3,7 @@ package ud import ( "crypto/rand" "github.com/pkg/errors" + jww "github.com/spf13/jwalterweatherman" pb "gitlab.com/elixxir/comms/mixmessages" "gitlab.com/elixxir/crypto/factID" "gitlab.com/elixxir/crypto/hash" @@ -10,7 +11,6 @@ import ( "gitlab.com/xx_network/comms/connect" "gitlab.com/xx_network/crypto/signature/rsa" "gitlab.com/xx_network/primitives/id" - jww "github.com/spf13/jwalterweatherman" ) type addFactComms interface { @@ -26,7 +26,7 @@ type addFactComms interface { // called along with the code to finalize the fact. func (m *Manager) SendRegisterFact(fact fact.Fact) (string, error) { jww.INFO.Printf("ud.SendRegisterFact(%s)", fact.Stringify()) - uid := m.storage.User().GetCryptographicIdentity().GetUserID() + uid := m.storage.User().GetCryptographicIdentity().GetTransmissionID() return m.addFact(fact, uid, m.comms) } @@ -66,8 +66,8 @@ func (m *Manager) addFact(inFact fact.Fact, uid *id.ID, aFC addFactComms) (strin response, err := aFC.SendRegisterFact(m.host, &remFactMsg) confirmationID := "" - if response!=nil{ - confirmationID=response.ConfirmationID + if response != nil { + confirmationID = response.ConfirmationID } // Return the error diff --git a/ud/manager.go b/ud/manager.go index 6350d0e7a511abd893ed92ac8d5f2482c992ddb4..eabb0750f7a9e1685076e0534bf3ed23c04be30a 100644 --- a/ud/manager.go +++ b/ud/manager.go @@ -2,6 +2,7 @@ package ud import ( "github.com/pkg/errors" + jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/client/api" "gitlab.com/elixxir/client/interfaces" "gitlab.com/elixxir/client/interfaces/message" @@ -14,7 +15,6 @@ import ( "gitlab.com/xx_network/crypto/signature/rsa" "gitlab.com/xx_network/primitives/id" "sync" - jww "github.com/spf13/jwalterweatherman" ) type Manager struct { @@ -48,9 +48,9 @@ type Manager struct { // New manager builds a new user discovery manager. It requires that an // updated NDF is available and will error if one is not. -func NewManager(client *api.Client)(*Manager, error){ +func NewManager(client *api.Client) (*Manager, error) { jww.INFO.Println("ud.NewManager()") - if !client.GetHealth().IsHealthy(){ + if !client.GetHealth().IsHealthy() { return nil, errors.New("cannot start UD Manager when network " + "was never healthy") } @@ -92,7 +92,7 @@ func NewManager(client *api.Client)(*Manager, error){ } //get the commonly used data from storage - m.privKey = m.storage.GetUser().RSA + m.privKey = m.storage.GetUser().TransmissionRSA //load the last used commID m.loadCommID() diff --git a/ud/register.go b/ud/register.go index 90832d6e5d9a036b260a920a284fe0c897c84e68..3afd284bb842ccd8182689c181c57e2bf0d5de6f 100644 --- a/ud/register.go +++ b/ud/register.go @@ -2,6 +2,7 @@ package ud import ( "github.com/pkg/errors" + jww "github.com/spf13/jwalterweatherman" pb "gitlab.com/elixxir/comms/mixmessages" "gitlab.com/elixxir/crypto/factID" "gitlab.com/elixxir/crypto/hash" @@ -9,7 +10,6 @@ import ( "gitlab.com/xx_network/comms/connect" "gitlab.com/xx_network/comms/messages" "gitlab.com/xx_network/crypto/signature/rsa" - jww "github.com/spf13/jwalterweatherman" ) type registerUserComms interface { @@ -20,7 +20,7 @@ type registerUserComms interface { // network signatures are malformed or if the username is taken. Usernames cannot // be changed after registration at this time. Will fail if the user is already // registered. -// Registration does not go over cmix, it occurs over normal communications +// Identity does not go over cmix, it occurs over normal communications func (m *Manager) Register(username string) error { jww.INFO.Printf("ud.Register(%s)", username) return m.register(username, m.comms) @@ -29,7 +29,7 @@ func (m *Manager) Register(username string) error { // register registers a user with user discovery with a specified comm for // easier testing. func (m *Manager) register(username string, comm registerUserComms) error { - if m.IsRegistered(){ + if m.IsRegistered() { return errors.New("cannot register client with User Discovery: " + "client is already registered") } @@ -41,19 +41,19 @@ func (m *Manager) register(username string, comm registerUserComms) error { // Construct the user registration message msg := &pb.UDBUserRegistration{ - PermissioningSignature: user.GetRegistrationValidationSignature(), - RSAPublicPem: string(rsa.CreatePublicKeyPem(cryptoUser.GetRSA().GetPublic())), + PermissioningSignature: user.GetTransmissionRegistrationValidationSignature(), + RSAPublicPem: string(rsa.CreatePublicKeyPem(cryptoUser.GetTransmissionRSA().GetPublic())), IdentityRegistration: &pb.Identity{ Username: username, DhPubKey: m.storage.E2e().GetDHPublicKey().Bytes(), - Salt: cryptoUser.GetSalt(), + Salt: cryptoUser.GetTransmissionSalt(), }, - UID: cryptoUser.GetUserID().Marshal(), + UID: cryptoUser.GetTransmissionID().Marshal(), } // Sign the identity data and add to user registration message identityDigest := msg.IdentityRegistration.Digest() - msg.IdentitySignature, err = rsa.Sign(rng, cryptoUser.GetRSA(), + msg.IdentitySignature, err = rsa.Sign(rng, cryptoUser.GetTransmissionRSA(), hash.CMixHash, identityDigest, nil) if err != nil { return errors.Errorf("Failed to sign user's IdentityRegistration: %+v", err) @@ -67,11 +67,11 @@ func (m *Manager) register(username string, comm registerUserComms) error { // Hash and sign fact hashedFact := factID.Fingerprint(usernameFact) - signedFact, err := rsa.Sign(rng, cryptoUser.GetRSA(), hash.CMixHash, hashedFact, nil) + signedFact, err := rsa.Sign(rng, cryptoUser.GetTransmissionRSA(), hash.CMixHash, hashedFact, nil) // Add username fact register request to the user registration message msg.Frs = &pb.FactRegisterRequest{ - UID: cryptoUser.GetUserID().Marshal(), + UID: cryptoUser.GetTransmissionID().Marshal(), Fact: &pb.Fact{ Fact: username, FactType: 0, @@ -82,7 +82,7 @@ func (m *Manager) register(username string, comm registerUserComms) error { // Register user with user discovery _, err = comm.SendRegisterUser(m.host, msg) - if err==nil{ + if err == nil { err = m.setRegistered() } diff --git a/ud/register_test.go b/ud/register_test.go index 8591ff9de8391183a1f5eedf6b2214a99036cfc8..7cfd66f1da801bf54b3c853b2232eb3d2f0d6645 100644 --- a/ud/register_test.go +++ b/ud/register_test.go @@ -38,9 +38,9 @@ func TestManager_register(t *testing.T) { // Set up manager m := &Manager{ - host: host, - rng: fastRNG.NewStreamGenerator(12, 3, csprng.NewSystemRNG), - storage: storage.InitTestingSession(t), + host: host, + rng: fastRNG.NewStreamGenerator(12, 3, csprng.NewSystemRNG), + storage: storage.InitTestingSession(t), registered: &isReg, } @@ -55,7 +55,7 @@ func TestManager_register(t *testing.T) { m.isCorrect("testUser", c.msg, t) // Verify the signed identity data - pubKey := m.storage.User().GetCryptographicIdentity().GetRSA().GetPublic() + pubKey := m.storage.User().GetCryptographicIdentity().GetTransmissionRSA().GetPublic() err = rsa.Verify(pubKey, hash.CMixHash, c.msg.IdentityRegistration.Digest(), c.msg.IdentitySignature, nil) if err != nil { @@ -77,14 +77,14 @@ func (m *Manager) isCorrect(username string, msg *pb.UDBUserRegistration, t *tes user := m.storage.User() cryptoUser := m.storage.User().GetCryptographicIdentity() - if !bytes.Equal(user.GetRegistrationValidationSignature(), msg.PermissioningSignature) { + if !bytes.Equal(user.GetTransmissionRegistrationValidationSignature(), msg.PermissioningSignature) { t.Errorf("PermissioningSignature incorrect.\n\texpected: %v\n\treceived: %v", - user.GetRegistrationValidationSignature(), msg.PermissioningSignature) + user.GetTransmissionRegistrationValidationSignature(), msg.PermissioningSignature) } - if string(rsa.CreatePublicKeyPem(cryptoUser.GetRSA().GetPublic())) != msg.RSAPublicPem { + if string(rsa.CreatePublicKeyPem(cryptoUser.GetTransmissionRSA().GetPublic())) != msg.RSAPublicPem { t.Errorf("RSAPublicPem incorrect.\n\texpected: %v\n\treceived: %v", - string(rsa.CreatePublicKeyPem(cryptoUser.GetRSA().GetPublic())), msg.RSAPublicPem) + string(rsa.CreatePublicKeyPem(cryptoUser.GetTransmissionRSA().GetPublic())), msg.RSAPublicPem) } if username != msg.IdentityRegistration.Username { @@ -97,14 +97,14 @@ func (m *Manager) isCorrect(username string, msg *pb.UDBUserRegistration, t *tes m.storage.E2e().GetDHPublicKey().Bytes(), msg.IdentityRegistration.DhPubKey) } - if !bytes.Equal(cryptoUser.GetSalt(), msg.IdentityRegistration.Salt) { + if !bytes.Equal(cryptoUser.GetTransmissionSalt(), msg.IdentityRegistration.Salt) { t.Errorf("IdentityRegistration Salt incorrect.\n\texpected: %#v\n\treceived: %#v", - cryptoUser.GetSalt(), msg.IdentityRegistration.Salt) + cryptoUser.GetTransmissionSalt(), msg.IdentityRegistration.Salt) } - if !bytes.Equal(cryptoUser.GetUserID().Marshal(), msg.Frs.UID) { + if !bytes.Equal(cryptoUser.GetTransmissionID().Marshal(), msg.Frs.UID) { t.Errorf("Frs UID incorrect.\n\texpected: %v\n\treceived: %v", - cryptoUser.GetUserID().Marshal(), msg.Frs.UID) + cryptoUser.GetTransmissionID().Marshal(), msg.Frs.UID) } if !reflect.DeepEqual(&pb.Fact{Fact: username}, msg.Frs.Fact) {