diff --git a/2021-oop1/ku/stream-05-27-2021/secure_classes/Account.hpp b/2021-oop1/ku/stream-05-27-2021/secure_classes/Account.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..7c59c93fdd2eb0a12c87eb82eea0bbb2699c18bb
--- /dev/null
+++ b/2021-oop1/ku/stream-05-27-2021/secure_classes/Account.hpp
@@ -0,0 +1,24 @@
+#ifndef ACCOUNT_HPP
+#define ACCOUNT_HPP
+
+class Account
+{
+  private:
+    int euros_;
+
+  public:
+    Account() : euros_(0) {}
+    Account(const Account& copy) : euros_(copy.euros_) {}
+    Account& operator=(const Account& rhs)
+    {
+      if (this != &rhs)
+        euros_ = rhs.euros_;
+      return *this;
+    }
+    ~Account() = default;
+
+    int getEuros() const { return euros_; }
+    void changeEurosBy(int difference) { euros_ += difference; }
+};
+
+#endif // ACCOUNT_HPP
diff --git a/2021-oop1/ku/stream-05-27-2021/secure_classes/Bank.hpp b/2021-oop1/ku/stream-05-27-2021/secure_classes/Bank.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..b874c87029ce8836824ab81934586ee50672cefe
--- /dev/null
+++ b/2021-oop1/ku/stream-05-27-2021/secure_classes/Bank.hpp
@@ -0,0 +1,67 @@
+#ifndef BANK_HPP
+#define BANK_HPP
+
+#include "Account.hpp"
+#include <stdexcept>
+#include <iostream>
+
+class Bank
+{
+  private:
+    Account* account_;
+    int pin_code_;
+
+  public:
+    // (*) References / Pointers as a parameters stay valid outside
+    //     No copy -> attributes of classes can be modified from outside
+    Bank(Account* account, int pin_code) : account_(new Account(*account)), pin_code_(pin_code)
+    {
+      // Checks in public methods that are called with parameters
+      if (pin_code_ < 0x1000 || pin_code_ >= 0x10000)
+        throw std::runtime_error("Der Pin-Code ist zu kurz / zu lang!");
+    }
+    Bank(const Bank&) = delete;
+    Bank& operator=(const Bank&) = delete;
+    ~Bank() { delete account_; }
+
+    bool verifyPinCode() const
+    {
+      // Very bad using just std::cin
+      int pin_code;
+      std::cout << "Enter your pin: ";
+      std::cin.unsetf(std::ios::dec);
+      std::cin.unsetf(std::ios::hex);
+      std::cin.unsetf(std::ios::oct);
+      std::cin >> pin_code;
+      return pin_code == pin_code_;
+    }
+
+    // (#) Methods that return references / pointers may screw up 
+    //     the concept of encapsulation
+    Account const* getAccount()
+    {
+      if (!verifyPinCode())
+        throw std::runtime_error("Der Pin-Code ist nicht gültig!");
+
+      return account_;
+    }
+
+    // These two methods are safe, as they do not return a reference / pointer
+    int getAccountEuros() const
+    {
+      if (!verifyPinCode())
+        throw std::runtime_error("Der Pin-Code ist nicht gültig!");
+
+      return account_->getEuros();
+    }
+
+    void changeAccountEurosBy(int euros)
+    {
+      if (!verifyPinCode())
+        throw std::runtime_error("Der Pin-Code ist nicht gültig!");
+
+      account_->changeEurosBy(euros);
+    }
+};
+
+#endif // BANK_HPP
diff --git a/2021-oop1/ku/stream-05-27-2021/secure_classes/main.cpp b/2021-oop1/ku/stream-05-27-2021/secure_classes/main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f612a2b23c2a6a823247bbb2953beda5f80180c5
--- /dev/null
+++ b/2021-oop1/ku/stream-05-27-2021/secure_classes/main.cpp
@@ -0,0 +1,91 @@
+#include "Bank.hpp"
+#include "Account.hpp"
+
+int main(void)
+{
+  int account_state;
+
+  //------------------------------------------------------------------------------------------------
+  std::cout << "\nÜberprüfungen in Settern / Konstruktoren!" << std::endl;
+
+  Account* my_account = new Account;
+
+  // Bank my_bank(my_account, 0x1337abc); // not valid after check in constructor
+  Bank my_bank(my_account, 0x1337); // this is okay
+
+  account_state = my_bank.getAccountEuros(); // pin-code check
+  std::cout << "Kontostand: " << account_state << std::endl;
+
+
+  //------------------------------------------------------------------------------------------------
+  std::cout << "\nPointer als Übergabeparameter!" << std::endl;
+
+  my_account->changeEurosBy(-100); // account from parameters, no pin-code check (* in Bank.hpp)
+
+  account_state = my_account->getEuros(); // no pin-code check
+  std::cout << "falscher  Kontostand: " << account_state << std::endl;
+
+  account_state = my_bank.getAccountEuros(); // pin-code check
+  std::cout << "richtiger Kontostand: " << account_state << std::endl;
+
+
+  //------------------------------------------------------------------------------------------------
+  std::cout << "\nPointer als Rückgabewerte!" << std::endl;
+
+  Account const* my_second_account = my_bank.getAccount(); // getter of account, (# in Bank.hpp)
+  // my_second_account->changeEurosBy(-500); // invalid, if pointer is const; no pin-code check
+
+  Account* hacked_account = const_cast<Account*>(my_second_account); // don't use const_cast
+  hacked_account->changeEurosBy(-500); // now valid and no pin-code check
+
+  account_state = my_second_account->getEuros(); // no pin-code check
+  std::cout << "falscher  Kontostand: " << account_state << std::endl;
+
+  account_state = my_bank.getAccountEuros(); // pin-code check
+  std::cout << "richtiger Kontostand: " << account_state << std::endl;
+
+  // Solution: Don't return a reference / pointer, rather try to provide a method
+  //           to handle everything inside of the class. If the reference / pointer
+  //           has to be returned anyway, make it at least const.
+
+
+  //------------------------------------------------------------------------------------------------
+  std::cout << "\nReinterpret Cast!" << std::endl;
+  std::cout << "Größe der Klasse: " << sizeof(my_bank) << std::endl;
+
+  uint8_t* array = reinterpret_cast<uint8_t*>(&my_bank); // interpret the class as a byte-array
+  for (size_t i = 0; i < sizeof(my_bank); i += 4)
+  {
+    std::cout.width(2);
+    std::cout << std::hex << static_cast<int>(array[i]) << " ";
+    std::cout.width(2);
+    std::cout << std::hex << static_cast<int>(array[i + 1]) << " ";
+    std::cout.width(2);
+    std::cout << std::hex << static_cast<int>(array[i + 2]) << " ";
+    std::cout.width(2);
+    std::cout << std::hex << static_cast<int>(array[i + 3]) << std::endl;
+  }
+  std::cout << std::endl;
+
+  array[8] = 0x38; // change a byte of the class (no encapsulation)
+
+  for (size_t i = 0; i < sizeof(my_bank); i += 4)
+  {
+    std::cout.width(2);
+    std::cout << std::hex << static_cast<int>(array[i]) << " ";
+    std::cout.width(2);
+    std::cout << std::hex << static_cast<int>(array[i + 1]) << " ";
+    std::cout.width(2);
+    std::cout << std::hex << static_cast<int>(array[i + 2]) << " ";
+    std::cout.width(2);
+    std::cout << std::hex << static_cast<int>(array[i + 3]) << std::endl;
+  }
+  std::cout << std::endl;
+
+  account_state = my_bank.getAccountEuros();
+  std::cout << "richtiger Kontostand: " << std::dec << account_state << std::endl << std::endl;
+
+  // Don't do this in the practicals ever! :D
+
+  return 0;
+}