examples: Extend example with basic trust schema (validator-config)

Change-Id: Iaf9f4abd57563e52cb167b55ba3b27d8ecc1ecd7
diff --git a/examples/README.md b/examples/README.md
index 22b71ac..f1f829c 100644
--- a/examples/README.md
+++ b/examples/README.md
@@ -1,22 +1,22 @@
-ndn-cxx examples
-================
+# ndn-cxx examples
 
-By default, examples in `examples/` folder are not built.  To enable them, use
+By default, the examples in `examples/` folder are not built. To enable them, use
 `--with-examples` configure option. For example:
 
     ./waf configure --with-examples
     ./waf
 
-There are two ways to add new examples, depending on their complexity:
+There are two ways to add new examples, depending on their complexity.
 
-1. Examples with a single translation unit
+1. **Examples with a single translation unit**
 
-  For simple examples that have a single translation unit, the `.cpp` file can be directly put
-  in `examples/` folder and it will be automatically compiled on the next run of `./waf`. Name
-  of the compiled binary will be determined by the base name of the `.cpp` file.  For example,
-  `examples/foo.cpp` will be compiled into binary `foo` in `<build>/examples` folder:
+    For simple examples that have a single translation unit, the `.cpp` file can be directly put
+    in the `examples/` folder and it will be automatically compiled on the next run of `./waf`.
+    The name of the compiled executable will be determined by the base name of the `.cpp` file.
+    For instance, `examples/foo.cpp` will be compiled into an executable named `foo` inside the
+    `build/examples` folder:
 
-        echo "int main() { return 0; }" > examples/foo.cpp
+        echo 'int main() { return 0; }' > examples/foo.cpp
         ./waf
         # ... Compiling examples/foo.cpp
         # ... Linking build/examples/foo
@@ -24,25 +24,23 @@
         # To run the example
         ./build/examples/foo
 
-2. Examples with multiple translation units
+2. **Examples with multiple translation units**
 
-  For more complex examples that contain multiple translation units, one can use
-  the following directory structure:
+    For more complex examples that contain multiple translation units, one can use
+    the following directory structure:
 
-  - Create a directory under `examples/` folder (e.g., `examples/bar`).
-    The name of this directory will determine the name of the compiled binary
-   (`<build>/examples/bar/bar`)
+    - Create a directory under the `examples/` folder (e.g., `examples/bar`). The name of this
+      directory will determine the name of the compiled executable (`build/examples/bar/bar`).
+    - Place any number of translation units (e.g., `examples/bar/a.cpp`, `examples/bar/b.cpp`,
+      ...) in this directory. All `.cpp` files in this directory will be compiled and linked
+      together to produce the binary executable of the example. One of the .cpp files must
+      contain the `main()` function.
 
-  - Place any number of translation units (e.g., `examples/bar/a.cpp`, `examples/bar/b.cpp`,
-    ...) in this directory.  All `.cpp` files in this directory will be compiled and linked
-    together to produce the binary of the example.  One of the .cpp files should contain
-    the `main()` function.
-
-  For example:
+    For example:
 
         mkdir examples/bar
-        echo "int bar(); int main() { return bar(); }" > examples/bar/a.cpp
-        echo "int bar() { return 10; } " > examples/bar/b.cpp
+        echo 'int bar(); int main() { return bar(); }' > examples/bar/a.cpp
+        echo 'int bar() { return 10; }' > examples/bar/b.cpp
         ./waf
         # ... Compiling examples/bar/a.cpp
         # ... Compiling examples/bar/b.cpp
@@ -50,3 +48,18 @@
 
         # To run the example
         ./build/examples/bar/bar
+
+## Security configuration for example apps
+
+In order for the ``consumer`` example app to be able to properly authenticate data packets
+created by the ``producer`` app, you must configure the following parameters.
+
+1. Generate example trust anchor:
+
+        ndnsec key-gen /example
+        ndnsec cert-dump -i /example > example-trust-anchor.cert
+
+2. Create a key for the producer and sign it with the example trust anchor:
+
+        ndnsec key-gen /example/testApp
+        ndnsec sign-req /example/testApp | ndnsec cert-gen -s /example -i example | ndnsec cert-install -
diff --git a/examples/consumer-with-timer.cpp b/examples/consumer-with-timer.cpp
index 2f9c4d4..985b77e 100644
--- a/examples/consumer-with-timer.cpp
+++ b/examples/consumer-with-timer.cpp
@@ -17,8 +17,6 @@
  * <http://www.gnu.org/licenses/>.
  *
  * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
- *
- * @author Alexander Afanasyev <http://lasr.cs.ucla.edu/afanasyev/index.html>
  */
 
 #include <ndn-cxx/face.hpp>
diff --git a/examples/consumer.cpp b/examples/consumer.cpp
index 5808c99..6643812 100644
--- a/examples/consumer.cpp
+++ b/examples/consumer.cpp
@@ -17,11 +17,10 @@
  * <http://www.gnu.org/licenses/>.
  *
  * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
- *
- * @author Alexander Afanasyev <http://lasr.cs.ucla.edu/afanasyev/index.html>
  */
 
 #include <ndn-cxx/face.hpp>
+#include <ndn-cxx/security/validator-config.hpp>
 
 #include <iostream>
 
@@ -33,6 +32,11 @@
 class Consumer
 {
 public:
+  Consumer()
+  {
+    m_validator.load("trust-schema.conf");
+  }
+
   void
   run()
   {
@@ -56,9 +60,17 @@
 
 private:
   void
-  onData(const Interest&, const Data& data) const
+  onData(const Interest&, const Data& data)
   {
     std::cout << "Received Data " << data << std::endl;
+
+    m_validator.validate(data,
+                         [] (const Data&) {
+                           std::cout << "Data conforms to trust schema" << std::endl;
+                         },
+                         [] (const Data&, const security::ValidationError& error) {
+                           std::cout << "Error authenticating data: " << error << std::endl;
+                         });
   }
 
   void
@@ -75,6 +87,7 @@
 
 private:
   Face m_face;
+  ValidatorConfig m_validator{m_face};
 };
 
 } // namespace examples
diff --git a/examples/producer.cpp b/examples/producer.cpp
index d88cc86..16356ff 100644
--- a/examples/producer.cpp
+++ b/examples/producer.cpp
@@ -17,8 +17,6 @@
  * <http://www.gnu.org/licenses/>.
  *
  * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
- *
- * @author Alexander Afanasyev <http://lasr.cs.ucla.edu/afanasyev/index.html>
  */
 
 #include <ndn-cxx/face.hpp>
@@ -38,10 +36,17 @@
   void
   run()
   {
-    m_face.setInterestFilter("/example/testApp",
+    m_face.setInterestFilter("/example/testApp/randomData",
                              std::bind(&Producer::onInterest, this, _1, _2),
                              nullptr, // RegisterPrefixSuccessCallback is optional
                              std::bind(&Producer::onRegisterFailed, this, _1, _2));
+
+    auto cert = m_keyChain.getPib().getDefaultIdentity().getDefaultKey().getDefaultCertificate();
+    m_certServeHandle = m_face.setInterestFilter(security::extractIdentityFromCertName(cert.getName()),
+                             [this, cert] (auto&&...) {
+                               m_face.put(cert);
+                             },
+                             std::bind(&Producer::onRegisterFailed, this, _1, _2));
     m_face.processEvents();
   }
 
@@ -58,6 +63,18 @@
     data->setFreshnessPeriod(10_s);
     data->setContent(reinterpret_cast<const uint8_t*>(content.data()), content.size());
 
+    // in order for the consumer application to be able to validate the packet, you need to setup
+    // the following keys:
+    // 1. Generate example trust anchor
+    //
+    //         ndnsec key-gen /example
+    //         ndnsec cert-dump -i /example > example-trust-anchor.cert
+    //
+    // 2. Create a key for the producer and sign it with the example trust anchor
+    //
+    //         ndnsec key-gen /example/testApp
+    //         ndnsec sign-req /example/testApp | ndnsec cert-gen -s /example -i example | ndnsec cert-install -
+
     // Sign Data packet with default identity
     m_keyChain.sign(*data);
     // m_keyChain.sign(*data, signingByIdentity(<identityName>));
@@ -81,6 +98,7 @@
 private:
   Face m_face;
   KeyChain m_keyChain;
+  ScopedRegisteredPrefixHandle m_certServeHandle;
 };
 
 } // namespace examples
diff --git a/examples/trust-schema.conf b/examples/trust-schema.conf
new file mode 100644
index 0000000..aade06c
--- /dev/null
+++ b/examples/trust-schema.conf
@@ -0,0 +1,34 @@
+rule
+{
+  id "Example rule"
+  for data
+  filter
+  {
+    type name
+    name /example/testApp
+    relation is-prefix-of
+  }
+  checker
+  {
+    type customized
+    sig-type ecdsa-sha256
+    key-locator
+    {
+      type name
+      hyper-relation
+      {
+        k-regex ^(<>*)<KEY><><>?<>?$
+        k-expand \\1
+        h-relation is-prefix-of
+        p-regex ^(<>*)<>*$
+        p-expand \\1
+      }
+    }
+  }
+}
+
+trust-anchor
+{
+  type file
+  file-name "example-trust-anchor.cert"
+}