diff --git a/.gitignore b/.gitignore index 1348703249512ef3a56de1dada944640e8269c15..872d4c5002777a957a3614f8005b36d548ebbb68 100644 --- a/.gitignore +++ b/.gitignore @@ -27,5 +27,6 @@ localdev_* *.class *.aar *.jar +glide.yaml # Ignore genered version file cmd/version_vars.go diff --git a/api/client.go b/api/client.go index 96d53f4397504bf15cbd16aa06cd9d6a0cbd8b11..d57b99e661ef4291b8fbd8810b434762e3672d69 100644 --- a/api/client.go +++ b/api/client.go @@ -7,6 +7,7 @@ package api import ( + "crypto" "crypto/rand" "crypto/sha256" "encoding/base64" @@ -29,7 +30,6 @@ import ( "gitlab.com/elixxir/crypto/hash" "gitlab.com/elixxir/crypto/large" "gitlab.com/elixxir/crypto/registration" - "gitlab.com/elixxir/crypto/signature" "gitlab.com/elixxir/crypto/signature/rsa" "gitlab.com/elixxir/primitives/circuit" "gitlab.com/elixxir/primitives/id" @@ -47,6 +47,8 @@ type Client struct { topology *circuit.Circuit } +var PermissioningAddrID = "registration" + // Populates a text message and returns its wire representation // TODO support multi-type messages or telling if a message is too long? func FormatTextMessage(message string) []byte { @@ -160,6 +162,7 @@ func (cl *Client) Connect() error { if gateway.TlsCertificate != "" { gwCreds = []byte(gateway.TlsCertificate) } + gwID := id.NewNodeFromBytes(cl.ndf.Nodes[i].ID).NewGateway() globals.Log.INFO.Printf("Connecting to gateway %s at %s...", gwID.String(), gateway.Address) @@ -179,8 +182,8 @@ func (cl *Client) Connect() error { if cl.ndf.Registration.TlsCertificate != "" { regCert = []byte(cl.ndf.Registration.TlsCertificate) } - addr := io.ConnAddr("registration") - globals.Log.INFO.Printf("Connecting to permissioning at %s...", + addr := io.ConnAddr(PermissioningAddrID) + globals.Log.INFO.Printf("Connecting to permissioning/registration at %s...", cl.ndf.Registration.Address) err = (cl.comm).(*io.Messaging).Comms.ConnectToRegistration(addr, cl.ndf.Registration.Address, regCert) if err != nil { @@ -203,70 +206,43 @@ func (cl *Client) Register(preCan bool, registrationCode, nick, email string) (* var u *user.User var UID *id.User + largeIntBits := 16 + cmixGrp := cyclic.NewGroup( - large.NewIntFromString(cl.ndf.CMIX.Prime, 16), - large.NewIntFromString(cl.ndf.CMIX.Generator, 16), - large.NewIntFromString(cl.ndf.CMIX.SmallPrime, 16)) + large.NewIntFromString(cl.ndf.CMIX.Prime, largeIntBits), + large.NewIntFromString(cl.ndf.CMIX.Generator, largeIntBits), + large.NewIntFromString(cl.ndf.CMIX.SmallPrime, largeIntBits)) e2eGrp := cyclic.NewGroup( - large.NewIntFromString(cl.ndf.E2E.Prime, 16), - large.NewIntFromString(cl.ndf.E2E.Generator, 16), - large.NewIntFromString(cl.ndf.E2E.SmallPrime, 16)) + large.NewIntFromString(cl.ndf.E2E.Prime, largeIntBits), + large.NewIntFromString(cl.ndf.E2E.Generator, largeIntBits), + large.NewIntFromString(cl.ndf.E2E.SmallPrime, largeIntBits)) // Make CMIX keys array nk := make(map[id.Node]user.NodeKeys) - // Generate DSA keypair even for precanned users as it will probably - // be needed for the new UDB flow - params := signature.CustomDSAParams( - cmixGrp.GetP(), - cmixGrp.GetQ(), - cmixGrp.GetG()) - privateKey := params.PrivateKeyGen(rand.Reader) - publicKey := privateKey.PublicKeyGen() + // GENERATE CLIENT RSA KEYS + privateKeyRSA, err := rsa.GenerateKey(rand.Reader, rsa.DefaultRSABitLen) + if err != nil { + return nil, err + } + publicKeyRSA := privateKeyRSA.GetPublic() - fmt.Println("gened private keys") + privateKeyDH := cmixGrp.RandomCoprime(cmixGrp.NewMaxInt()) + publicKeyDH := cmixGrp.ExpG(privateKeyDH, cmixGrp.NewMaxInt()) // Handle precanned registration if preCan { - var successLook bool - globals.Log.DEBUG.Printf("Registering precanned user") - UID, successLook = user.Users.LookupUser(registrationCode) - - fmt.Println("UID:", UID, "success:", successLook) - - if !successLook { - globals.Log.ERROR.Printf("Register: HUID does not match") - return id.ZeroID, errors.New("could not register due to invalid HUID") - } - - var successGet bool - u, successGet = user.Users.GetUser(UID) - - if !successGet { - globals.Log.ERROR.Printf("Register: ID lookup failed") - err = errors.New("could not register due to ID lookup failure") - return id.ZeroID, err - } - - if nick != "" { - u.Nick = nick - } - - nodekeys, successKeys := user.Users.LookupKeys(u.User) - - if !successKeys { - globals.Log.ERROR.Printf("Register: could not find user keys") - err = errors.New("could not register due to missing user keys") + globals.Log.INFO.Printf("Registering precanned user") + u, UID, nk, err = cl.precannedRegister(registrationCode, nick, nk) + if err != nil { + globals.Log.ERROR.Printf("Unable to complete precanned registration: %+v", err) return id.ZeroID, err } - - for i := 0; i < len(cl.ndf.Gateways); i++ { - nk[*cl.topology.GetNodeAtIndex(i)] = *nodekeys - } } else { + saltSize := 256 // Generate salt for UserID - salt := make([]byte, 256) + salt := make([]byte, saltSize) _, err = csprng.NewSystemRNG().Read(salt) if err != nil { globals.Log.ERROR.Printf("Register: Unable to generate salt! %s", err) @@ -274,131 +250,59 @@ func (cl *Client) Register(preCan bool, registrationCode, nick, email string) (* } // Generate UserID by hashing salt and public key - UID = registration.GenUserID(publicKey, salt) - // Keep track of Server public keys provided at end of registration - var serverPublicKeys []*signature.DSAPublicKey + UID = registration.GenUserID(publicKeyRSA, salt) + // Initialized response from Registration Server - regHash, regR, regS := make([]byte, 0), make([]byte, 0), make([]byte, 0) + regHash := make([]byte, 0) // If Registration Server is specified, contact it // Only if registrationCode is set + globals.Log.INFO.Println("Register: Contacting registration server") if cl.ndf.Registration.Address != "" && registrationCode != "" { - // Send registration code and public key to RegistrationServer - response, err := (cl.comm).(*io.Messaging).Comms. - SendRegistrationMessage(io.ConnAddr("registration"), - &pb.UserRegistration{ - RegistrationCode: registrationCode, - Client: &pb.DSAPublicKey{ - Y: publicKey.GetKey().Bytes(), - P: params.GetP().Bytes(), - Q: params.GetQ().Bytes(), - G: params.GetG().Bytes(), - }, - }) + regHash, err = cl.sendRegistrationMessage(registrationCode, publicKeyRSA) if err != nil { - globals.Log.ERROR.Printf( - "Register: Unable to contact Registration Server! %s", err) + globals.Log.ERROR.Printf("Register: Unable to send registration message: %+v", err) return id.ZeroID, err } - if response.Error != "" { - globals.Log.ERROR.Printf("Register: %s", response.Error) - return id.ZeroID, errors.New(response.Error) - } - regHash = response.ClientSignedByServer.Hash - regR = response.ClientSignedByServer.R - regS = response.ClientSignedByServer.S - // Disconnect from regServer here since it will not be needed - (cl.comm).(*io.Messaging).Comms.Disconnect(cl.ndf.Registration.Address) } - fmt.Println("passed reg") + globals.Log.INFO.Println("Register: successfully passed Registration message") + + // Initialise blake2b hash for transmission keys and sha256 for reception + // keys + transmissionHash, _ := hash.NewCMixHash() + receptionHash := sha256.New() + // Loop over all Servers + globals.Log.INFO.Println("Register: Requesting nonces") for i := range cl.ndf.Gateways { gwID := id.NewNodeFromBytes(cl.ndf.Nodes[i].ID).NewGateway() - // Send signed public key and salt for UserID to Server - nonceResponse, err := (cl.comm).(*io.Messaging).Comms. - SendRequestNonceMessage(gwID, - &pb.NonceRequest{ - Salt: salt, - Client: &pb.DSAPublicKey{ - Y: publicKey.GetKey().Bytes(), - P: params.GetP().Bytes(), - Q: params.GetQ().Bytes(), - G: params.GetG().Bytes(), - }, - ClientSignedByServer: &pb.DSASignature{ - Hash: regHash, - R: regR, - S: regS, - }, - }) + // Request nonce message from gateway + globals.Log.INFO.Printf("Register: Requesting nonce from gateway %v/%v", i, len(cl.ndf.Gateways)) + nonce, dhPub, err := cl.requestNonce(salt, regHash, publicKeyDH, publicKeyRSA, privateKeyRSA, gwID) if err != nil { - globals.Log.ERROR.Printf( - "Register: Unable to request nonce! %s", - err) + globals.Log.ERROR.Printf("Register: Failed requesting nonce from gateway: %+v", err) return id.ZeroID, err } - if nonceResponse.Error != "" { - globals.Log.ERROR.Printf("Register: %s", nonceResponse.Error) - return id.ZeroID, errors.New(nonceResponse.Error) - } - // Use Client keypair to sign Server nonce - nonce := nonceResponse.Nonce - sig, err := privateKey.Sign(nonce, rand.Reader) - if err != nil { - globals.Log.ERROR.Printf( - "Register: Unable to sign nonce! %s", err) - return id.ZeroID, err - } + // Load server DH pubkey + serverPubDH := cmixGrp.NewIntFromBytes(dhPub) - // Send signed nonce to Server - // TODO: This returns a receipt that can be used to speed up registration - confirmResponse, err := (cl.comm).(*io.Messaging).Comms. - SendConfirmNonceMessage(gwID, - &pb.DSASignature{ - Hash: nonce, - R: sig.R.Bytes(), - S: sig.S.Bytes(), - }) + // Confirm received nonce + globals.Log.INFO.Println("Register: Confirming received nonce") + err = cl.confirmNonce(UID.Bytes(), nonce, privateKeyRSA, gwID) if err != nil { - globals.Log.ERROR.Printf( - "Register: Unable to send signed nonce! %s", err) + globals.Log.ERROR.Printf("Register: Unable to confirm nonce: %+v", err) return id.ZeroID, err } - if confirmResponse.Error != "" { - globals.Log.ERROR.Printf( - "Register: %s", confirmResponse.Error) - return id.ZeroID, errors.New(confirmResponse.Error) - } - - // Append Server public key - serverPublicKeys = append(serverPublicKeys, - signature.ReconstructPublicKey(signature. - CustomDSAParams( - large.NewIntFromBytes(confirmResponse.Server.GetP()), - large.NewIntFromBytes(confirmResponse.Server.GetQ()), - large.NewIntFromBytes(confirmResponse.Server.GetG())), - large.NewIntFromBytes(confirmResponse.Server.GetY()))) - - } - - // Initialise blake2b hash for transmission keys and sha256 for reception - // keys - transmissionHash, _ := hash.NewCMixHash() - receptionHash := sha256.New() - - // Loop through all the server public keys - for itr, publicKey := range serverPublicKeys { - - nodeID := *cl.topology.GetNodeAtIndex(itr) + nodeID := *cl.topology.GetNodeAtIndex(i) nk[nodeID] = user.NodeKeys{ TransmissionKey: registration.GenerateBaseKey(cmixGrp, - publicKey, privateKey, transmissionHash), - ReceptionKey: registration.GenerateBaseKey(cmixGrp, publicKey, - privateKey, receptionHash), + serverPubDH, privateKeyDH, transmissionHash), + ReceptionKey: registration.GenerateBaseKey(cmixGrp, serverPubDH, + privateKeyDH, receptionHash), } receptionHash.Reset() @@ -418,10 +322,10 @@ func (cl *Client) Register(preCan bool, registrationCode, nick, email string) (* u.Email = email // Create the user session - nus := user.NewSession(cl.storage, u, nk, publicKey, privateKey, cmixGrp, e2eGrp) + newSession := user.NewSession(cl.storage, u, nk, publicKeyRSA, privateKeyRSA, publicKeyDH, privateKeyDH, cmixGrp, e2eGrp) // Store the user session - errStore := nus.StoreSession() + errStore := newSession.StoreSession() // FIXME If we have an error here, the session that gets created doesn't get immolated. // Immolation should happen in a deferred call instead. @@ -433,15 +337,177 @@ func (cl *Client) Register(preCan bool, registrationCode, nick, email string) (* return id.ZeroID, err } - err = nus.Immolate() + err = newSession.Immolate() if err != nil { globals.Log.ERROR.Printf("Error on immolate: %+v", err) } - nus = nil + newSession = nil return UID, nil } +// precannedRegister is a helper function for Register +// It handles the precanned registration case +func (cl *Client) precannedRegister(registrationCode, nick string, + nk map[id.Node]user.NodeKeys) (*user.User, *id.User, map[id.Node]user.NodeKeys, error) { + var successLook bool + var UID *id.User + var u *user.User + var err error + + UID, successLook = user.Users.LookupUser(registrationCode) + + globals.Log.DEBUG.Printf("UID: %+v, success: %+v", UID, successLook) + + if !successLook { + return nil, nil, nil, errors.New("precannedRegister: could not register due to invalid HUID") + } + + var successGet bool + u, successGet = user.Users.GetUser(UID) + + if !successGet { + err = errors.New("precannedRegister: could not register due to ID lookup failure") + return nil, nil, nil, err + } + + if nick != "" { + u.Nick = nick + } + + nodekeys, successKeys := user.Users.LookupKeys(u.User) + + if !successKeys { + err = errors.New("precannedRegister: could not register due to missing user keys") + return nil, nil, nil, err + } + + for i := 0; i < len(cl.ndf.Gateways); i++ { + nk[*cl.topology.GetNodeAtIndex(i)] = *nodekeys + } + return u, UID, nk, nil +} + +// sendRegistrationMessage is a helper for the Register function +// It sends a registration message and returns the registration hash +func (cl *Client) sendRegistrationMessage(registrationCode string, + publicKeyRSA *rsa.PublicKey) ([]byte, error) { + regHash := make([]byte, 0) + // Send registration code and public key to RegistrationServer + response, err := (cl.comm).(*io.Messaging).Comms. + SendRegistrationMessage(io.ConnAddr(PermissioningAddrID), + &pb.UserRegistration{ + RegistrationCode: registrationCode, + ClientRSAPubKey: string(rsa.CreatePublicKeyPem(publicKeyRSA)), + }) + if err != nil { + err = errors.New(fmt.Sprintf( + "sendRegistrationMessage: Unable to contact Registration Server! %s", err)) + return nil, err + } + if response.Error != "" { + err = errors.New(fmt.Sprintf("sendRegistrationMessage: error handing message: %s", response.Error)) + return nil, err + } + regHash = response.ClientSignedByServer.Signature + // Disconnect from regServer here since it will not be needed + (cl.comm).(*io.Messaging).Comms.Disconnect(cl.ndf.Registration.Address) + return regHash, nil +} + +// requestNonce is a helper for the Register function +// It sends a request nonce message containing the client's keys for signing +// Returns nonce if successful +func (cl *Client) requestNonce(salt, regHash []byte, + publicKeyDH *cyclic.Int, publicKeyRSA *rsa.PublicKey, + privateKeyRSA *rsa.PrivateKey, gwID *id.Gateway) ([]byte, []byte, error) { + dhPub := publicKeyDH.Bytes() + sha := crypto.SHA256 + opts := rsa.NewDefaultOptions() + opts.Hash = sha + h := sha.New() + h.Write(dhPub) + data := h.Sum(nil) + fmt.Println(data) + // Sign DH pubkey + rng := csprng.NewSystemRNG() + signed, err := rsa.Sign(rng, privateKeyRSA, sha, data, opts) + if err != nil { + return nil, nil, err + } + + // Send signed public key and salt for UserID to Server + nonceResponse, err := (cl.comm).(*io.Messaging).Comms. + SendRequestNonceMessage(gwID, + &pb.NonceRequest{ + Salt: salt, + ClientRSAPubKey: string(rsa.CreatePublicKeyPem(publicKeyRSA)), + ClientSignedByServer: &pb.RSASignature{ + Signature: regHash, + }, + ClientDHPubKey: publicKeyDH.Bytes(), + RequestSignature: &pb.RSASignature{ + Signature: signed, + }, + }) // TODO: modify this to return server DH + if err != nil { + err := errors.New(fmt.Sprintf( + "requestNonce: Unable to request nonce! %s", err)) + return nil, nil, err + } + if nonceResponse.Error != "" { + err := errors.New(fmt.Sprintf("requestNonce: nonceResponse error: %s", nonceResponse.Error)) + return nil, nil, err + } + + // Use Client keypair to sign Server nonce + return nonceResponse.Nonce, nonceResponse.DHPubKey, nil + +} + +// confirmNonce is a helper for the Register function +// It signs a nonce and sends it for confirmation +// Returns nil if successful, error otherwise +func (cl *Client) confirmNonce(UID, nonce []byte, + privateKeyRSA *rsa.PrivateKey, gwID *id.Gateway) error { + sha := crypto.SHA256 + opts := rsa.NewDefaultOptions() + opts.Hash = sha + h := sha.New() + h.Write(nonce) + data := h.Sum(nil) + + // Hash nonce & sign + sig, err := rsa.Sign(rand.Reader, privateKeyRSA, sha, data, opts) + if err != nil { + globals.Log.ERROR.Printf( + "Register: Unable to sign nonce! %s", err) + return err + } + + // Send signed nonce to Server + // TODO: This returns a receipt that can be used to speed up registration + msg := &pb.RequestRegistrationConfirmation{ + UserID: UID, + NonceSignedByClient: &pb.RSASignature{ + Signature: sig, + }, + } + confirmResponse, err := (cl.comm).(*io.Messaging).Comms. + SendConfirmNonceMessage(gwID, msg) + if err != nil { + err := errors.New(fmt.Sprintf( + "confirmNonce: Unable to send signed nonce! %s", err)) + return err + } + if confirmResponse.Error != "" { + err := errors.New(fmt.Sprintf( + "confirmNonce: Error confirming nonce: %s", confirmResponse.Error)) + return err + } + return nil +} + // LoadSession loads the session object for the UID func (cl *Client) Login(UID *id.User) (string, error) { session, err := user.LoadSession(cl.storage, UID) @@ -453,6 +519,10 @@ func (cl *Client) Login(UID *id.User) (string, error) { return "", err } + if session == nil { + return "", errors.New("Unable to load session: " + err.Error()) + } + cl.session = session return cl.session.GetCurrentUser().Nick, nil } @@ -591,8 +661,8 @@ func (cl *Client) registerForUserDiscovery(emailAddress string) error { return err } - publicKey := cl.session.GetPublicKey() - publicKeyBytes := publicKey.GetKey().LeftpadBytes(256) + publicKey := cl.session.GetRSAPublicKey() + publicKeyBytes := rsa.CreatePublicKeyPem(publicKey) return bots.Register(valueType, emailAddress, publicKeyBytes) } @@ -651,8 +721,8 @@ func (cl *Client) registerUserE2E(partnerID *id.User, // Create user private key and partner public key // in the group - privKey := cl.session.GetPrivateKey() - privKeyCyclic := grp.NewIntFromLargeInt(privKey.GetKey()) + privKey := cl.session.GetDHPrivateKey() + privKeyCyclic := grp.NewIntFromLargeInt(privKey.GetLargeInt()) partnerPubKeyCyclic := grp.NewIntFromBytes(partnerPubKey) // Generate baseKey diff --git a/api/client_test.go b/api/client_test.go index 6c6a825e520e37fa4907f854a0861383c54a63e3..21839c58048681a5f76a00d9bdef881331696690 100644 --- a/api/client_test.go +++ b/api/client_test.go @@ -23,7 +23,7 @@ import ( "gitlab.com/elixxir/crypto/e2e" "gitlab.com/elixxir/crypto/hash" "gitlab.com/elixxir/crypto/large" - "gitlab.com/elixxir/crypto/signature" + "gitlab.com/elixxir/crypto/signature/rsa" "gitlab.com/elixxir/primitives/circuit" "gitlab.com/elixxir/primitives/format" "gitlab.com/elixxir/primitives/id" @@ -32,6 +32,8 @@ import ( "time" ) +var TestKeySize = 768 + func TestRegistrationGob(t *testing.T) { // Get a Client testClient, err := NewClient(&globals.RamStorage{}, "", def) @@ -188,24 +190,23 @@ func TestRegisterUserE2E(t *testing.T) { t.Error(err) } + rng := csprng.NewSystemRNG() cmixGrp, e2eGrp := getGroups() userID := id.NewUserFromUint(18, t) partner := id.NewUserFromUint(14, t) - params := signature.CustomDSAParams( - cmixGrp.GetP(), - cmixGrp.GetQ(), - cmixGrp.GetG()) - rng := csprng.NewSystemRNG() - myPrivKey := params.PrivateKeyGen(rng) - myPrivKeyCyclic := cmixGrp.NewIntFromLargeInt(myPrivKey.GetKey()) - myPubKey := myPrivKey.PublicKeyGen() - partnerPrivKey := params.PrivateKeyGen(rng) - partnerPubKey := partnerPrivKey.PublicKeyGen() - partnerPubKeyCyclic := cmixGrp.NewIntFromLargeInt(partnerPubKey.GetKey()) + + myPrivKeyCyclic := cmixGrp.RandomCoprime(cmixGrp.NewMaxInt()) + myPubKeyCyclic := cmixGrp.ExpG(myPrivKeyCyclic, cmixGrp.NewMaxInt()) + + partnerPubKeyCyclic := cmixGrp.RandomCoprime(cmixGrp.NewMaxInt()) + + privateKeyRSA, _ := rsa.GenerateKey(rng, TestKeySize) + publicKeyRSA := rsa.PublicKey{PublicKey: privateKeyRSA.PublicKey} myUser := &user.User{User: userID, Nick: "test"} session := user.NewSession(testClient.storage, - myUser, make(map[id.Node]user.NodeKeys), myPubKey, myPrivKey, cmixGrp, e2eGrp) + myUser, make(map[id.Node]user.NodeKeys), &publicKeyRSA, privateKeyRSA, + myPubKeyCyclic, myPrivKeyCyclic, cmixGrp, e2eGrp) testClient.session = session fmt.Println("runn") @@ -280,22 +281,21 @@ func TestRegisterUserE2E_CheckAllKeys(t *testing.T) { cmixGrp, e2eGrp := getGroups() userID := id.NewUserFromUint(18, t) partner := id.NewUserFromUint(14, t) - params := signature.CustomDSAParams( - cmixGrp.GetP(), - cmixGrp.GetQ(), - cmixGrp.GetG()) + rng := csprng.NewSystemRNG() - myPrivKey := params.PrivateKeyGen(rng) - myPrivKeyCyclic := cmixGrp.NewIntFromLargeInt(myPrivKey.GetKey()) - myPubKey := myPrivKey.PublicKeyGen() - partnerPrivKey := params.PrivateKeyGen(rng) - partnerPubKey := partnerPrivKey.PublicKeyGen() - partnerPubKeyCyclic := cmixGrp.NewIntFromLargeInt(partnerPubKey.GetKey()) + myPrivKeyCyclic := cmixGrp.RandomCoprime(cmixGrp.NewMaxInt()) + myPubKeyCyclic := cmixGrp.ExpG(myPrivKeyCyclic, cmixGrp.NewMaxInt()) + + partnerPrivKeyCyclic := cmixGrp.RandomCoprime(cmixGrp.NewMaxInt()) + partnerPubKeyCyclic := cmixGrp.ExpG(partnerPrivKeyCyclic, cmixGrp.NewMaxInt()) + + privateKeyRSA, _ := rsa.GenerateKey(rng, TestKeySize) + publicKeyRSA := rsa.PublicKey{PublicKey: privateKeyRSA.PublicKey} myUser := &user.User{User: userID, Nick: "test"} session := user.NewSession(testClient.storage, - myUser, make(map[id.Node]user.NodeKeys), myPubKey, - myPrivKey, cmixGrp, e2eGrp) + myUser, make(map[id.Node]user.NodeKeys), &publicKeyRSA, + privateKeyRSA, myPubKeyCyclic, myPrivKeyCyclic, cmixGrp, e2eGrp) testClient.session = session @@ -417,80 +417,99 @@ func TestRegisterUserE2E_CheckAllKeys(t *testing.T) { } } -// FIXME Reinstate tests for the UDB api -//var ListenCh chan *format.Message -//var lastmsg string - -//type dummyMessaging struct { -// listener chan *format.Message -//} - -// SendMessage to the server -//func (d *dummyMessaging) SendMessage(recipientID id.User, -// message string) error { -// jww.INFO.Printf("Sending: %s", message) -// lastmsg = message -// return nil -//} - -// Listen for messages from a given sender -//func (d *dummyMessaging) Listen(senderID id.User) chan *format.Message { -// return d.listener -//} - -// StopListening to a given switchboard (closes and deletes) -//func (d *dummyMessaging) StopListening(listenerCh chan *format.Message) {} - -// MessageReceiver thread to get new messages -//func (d *dummyMessaging) MessageReceiver(delay time.Duration) {} - -//var pubKeyBits []string -//var keyFingerprint string -//var pubKey []byte - -// SendMsg puts a fake udb response message on the channel -//func SendMsg(msg string) { -// m, _ := format.NewMessage(13, 1, msg) -// ListenCh <- &m[0] -//} - -//func TestRegisterPubKeyByteLen(t *testing.T) { -// ListenCh = make(chan *format.Message, 100) -// io.Messaging = &dummyMessaging{ -// switchboard: ListenCh, -// } -// pubKeyBits = []string{ -// "S8KXBczy0jins9uS4LgBPt0bkFl8t00MnZmExQ6GcOcu8O7DKgAsNz" + -// "LU7a+gMTbIsS995IL/kuFF8wcBaQJBY23095PMSQ/nMuetzhk9HdXxrGIiKBo3C/n4SClp" + -// "q4H+PoF9XziEVKua8JxGM2o83KiCK3tNUpaZbAAElkjueY4=", -// "8Lg/eoeKGgPlleTYfO3JyGfnwBtLi73ti0h2dBQWW94JTqTQDr+z" + -// "xVpLzdgTt+87TkAl0yXu9mOUXqGJ+51lTcRlIdIpWpfgUbibdRme8IThg0RNCF31ESKCts" + -// "o8gJ8mSVljIXxrC+Uuoi+Gl1LNN5nPARykatx0Y70xNdJd2BQ=", -// } -// pubKey = make([]byte, 256) -// for i := range pubKeyBits { -// pubkeyBytes, _ := base64.StdEncoding.DecodeString(pubKeyBits[i]) -// for j := range pubkeyBytes { -// pubKey[j+i*128] = pubkeyBytes[j] -// } -// } -// -// keyFingerprint = "8oKh7TYG4KxQcBAymoXPBHSD/uga9pX3Mn/jKhvcD8M=" -// //SendMsg("SEARCH blah@privategrity.com NOTFOUND") -// SendMsg(fmt.Sprintf("GETKEY %s NOTFOUND", keyFingerprint)) -// SendMsg("PUSHKEY ACK NEED 128") -// SendMsg(fmt.Sprintf("PUSHKEY COMPLETE %s", keyFingerprint)) -// SendMsg("REGISTRATION COMPLETE") -// -// err := bots.Register("EMAIL", "blah@privategrity.com", pubKey) -// -// if err != nil { -// t.Errorf("Unexpected error: %s", err.Error()) -// } -// if len(lastmsg) != 81 { -// t.Errorf("Message wrong length: %d v. expected 81", len(lastmsg)) -// } -//} +// Test happy path for precannedRegister +func TestClient_precannedRegister(t *testing.T) { + testClient, err := NewClient(&globals.RamStorage{}, "", def) + if err != nil { + t.Error(err) + } + + err = testClient.Connect() + if err != nil { + t.Error(err) + } + + nk := make(map[id.Node]user.NodeKeys) + + _, _, nk, err = testClient.precannedRegister("UAV6IWD6", "tony_johns", nk) + if err != nil { + t.Errorf("Error during precannedRegister: %+v", err) + } +} + +// Test happy path for sendRegistrationMessage +func TestClient_sendRegistrationMessage(t *testing.T) { + testClient, err := NewClient(&globals.RamStorage{}, "", def) + if err != nil { + t.Error(err) + } + + err = testClient.Connect() + if err != nil { + t.Error(err) + } + + rng := csprng.NewSystemRNG() + privateKeyRSA, _ := rsa.GenerateKey(rng, TestKeySize) + publicKeyRSA := rsa.PublicKey{PublicKey: privateKeyRSA.PublicKey} + + _, err = testClient.sendRegistrationMessage("UAV6IWD6", &publicKeyRSA) + if err != nil { + t.Errorf("Error during sendRegistrationMessage: %+v", err) + } +} + +// Test happy path for requestNonce +func TestClient_requestNonce(t *testing.T) { + cmixGrp, _ := getGroups() + privateKeyDH := cmixGrp.RandomCoprime(cmixGrp.NewMaxInt()) + publicKeyDH := cmixGrp.ExpG(privateKeyDH, cmixGrp.NewMaxInt()) + rng := csprng.NewSystemRNG() + privateKeyRSA, _ := rsa.GenerateKey(rng, TestKeySize) + publicKeyRSA := rsa.PublicKey{PublicKey: privateKeyRSA.PublicKey} + + testClient, err := NewClient(&globals.RamStorage{}, "", def) + if err != nil { + t.Error(err) + } + + err = testClient.Connect() + if err != nil { + t.Error(err) + } + + salt := make([]byte, 256) + _, err = csprng.NewSystemRNG().Read(salt) + if err != nil { + t.Errorf("Unable to generate salt! %s", err) + } + + gwID := id.NewNodeFromBytes(testClient.ndf.Nodes[0].ID).NewGateway() + _, _, err = testClient.requestNonce(salt, []byte("test"), publicKeyDH, &publicKeyRSA, privateKeyRSA, gwID) + if err != nil { + t.Errorf("Error during requestNonce: %+v", err) + } +} + +// Test happy path for confirmNonce +func TestClient_confirmNonce(t *testing.T) { + testClient, err := NewClient(&globals.RamStorage{}, "", def) + if err != nil { + t.Error(err) + } + + err = testClient.Connect() + if err != nil { + t.Error(err) + } + rng := csprng.NewSystemRNG() + privateKeyRSA, _ := rsa.GenerateKey(rng, TestKeySize) + gwID := id.NewNodeFromBytes(testClient.ndf.Nodes[0].ID).NewGateway() + err = testClient.confirmNonce([]byte("user"), []byte("test"), privateKeyRSA, gwID) + if err != nil { + t.Errorf("Error during confirmNonce: %+v", err) + } +} func getGroups() (*cyclic.Group, *cyclic.Group) { diff --git a/api/mockserver.go b/api/mockserver.go index abeb89278e4ee7f74f9bac3dad43b70efd3c19a6..89a41be371ae9ceecf2e748f29e08737b8ff8c5a 100644 --- a/api/mockserver.go +++ b/api/mockserver.go @@ -11,6 +11,7 @@ import ( "gitlab.com/elixxir/client/cmixproto" "gitlab.com/elixxir/client/parse" pb "gitlab.com/elixxir/comms/mixmessages" + "gitlab.com/elixxir/crypto/cyclic" "gitlab.com/elixxir/crypto/large" "gitlab.com/elixxir/primitives/id" "sync" @@ -77,16 +78,11 @@ func (m *TestInterface) PutMessage(msg *pb.Slot) bool { return true } -func (m *TestInterface) ConfirmNonce(message *pb.DSASignature) (*pb.RegistrationConfirmation, error) { +func (m *TestInterface) ConfirmNonce(message *pb.RequestRegistrationConfirmation) (*pb.RegistrationConfirmation, error) { regConfirmation := &pb.RegistrationConfirmation{ - Server: &pb.DSAPublicKey{}, + ClientSignedByServer: &pb.RSASignature{}, } - regConfirmation.Server.P = large.NewInt(1).Bytes() - regConfirmation.Server.Q = large.NewInt(1).Bytes() - regConfirmation.Server.G = large.NewInt(1).Bytes() - regConfirmation.Server.Y = large.NewInt(1).Bytes() - return regConfirmation, nil } @@ -101,14 +97,41 @@ func (s *MockRegistration) RegisterNode(ID []byte, } // Registers a user and returns a signed public key -func (s *MockRegistration) RegisterUser(registrationCode string, - Y, P, Q, G []byte) (hash, R, S []byte, err error) { - return nil, nil, nil, nil +func (s *MockRegistration) RegisterUser(registrationCode, + key string) (hash []byte, err error) { + return nil, nil +} + +func getDHPubKey() *cyclic.Int { + cmixGrp := cyclic.NewGroup( + large.NewIntFromString("9DB6FB5951B66BB6FE1E140F1D2CE5502374161FD6538DF1648218642F0B5C48"+ + "C8F7A41AADFA187324B87674FA1822B00F1ECF8136943D7C55757264E5A1A44F"+ + "FE012E9936E00C1D3E9310B01C7D179805D3058B2A9F4BB6F9716BFE6117C6B5"+ + "B3CC4D9BE341104AD4A80AD6C94E005F4B993E14F091EB51743BF33050C38DE2"+ + "35567E1B34C3D6A5C0CEAA1A0F368213C3D19843D0B4B09DCB9FC72D39C8DE41"+ + "F1BF14D4BB4563CA28371621CAD3324B6A2D392145BEBFAC748805236F5CA2FE"+ + "92B871CD8F9C36D3292B5509CA8CAA77A2ADFC7BFD77DDA6F71125A7456FEA15"+ + "3E433256A2261C6A06ED3693797E7995FAD5AABBCFBE3EDA2741E375404AE25B", 16), + large.NewIntFromString("5C7FF6B06F8F143FE8288433493E4769C4D988ACE5BE25A0E24809670716C613"+ + "D7B0CEE6932F8FAA7C44D2CB24523DA53FBE4F6EC3595892D1AA58C4328A06C4"+ + "6A15662E7EAA703A1DECF8BBB2D05DBE2EB956C142A338661D10461C0D135472"+ + "085057F3494309FFA73C611F78B32ADBB5740C361C9F35BE90997DB2014E2EF5"+ + "AA61782F52ABEB8BD6432C4DD097BC5423B285DAFB60DC364E8161F4A2A35ACA"+ + "3A10B1C4D203CC76A470A33AFDCBDD92959859ABD8B56E1725252D78EAC66E71"+ + "BA9AE3F1DD2487199874393CD4D832186800654760E1E34C09E4D155179F9EC0"+ + "DC4473F996BDCE6EED1CABED8B6F116F7AD9CF505DF0F998E34AB27514B0FFE7", 16), + large.NewIntFromString("F2C3119374CE76C9356990B465374A17F23F9ED35089BD969F61C6DDE9998C1F", 16)) + + dh := cmixGrp.RandomCoprime(cmixGrp.NewMaxInt()) + return cmixGrp.ExpG(dh, cmixGrp.NewMaxInt()) } // Pass-through for Registration Nonce Communication func (m *TestInterface) RequestNonce(message *pb.NonceRequest) (*pb.Nonce, error) { - return &pb.Nonce{}, nil + dh := getDHPubKey().Bytes() + return &pb.Nonce{ + DHPubKey: dh, + }, nil } // Mock dummy storage interface for testing. diff --git a/bots/bots_test.go b/bots/bots_test.go index 88a7bafc0ba67a78dcd002d0fd05cfb016f2c9ad..ad22272a5d94dabe59f0d3b94a5ba87b73bb5c00 100644 --- a/bots/bots_test.go +++ b/bots/bots_test.go @@ -70,7 +70,7 @@ func TestMain(m *testing.M) { cmixGrp, e2eGrp := getGroups() fakeSession := user.NewSession(&globals.RamStorage{}, - u, nil, nil, nil, cmixGrp, e2eGrp) + u, nil, nil, nil, nil, nil, cmixGrp, e2eGrp) fakeComm := &dummyMessaging{ listener: ListenCh, } diff --git a/cmd/root.go b/cmd/root.go index 7e761275eab0b0ffe2644889d69a8050c724091b..2b0caf60f1fdd4cd27a39b060db2c9c54b1f3f37 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -36,16 +36,13 @@ import ( var verbose bool var userId uint64 var destinationUserId uint64 -var gwAddresses []string var message string var sessionFile string var dummyFrequency float64 var noBlockingTransmission bool var rateLimiting uint32 var showVer bool -var gwCertPath string var registrationCertPath string -var registrationAddr string var registrationCode string var userEmail string var userNick string @@ -56,6 +53,7 @@ var skipNDFVerification bool var ndfRegistration []string var ndfUDB []string var ndfPubKey string +var noTLS bool // Execute adds all child commands to the root command and sets flags // appropriately. This is called by main.main(). It only needs to @@ -381,8 +379,14 @@ var rootCmd = &cobra.Command{ cryptoType = parse.E2E } - // Only send a message if we have a message to send (except dummy messages) - recipientId := id.NewUserFromUints(&[4]uint64{0, 0, 0, destinationUserId}) + var recipientId *id.User + + if destinationUserId == 0 { + recipientId = userID + } else { + recipientId = id.NewUserFromUints(&[4]uint64{0, 0, 0, destinationUserId}) + } + if message != "" { // Get the recipient's nick recipientNick := "" @@ -504,20 +508,10 @@ func init() { rootCmd.PersistentFlags().Uint64VarP(&userId, "userid", "i", 0, "ID to sign in as") - rootCmd.PersistentFlags().StringSliceVarP(&gwAddresses, "gwaddresses", - "g", make([]string, 0), "Gateway addresses:port for message sending, "+ - "comma-separated") - rootCmd.PersistentFlags().StringVarP(&gwCertPath, "gwcertpath", "c", "", - "Path to the certificate file for connecting to gateway using TLS") rootCmd.PersistentFlags().StringVarP(®istrationCertPath, "registrationcertpath", "r", "", "Path to the certificate file for connecting to registration server"+ " using TLS") - rootCmd.PersistentFlags().StringVarP(®istrationAddr, - "registrationaddr", "a", - "", - "Address:Port for connecting to registration server"+ - " using TLS") rootCmd.PersistentFlags().StringVarP(®istrationCode, "regcode", "e", @@ -585,6 +579,9 @@ func init() { rootCmd.PersistentFlags().StringSliceVarP(&keyParams, "keyParams", "", make([]string, 0), "Define key generation parameters. Pass values in comma separated list"+ " in the following order: MinKeys,MaxKeys,NumRekeys,TTLScalar,MinNumKeys") + + rootCmd.Flags().BoolVarP(&noTLS, "noTLS", "", false, + "Set to ignore TLS") } // initConfig reads in config file and ENV variables if set. @@ -637,4 +634,14 @@ func overwriteNDF(n *ndf.NetworkDefinition) { globals.Log.WARN.Println("Overwrote UDB values in the " + "NetworkDefinition from the commandline") } + + if noTLS { + for i := 0; i < len(n.Nodes); i++ { + n.Nodes[i].TlsCertificate = "" + } + n.Registration.TlsCertificate = "" + for i := 0; i < len(n.Gateways); i++ { + n.Gateways[i].TlsCertificate = "" + } + } } diff --git a/crypto/encryptdecrypt_test.go b/crypto/encryptdecrypt_test.go index 4285747ec311fb5591cdeeefab589f9b5e1c5ec9..5ec2bdc6db91ac06b1680be054c67f2c24d7201a 100644 --- a/crypto/encryptdecrypt_test.go +++ b/crypto/encryptdecrypt_test.go @@ -81,7 +81,7 @@ func setup() { } session = user.NewSession(nil, u, nkMap, - nil, nil, cmixGrp, e2eGrp) + nil, nil, nil, nil, cmixGrp, e2eGrp) } func TestMain(m *testing.M) { @@ -124,9 +124,9 @@ func TestFullEncryptDecrypt(t *testing.T) { // This block imitates what the server does during the realtime payloadA := cmixGrp.NewIntFromBytes(encMsg.GetPayloadA()) payloadB := cmixGrp.NewIntFromBytes(encMsg.GetPayloadB()) - // Multiply payloadA by its server key + // Multiply payloadA and associated data by serverPayloadBkey cmixGrp.Mul(payloadA, serverPayloadAKey, payloadA) - // Multiply payloadB by its server key + // Multiply payloadB data only by serverPayloadAkey cmixGrp.Mul(payloadB, serverPayloadBKey, payloadB) decMsg := format.NewMessage() @@ -186,17 +186,17 @@ func TestFullEncryptDecrypt_Unsafe(t *testing.T) { // This block imitates what the server does during the realtime var encryptedNet *pb.Slot { - payloadA := cmixGrp.NewIntFromBytes(encMsg.GetPayloadA()) - payloadB := cmixGrp.NewIntFromBytes(encMsg.GetPayloadB()) - // Multiply payloadA by transmission key - cmixGrp.Mul(payloadA, serverPayloadAKey, payloadA) - // Multiply payloadB by transmission key - cmixGrp.Mul(payloadB, serverPayloadBKey, payloadB) + payload := cmixGrp.NewIntFromBytes(encMsg.GetPayloadA()) + assocData := cmixGrp.NewIntFromBytes(encMsg.GetPayloadB()) + // Multiply payload and associated data by transmission key only + cmixGrp.Mul(payload, serverPayloadAKey, payload) + // Multiply associated data only by transmission key + cmixGrp.Mul(assocData, serverPayloadBKey, assocData) encryptedNet = &pb.Slot{ SenderID: sender.Bytes(), Salt: salt, - PayloadA: payloadA.LeftpadBytes(uint64(format.PayloadLen)), - PayloadB: payloadB.LeftpadBytes(uint64(format.PayloadLen)), + PayloadA: payload.LeftpadBytes(uint64(format.PayloadLen)), + PayloadB: assocData.LeftpadBytes(uint64(format.PayloadLen)), } } diff --git a/glide.yaml b/glide.yaml index 1819086cd5dc7cbd637c11919299e54f7200a25e..404fd85339e3572c75cf665f48a8c31f6d05e063 100644 --- a/glide.yaml +++ b/glide.yaml @@ -4,15 +4,15 @@ import: version: master vcs: git - package: gitlab.com/elixxir/crypto - version: release + version: master repo: git@gitlab.com:elixxir/crypto vcs: git - package: gitlab.com/elixxir/comms - version: release + version: master repo: git@gitlab.com:elixxir/comms vcs: git - package: gitlab.com/elixxir/primitives - version: release + version: master repo: git@gitlab.com:elixxir/primitives vcs: git - package: github.com/mitchellh/go-homedir diff --git a/rekey/rekey.go b/rekey/rekey.go index 7f369a2c1fc8a3811f3b24578b33e790b63fdf35..e749340d822d094ad789ff900f2f61809bc40e04 100644 --- a/rekey/rekey.go +++ b/rekey/rekey.go @@ -2,7 +2,6 @@ package rekey import ( "bytes" - "crypto/rand" "fmt" "gitlab.com/elixxir/client/cmixproto" "gitlab.com/elixxir/client/globals" @@ -14,7 +13,6 @@ import ( "gitlab.com/elixxir/crypto/diffieHellman" "gitlab.com/elixxir/crypto/e2e" "gitlab.com/elixxir/crypto/hash" - "gitlab.com/elixxir/crypto/signature" "gitlab.com/elixxir/primitives/circuit" "gitlab.com/elixxir/primitives/format" "gitlab.com/elixxir/primitives/id" @@ -164,37 +162,36 @@ func rekeyProcess(rt rekeyType, partner *id.User, data []byte) error { // Add context to RekeyManager in case of RekeyTrigger var privKeyCyclic *cyclic.Int var pubKeyCyclic *cyclic.Int + var partnerPubKeyCyclic *cyclic.Int var baseKey *cyclic.Int - var pubKey *signature.DSAPublicKey if ctx == nil { if rt == RekeyTrigger { - params := signature.GetDefaultDSAParams() - privateKey := params.PrivateKeyGen(rand.Reader) - pubKey = privateKey.PublicKeyGen() - privKeyCyclic = grp.NewIntFromLargeInt(privateKey.GetKey()) + privKeyCyclic = grp.RandomCoprime(grp.NewInt(1)) + fmt.Println("Private key actual: ", privKeyCyclic.Text(16)) + pubKeyCyclic = grp.ExpG(privKeyCyclic, grp.NewInt(1)) // Get Current Partner Public Key from RekeyKeys - pubKeyCyclic = keys.CurrPubKey + partnerPubKeyCyclic = keys.CurrPubKey // Set new Own Private Key keys.NewPrivKey = privKeyCyclic } else { // Get Current Own Private Key from RekeyKeys privKeyCyclic = keys.CurrPrivKey // Get Partner New Public Key from data - pubKeyCyclic = grp.NewIntFromBytes(data) + partnerPubKeyCyclic = grp.NewIntFromBytes(data) // Set new Partner Public Key - keys.NewPubKey = pubKeyCyclic + keys.NewPubKey = partnerPubKeyCyclic } // Generate baseKey baseKey, _ = diffieHellman.CreateDHSessionKey( - pubKeyCyclic, + partnerPubKeyCyclic, privKeyCyclic, grp) ctx = &keyStore.RekeyContext{ BaseKey: baseKey, PrivKey: privKeyCyclic, - PubKey: pubKeyCyclic, + PubKey: partnerPubKeyCyclic, } if rt == RekeyTrigger { @@ -254,7 +251,7 @@ func rekeyProcess(rt rekeyType, partner *id.User, data []byte) error { // This ensures that the publicKey fits in a single message, which // is sent with E2E encryption using a send Rekey, and without padding return messaging.SendMessageNoPartition(session, topology, partner, parse.E2E, - pubKey.GetKey().LeftpadBytes(uint64(format.ContentsLen))) + pubKeyCyclic.LeftpadBytes(uint64(format.ContentsLen))) case Rekey: // Send rekey confirm message with hash of the baseKey h, _ := hash.NewCMixHash() diff --git a/rekey/rekey_test.go b/rekey/rekey_test.go index 6580a0f5e95fae24db97de64910c311d838d340e..3cffc7fb951b548bf780b029954592fbc5eda16e 100644 --- a/rekey/rekey_test.go +++ b/rekey/rekey_test.go @@ -2,6 +2,7 @@ package rekey import ( "bytes" + "fmt" "gitlab.com/elixxir/client/cmixproto" "gitlab.com/elixxir/client/globals" "gitlab.com/elixxir/client/keyStore" @@ -13,7 +14,7 @@ import ( "gitlab.com/elixxir/crypto/e2e" "gitlab.com/elixxir/crypto/hash" "gitlab.com/elixxir/crypto/large" - "gitlab.com/elixxir/crypto/signature" + "gitlab.com/elixxir/crypto/signature/rsa" "gitlab.com/elixxir/primitives/circuit" "gitlab.com/elixxir/primitives/id" "os" @@ -56,25 +57,22 @@ func TestMain(m *testing.M) { grp, e2eGrp := getGroups() user.InitUserRegistry(grp) - params := signature.CustomDSAParams( - grp.GetP(), - grp.GetQ(), - grp.GetG()) rng := csprng.NewSystemRNG() u := &user.User{ User: id.NewUserFromUints(&[4]uint64{0, 0, 0, 18}), Nick: "Bernie", } - myPrivKey := params.PrivateKeyGen(rng) - myPrivKeyCyclic := grp.NewIntFromLargeInt(myPrivKey.GetKey()) - myPubKey := myPrivKey.PublicKeyGen() + myPrivKeyCyclic := grp.RandomCoprime(grp.NewMaxInt()) + myPubKeyCyclic := grp.ExpG(myPrivKeyCyclic, grp.NewInt(1)) partnerID := id.NewUserFromUints(&[4]uint64{0, 0, 0, 12}) - partnerPrivKey := params.PrivateKeyGen(rng) - partnerPubKey := partnerPrivKey.PublicKeyGen() - partnerPubKeyCyclic := grp.NewIntFromLargeInt(partnerPubKey.GetKey()) + + partnerPubKeyCyclic := grp.RandomCoprime(grp.NewMaxInt()) + + privateKeyRSA, _ := rsa.GenerateKey(rng, 768) + publicKeyRSA := rsa.PublicKey{PublicKey: privateKeyRSA.PublicKey} session := user.NewSession(&globals.RamStorage{}, - u, nil, myPubKey, myPrivKey, grp, e2eGrp) + u, nil, &publicKeyRSA, privateKeyRSA, myPubKeyCyclic, myPrivKeyCyclic, grp, e2eGrp) ListenCh = make(chan []byte, 100) fakeComm := &dummyMessaging{ listener: ListenCh, @@ -146,13 +144,15 @@ func TestRekeyTrigger(t *testing.T) { grp := session.GetCmixGroup() actualPubKey := grp.NewIntFromBytes(value) privKey := session.GetRekeyManager().GetCtx(partnerID).PrivKey + fmt.Println("privKey: ", privKey.Text(16)) expectedPubKey := grp.NewInt(1) grp.ExpG(privKey, expectedPubKey) + fmt.Println("new pub key: ", value) if expectedPubKey.Cmp(actualPubKey) != 0 { t.Errorf("RekeyTrigger publicKey mismatch, expected %s,"+ - " got %s", expectedPubKey.Text(10), - actualPubKey.Text(10)) + " got %s", expectedPubKey.Text(16), + actualPubKey.Text(16)) } // Check that trying to send another rekeyTrigger message returns an error @@ -216,7 +216,7 @@ func TestRekeyConfirm(t *testing.T) { // Confirm that user Private key in Send Key Manager // differs from the one stored in session - if session.GetPrivateKey().GetKey().Cmp( + if session.GetDHPrivateKey().GetLargeInt().Cmp( session.GetKeyStore().GetSendManager(partnerID). GetPrivKey().GetLargeInt()) == 0 { t.Errorf("PrivateKey remained unchanged after Outgoing Rekey!") @@ -247,19 +247,14 @@ func TestRekey(t *testing.T) { km := session.GetKeyStore().GetSendManager(partnerID) // Generate new partner public key grp, _ := getGroups() - params := signature.CustomDSAParams( - grp.GetP(), - grp.GetQ(), - grp.GetG()) - rng := csprng.NewSystemRNG() - partnerPrivKey := params.PrivateKeyGen(rng) - partnerPubKey := partnerPrivKey.PublicKeyGen() + privKey := grp.RandomCoprime(grp.NewMaxInt()) + pubKey := grp.ExpG(privKey, grp.NewMaxInt()) // Test receiving a Rekey message msg := &parse.Message{ Sender: partnerID, TypedBody: parse.TypedBody{ MessageType: int32(cmixproto.Type_NO_TYPE), - Body: partnerPubKey.GetKey().Bytes(), + Body: pubKey.Bytes(), }, InferredType: parse.Rekey, Receiver: session.GetCurrentUser().User, @@ -291,12 +286,12 @@ func TestRekey(t *testing.T) { keys := rkm.GetKeys(partnerID) if keys.CurrPrivKey.GetLargeInt(). - Cmp(session.GetPrivateKey().GetKey()) == 0 { + Cmp(session.GetDHPrivateKey().GetLargeInt()) == 0 { t.Errorf("Own PrivateKey didn't update properly after both parties rekeys") } if keys.CurrPubKey.GetLargeInt(). - Cmp(partnerPubKey.GetKey()) != 0 { + Cmp(pubKey.GetLargeInt()) != 0 { t.Errorf("Partner PublicKey didn't update properly after both parties rekeys") } } diff --git a/user/session.go b/user/session.go index 43c8144e14f74d23c6343bb0aba34551858b6196..e6f792759c2fdfca666747e235d8979ca13732ed 100644 --- a/user/session.go +++ b/user/session.go @@ -15,7 +15,7 @@ import ( "gitlab.com/elixxir/client/globals" "gitlab.com/elixxir/client/keyStore" "gitlab.com/elixxir/crypto/cyclic" - "gitlab.com/elixxir/crypto/signature" + "gitlab.com/elixxir/crypto/signature/rsa" "gitlab.com/elixxir/primitives/circuit" "gitlab.com/elixxir/primitives/id" "gitlab.com/elixxir/primitives/switchboard" @@ -31,8 +31,10 @@ var ErrQuery = errors.New("element not in map") type Session interface { GetCurrentUser() (currentUser *User) GetKeys(topology *circuit.Circuit) []NodeKeys - GetPrivateKey() *signature.DSAPrivateKey - GetPublicKey() *signature.DSAPublicKey + GetRSAPrivateKey() *rsa.PrivateKey + GetRSAPublicKey() *rsa.PublicKey + GetDHPrivateKey() *cyclic.Int + GetDHPublicKey() *cyclic.Int GetCmixGroup() *cyclic.Group GetE2EGroup() *cyclic.Group GetLastMessageID() string @@ -59,16 +61,20 @@ type NodeKeys struct { // Creates a new Session interface for registration func NewSession(store globals.Storage, u *User, nk map[id.Node]NodeKeys, - publicKey *signature.DSAPublicKey, - privateKey *signature.DSAPrivateKey, + publicKeyRSA *rsa.PublicKey, + privateKeyRSA *rsa.PrivateKey, + publicKeyDH *cyclic.Int, + privateKeyDH *cyclic.Int, cmixGrp, e2eGrp *cyclic.Group) Session { // With an underlying Session data structure return Session(&SessionObj{ CurrentUser: u, Keys: nk, - PrivateKey: privateKey, - PublicKey: publicKey, + RSAPublicKey: publicKeyRSA, + RSAPrivateKey: privateKeyRSA, + DHPublicKey: publicKeyDH, + DHPrivateKey: privateKeyDH, CmixGrp: cmixGrp, E2EGrp: e2eGrp, InterfaceMap: make(map[string]interface{}), @@ -147,11 +153,13 @@ type SessionObj struct { // Currently authenticated user CurrentUser *User - Keys map[id.Node]NodeKeys - PrivateKey *signature.DSAPrivateKey - PublicKey *signature.DSAPublicKey - CmixGrp *cyclic.Group - E2EGrp *cyclic.Group + Keys map[id.Node]NodeKeys + RSAPrivateKey *rsa.PrivateKey + RSAPublicKey *rsa.PublicKey + DHPrivateKey *cyclic.Int + DHPublicKey *cyclic.Int + CmixGrp *cyclic.Group + E2EGrp *cyclic.Group // Last received message ID. Check messages after this on the gateway. LastMessageID string @@ -203,16 +211,28 @@ func (s *SessionObj) GetKeys(topology *circuit.Circuit) []NodeKeys { return keys } -func (s *SessionObj) GetPrivateKey() *signature.DSAPrivateKey { +func (s *SessionObj) GetRSAPrivateKey() *rsa.PrivateKey { s.LockStorage() defer s.UnlockStorage() - return s.PrivateKey + return s.RSAPrivateKey } -func (s *SessionObj) GetPublicKey() *signature.DSAPublicKey { +func (s *SessionObj) GetRSAPublicKey() *rsa.PublicKey { s.LockStorage() defer s.UnlockStorage() - return s.PublicKey + return s.RSAPublicKey +} + +func (s *SessionObj) GetDHPrivateKey() *cyclic.Int { + s.LockStorage() + defer s.UnlockStorage() + return s.DHPrivateKey +} + +func (s *SessionObj) GetDHPublicKey() *cyclic.Int { + s.LockStorage() + defer s.UnlockStorage() + return s.DHPublicKey } func (s *SessionObj) GetCmixGroup() *cyclic.Group { diff --git a/user/session_test.go b/user/session_test.go index a54f6beb2e59caa674ed7b792a3fcd980966adce..9d170a05fd9e789f503e8647b45977460035a1e4 100644 --- a/user/session_test.go +++ b/user/session_test.go @@ -11,7 +11,7 @@ import ( "gitlab.com/elixxir/client/globals" "gitlab.com/elixxir/crypto/cyclic" "gitlab.com/elixxir/crypto/large" - "gitlab.com/elixxir/crypto/signature" + "gitlab.com/elixxir/crypto/signature/rsa" "gitlab.com/elixxir/primitives/circuit" "gitlab.com/elixxir/primitives/id" "math/rand" @@ -51,14 +51,16 @@ func TestUserSession(t *testing.T) { storage := &globals.RamStorage{} rng := rand.New(rand.NewSource(42)) - params := signature.NewDSAParams(rng, signature.L1024N160) - privateKey := params.PrivateKeyGen(rng) - publicKey := privateKey.PublicKeyGen() + privateKey, _ := rsa.GenerateKey(rng, 768) + publicKey := rsa.PublicKey{PublicKey: privateKey.PublicKey} cmixGrp, e2eGrp := getGroups() + privateKeyDH := cmixGrp.RandomCoprime(cmixGrp.NewInt(1)) + publicKeyDH := cmixGrp.ExpG(privateKeyDH, cmixGrp.NewInt(1)) + ses := NewSession(storage, - u, keys, publicKey, privateKey, cmixGrp, e2eGrp) + u, keys, &publicKey, privateKey, publicKeyDH, privateKeyDH, cmixGrp, e2eGrp) ses.SetLastMessageID("totally unique ID") @@ -118,10 +120,26 @@ func TestUserSession(t *testing.T) { for i := 0; i < len(ses.GetKeys(topology)); i++ { - if !reflect.DeepEqual(*ses.GetPublicKey(), *publicKey) { + sesPriv := ses.GetRSAPrivateKey().PrivateKey + if !reflect.DeepEqual(*ses.GetRSAPublicKey(), publicKey) { t.Errorf("Error: Public key not set correctly!") - } else if !reflect.DeepEqual(*ses.GetPrivateKey(), *privateKey) { - t.Errorf("Error: Private key not set correctly!") + } else if !reflect.DeepEqual(sesPriv, privateKey.PrivateKey) { + orig := privateKey.PrivateKey + if sesPriv.E != orig.E { + t.Errorf("Error: Private key not set correctly E! \nExpected: %+v\nreceived: %+v", + orig.E, sesPriv.E) + } else if sesPriv.D.Cmp(orig.D) != 0 { + t.Errorf("Error: Private key not set correctly D! \nExpected: %+v\nreceived: %+v", + orig.D, sesPriv.D) + } else if sesPriv.N.Cmp(orig.N) != 0 { + t.Errorf("Error: Private key not set correctly N! \nExpected: %+v\nreceived: %+v", + orig.N, sesPriv.N) + } else if !reflect.DeepEqual(sesPriv.Primes, orig.Primes) { + t.Errorf("Error: Private key not set correctly PRIMES! \nExpected: %+v\nreceived: %+v", + orig, sesPriv) + } else { + t.Log("DeepEqual failed, but values are equal...") + } } else if ses.GetKeys(topology)[i].ReceptionKey.Cmp(grp. NewInt(2)) != 0 { t.Errorf("Error: Reception key not set correctly!") @@ -135,7 +153,7 @@ func TestUserSession(t *testing.T) { } //TODO: FIX THIS? - if ses.GetPrivateKey() == nil { + if ses.GetRSAPrivateKey() == nil { t.Errorf("Error: Private Keys not set correctly!") } else { pass++ @@ -212,15 +230,17 @@ func TestGetPubKey(t *testing.T) { } rng := rand.New(rand.NewSource(42)) - params := signature.NewDSAParams(rng, signature.L1024N160) - privateKey := params.PrivateKeyGen(rng) - publicKey := privateKey.PublicKeyGen() + privateKey, _ := rsa.GenerateKey(rng, 768) + publicKey := rsa.PublicKey{PublicKey: privateKey.PublicKey} cmixGrp, e2eGrp := getGroups() - ses := NewSession(nil, u, keys, publicKey, privateKey, cmixGrp, e2eGrp) + privateKeyDH := cmixGrp.RandomCoprime(cmixGrp.NewInt(1)) + publicKeyDH := cmixGrp.ExpG(privateKeyDH, cmixGrp.NewInt(1)) + + ses := NewSession(nil, u, keys, &publicKey, privateKey, publicKeyDH, privateKeyDH, cmixGrp, e2eGrp) - pubKey := ses.GetPublicKey() + pubKey := *ses.GetRSAPublicKey() if !reflect.DeepEqual(pubKey, publicKey) { t.Errorf("Public key not returned correctly!") } @@ -243,15 +263,17 @@ func TestGetPrivKey(t *testing.T) { } rng := rand.New(rand.NewSource(42)) - params := signature.NewDSAParams(rng, signature.L1024N160) - privateKey := params.PrivateKeyGen(rng) - publicKey := privateKey.PublicKeyGen() + privateKey, _ := rsa.GenerateKey(rng, 768) + publicKey := rsa.PublicKey{PublicKey: privateKey.PublicKey} cmixGrp, e2eGrp := getGroups() - ses := NewSession(nil, u, keys, publicKey, privateKey, cmixGrp, e2eGrp) + privateKeyDH := cmixGrp.RandomCoprime(cmixGrp.NewInt(1)) + publicKeyDH := cmixGrp.ExpG(privateKeyDH, cmixGrp.NewInt(1)) + + ses := NewSession(nil, u, keys, &publicKey, privateKey, publicKeyDH, privateKeyDH, cmixGrp, e2eGrp) - privKey := ses.GetPrivateKey() + privKey := ses.GetRSAPrivateKey() if !reflect.DeepEqual(*privKey, *privateKey) { t.Errorf("Private key is not returned correctly!") }