def receiveM2Request(self):

        # M2 length
        firstMessage = self.sock.recv(4)

        if firstMessage == "":
            print "[Error] Error in the protocol --> M2"
            return False
        
        # M2
        length = struct.unpack('>I', firstMessage)[0]
        response = self.secureReceive(int(length))
        
        packet = clientGui_utility.unpackMessage(response, 4)
        cryptogram = packet[0]
        ivServer = packet[1]
        plaintextReceived = symmetric_encryption.decrypt_AES(cryptogram, self.kcs, ivServer)


        fieldsM2 = clientGui_utility.unpackMessage(plaintextReceived, 4)
        
        print "\n[Protocol] M2 IV\n"
        print "\tM1 IV: [cryptogram, serverIV]"
        print "C <----------------------------------------------------------- S\n"

        return fieldsM2
    def receiveM4Request(self):
        firstMessage = self.sock.recv(4)

        if firstMessage == "" or firstMessage == "FAIL":
            print "[Error] Error in the protocol M4 length"
            return False, None
        
        # M4
        length = struct.unpack('>I', firstMessage)[0]
        response = self.secureReceive(int(length))

        cryptogram, ivServer = clientGui_utility.unpackMessage(response, 4)

        plaintextReceived = symmetric_encryption.decrypt_AES(cryptogram, self.kcs, ivServer)

        fieldsM4 = clientGui_utility.unpackMessage(plaintextReceived, 4)
            
        print "\n[Protocol] M4\n"
        print "\t\t\tM4: [cryptogram, serverIV]"
        print "C <----------------------------------------------------------- S\n"

        return fieldsM4, plaintextReceived
    def receiveM2(self):
        lenM2 = self.sock.recv(4)
        length = struct.unpack('>I', lenM2)[0]
        if lenM2 == "":
            print "[Error] Error in the protocol M2 length"
            return "1050"
            #return False
        
        # M2
        response = self.secureReceive(int(length))
        fieldsM1 = clientGui_utility.unpackMessage(response, 4)

        print "\n[Protocol] M2\n"
        print "\tM1: [ServerName, ServerCertificate, NounceS]"
        print "C <----------------------------------------------------------- S\n"

        return fieldsM1
    def receiveM4(self):
            
        firstMessage = self.sock.recv(4)

        if firstMessage == "":
            print "[Error] Error in the protocol --> M4"
            return "1050"
            #return False
        
        # M4
        length = struct.unpack('>I', firstMessage)[0]
        response = self.secureReceive(int(length))
    
        fieldsM4 = clientGui_utility.unpackMessage(response, 4)

        print "\n[Protocol] M4\n"
        print "\t\t\tM4: [cryptogram, serverIV]"
        print "C <----------------------------------------------------------- S\n"

        return fieldsM4
    def registration(self, username, password, code):
        global counter
        if counter >= 4:
            return "1090" # Too many errors in login/sign in phases. Please close the app and try again.

        try:
            global connectFlag
            if connectFlag is True:
                res = self.connect(addr, int(port))
                if res is False:
                    return "1050"
                else:
                    connectFlag = False
            # M1
            try:

                self.sendM1(username)
                
            except socket.error as err:
                print "[Error] Error on M1 ---"
                err_type = err.args[0]
                if err_type in [errno.EBADF, errno.ENOTCONN]:  #   9: Bad file descriptor.
                    print err_type
                
                return "1050"
                
                #return False
            
            # M2
            fieldsM1 = self.receiveM2()

            if len(fieldsM1) != 3:
                print "[Error] Error in the field length"
                return "1050"
            
            serverName = fieldsM1[0]
            serverCertificate = fieldsM1[1]
            nounceS = fieldsM1[2]
            
            result, serverNameCert, serverPublicKey, serialNumber, ca_pubkey = clientGui_utility.checkCertificate(serverCertificate)
        
            if clientGui_utility.certificateControl(result, serverName, serverNameCert, ca_pubkey, serialNumber) == "1050":
                return "1050"

            self.kcs = os.urandom(32)
            nounceC = os.urandom(16)
 
            plaintext = clientGui_utility.createPlaintext(code, serverName, username, password, self.kcs, nounceS, nounceC)

            # M3
            self.sendM3(serverPublicKey, plaintext)

            # M4
            fieldsM4 = self.receiveM4()
            
            if fieldsM4 is False or fieldsM4[0] == "FAIL":
                counter = counter + 1
                return "1050"
            
            if fieldsM4[0] == "COPY":
                counter = counter + 1
                return "1070"

            cryptogram = fieldsM4[0]
            ivServer = fieldsM4[1]

            plaintext = symmetric_encryption.createPlaintextAES(self.kcs, ivServer, cryptogram)
            clearFieldM4 = clientGui_utility.unpackMessage(plaintext, DIM)

            status = clearFieldM4[0]
            serverNameM4 = clearFieldM4[1]
            usernameM4 = clearFieldM4[2]
            nounceCHashed = clearFieldM4[3]
            hashReceived = clearFieldM4[4]

            packet = clientGui_utility.concatenate(status, serverNameM4, usernameM4, nounceCHashed)
            hashExpected = clientGui_utility.get_hash(bytes(packet), "")

            my_nounceC_hashed = clientGui_utility.get_hash(bytes(nounceC), "")

            if clientGui_utility.checkFields(serverNameM4, serverName, usernameM4, username, hashExpected, hashReceived, my_nounceC_hashed, nounceCHashed) is False:
                return "1050"
        
            print " RESPONSE: ", '[' + code + '|' + status + ']'

            if int(status) == 100:
                counter = 0
            else:
                return "1050"

            if kdfunction.kdf(password) is None:
                return "1050"
            else:
                self.kdfPassword = kdfunction.kdf(password) 

            return True
    
        except socket.error as err:
            
            print "[Error] Error on registration or login"
            err_type = err.args[0]
            if err_type in [errno.EBADF, errno.ENOTCONN]:  #   9: Bad file descriptor.
                return "1050"
            return "1050"