The Observer Pattern

The Observer Pattern was defined by the Gang of Four (GoF). It is also known as Dependents-, and Publish-Subscribe-Pattern.

Motivation

The intention for using the observer pattern is to have a one-to-many dependency between objects. When one object changes it’s state, all the other objects shall be notified. This makes it possible to couple different modules with each other without the need of hardcoding their dependency. Thus, you get better structured, more reusable classes.

Example

Consider a spreadsheet application, that can illustrate the data with different diagrams. By using the Observer-Pattern, every diagram-object would be an observer, and every spreadsheet-object would be a subject. The observers and the subjects are coupled with each other, while every subject can be coupled with many observers. If the user changes something in a diagram, the diagram-object would request the modification at the spreadsheet-object. Now, the spreadsheet-object can start calculating. When it finished, all the diagram-objects are notified, and they can update their view with the modified data.

Observer - spreadsheet-diagram

When to use it

  • When a class has two aspects, and one is dependent on the other. By separating these aspects into observer and subject, you can reuse them independently
  • When modifying one object requires to modify other objects, and you don’t know how many
  • When you don’t want to couple objects tightly with each other

Structure

Observer - Class Diagram

  • ConcreteObserver
    • Implements the update() method, inherited by the Observer Interface
    • Synchronizes it’s subjectState with the observerState
    • Has a reference to it’s ConcreteSubject, to call methods like getState() or setState(state)
  • Observer
    • Interface with an abstract method – update(), that is called, when the Subject notifies the Observer
  • ConcreteSubject
    • Stores the subjectState
    • Notifies it’s Observers, when the subjectState changed
  • Subject
    • Interface for attaching and detaching Observers
    • Hold’s a reference to it’s Observers

Interaction

Observer - Sequence Diagram

Implementation

The code can be downloaded here. Observer.h

class Observer {
public:
    virtual void update() = 0;
};

ConcreteObserver.h

#include "ConcreteSubject.h"
#include <string>

class ConcreteObserver: public Observer {
private:
    std::string observerState;
    ConcreteSubject* subject;
public:
    ConcreteObserver(std::string state, ConcreteSubject* subject);
    void modifyTheSubject(std::string state);
    std::string getObserverState();
    void update();
};

ConcreteObserver.cpp

#include "ConcreteSubject.h"

std::string ConcreteSubject::getState() {
    return subjectState;
}

void ConcreteSubject::setState(std::string state) {
    this->subjectState = state;
    notify();
}

Subject.h

#include <list>
#include "Observer.h"

class Subject {
private:
    std::list <Observer*> observers;
public:
    void attachObserver(Observer* observer);
    void detachObserver(Observer* observer);
    void notify();
};

Subject.cpp

#include "Subject.h"

void Subject::attachObserver(Observer* observer) {
    observers.push_back(observer);
}

void Subject::detachObserver(Observer* observer) {
    for (std::list<Observer*>::iterator it = observers.begin(); it != observers.end(); it++) {
        if (observer == *it) {
            observers.erase(it);
            break;
        }
    }
}

void Subject::notify() {
    for (auto obs : observers) {
        obs->update();
    }
}

ConcreteSubject.h

#include <string>
#include "Subject.h"

class ConcreteSubject: public Subject {
private:
    std::string subjectState;
public:
    std::string getState();
    void setState(std::string state);
};

ConcreteSubject.cpp

#include "ConcreteSubject.h"

std::string ConcreteSubject::getState() {
    return subjectState;
}

void ConcreteSubject::setState(std::string state) {
    this->subjectState = state;
    notify();
}

…Finally for testing main.cpp

#include <iostream>
#include "ConcreteObserver.h"

int main(int argc, const char * argv[]) {
    auto subj = ConcreteSubject();
    auto obs1 = ConcreteObserver("observer 1 hasn't changed", &subj);
    auto obs2 = ConcreteObserver("observer 2 hasn't changed", &subj);
    
    subj.attachObserver(&obs1);
    subj.attachObserver(&obs2);
    
    std::cout << "observer 1: " << obs1.getObserverState() << "\n";
    std::cout << "observer 2: " << obs2.getObserverState() << "\n";
    
    obs1.modifyTheSubject("All observers changed \n");
    
    std::cout << "observer 1: " << obs1.getObserverState();
    std::cout << "observer 2: " << obs2.getObserverState();
    
    return 0;
}

Source: Gang of Four – Design Patterns. Elements of Reusable Object-Oriented Software

The Observer Pattern

How to store passwords in a database

1. Unencrypted

att-1-plain-5002 

Cons:
• Everyone who gets a peek at the file immediately knows how to login with as any user.
• Gives a clue on which sort of password a user seems to favour (Alfred and David might like dates, Eric Cleese likes Monty Python)

Conclusion:
Neither you, nor any system admin should be able to recover a user’s password.

2. Symmetric encrypted

att-2-crypted-500
example: DES encryption with ‘DESPAIR’ as the key.

Cons (of DES):
• Only 56 bit keys (7 characters)
• Several passwords can be cracked within a day, with modern cracking tools.
• If you get the key, you have all passwords
•Same password produces same data, so you know, that e.g.  ‘charlie’ and ‘duck’ use the same password.
•Short password produces short cipher text, long password produces long cipher text.

Conclusion:
• User passwords should not be recoverable from the database
• Identical, or even similar passwords should have different hashes
• The database should not give any hints about the password length

3. Hashed Passwords

att-3-hashed-500
Best hash algorithm right now is SHA-256 (compared to MD5 and SHA-1)

Pros:
• you can’t create a file that comes out with a predefined hash by any method, better than chance.
• you can’t find two files that ‘collide’, i.e. have the same hash, by any method better than chance.
• You can’t work out anything about the structure of the input, including its length, from the hash alone.

Cons:
• Same passwords still produce the same hash (e.g. Charlie and Duck) -> Hackers can pre-calculate famous passwords and look em up.

4. Salt and Hash

att-4-salted

A salt (= nonce: number used once) is a random string, that is included in the hash calculation along with the actual password. This way, the chance, that two passwords become the same hash becomes ignorable small. 
The salt is not an encryption key, so it can be stored in the database.

Don’t use counters such as 0001, 0002… for the salt. Use /dev/urandom on Unix-like systems, or CryptoAPI on Windows. So it can be guaranteed, that each salt is unique.

Cons:
When the attackers manage to steel the database, there is no limit other than CPU power to how fast they can guess passwords. They can try to combine every word in a dictionary, or every password from 00..00 to ZZ..ZZ with every salt in the database. In fact, modern hash-cracking servers costing under $20,000 can compute 100,000,000,000 or more SHA-256 hashes each second.

5. Hash stretching

To make the decryption for a hash-cracking machine harder, you can run the password hashing in a loop, that requires thousands of individual hash calculations.
This will reduce the rate at which an attacker can carry out an offline attack, in direct proportion to the number of iterations you choose.

att-5-pbkdf2-500

• create a salt of 16 bytes or longer
• use HMAC-SHA-256 as the core hash inside PBKDF2
• perform 10000 iterations and more
• take 256 bits of output from PBKDF2 as the final password hash
• store the iteration count, the salt and the final hash in your database
• increase you iteration count regularly to keep up with faster cracking tools

I did this for my own studies. And I posted it, because I like to share. If you like it, great, but the fame goes to Paul Ducklin: https://nakedsecurity.sophos.com/2013/11/20/serious-security-how-to-store-your-users-passwords-safely/

How to store passwords in a database