blob: 392bbf67209dd6c23d5d7867043c1bb87b6bb0d1 [file] [log] [blame]
Alexander Afanasyevaa8b3782017-01-19 20:04:31 -08001.. _Security Library Tutorial:
2
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -07003Security Library Tutorial
4=========================
5
Yingdi Yu4e99f532014-08-25 19:40:57 -07006.. contents::
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -07007
8Identity, Key and Certificates
Yingdi Yu4e99f532014-08-25 19:40:57 -07009------------------------------
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -070010
Yingdi Yu4e99f532014-08-25 19:40:57 -070011All keys, certificates and their corresponding identities are managed by :ndn-cxx:`KeyChain`.
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -070012
Yingdi Yu4e99f532014-08-25 19:40:57 -070013An real world **identity** can be expressed by a namespace. (e.g.,
14``/ndn/edu/ucla/alice``, or ``/ndn/edu/ucla/BoelterHall/4805``).
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -070015
Yingdi Yu4e99f532014-08-25 19:40:57 -070016**Keys** belonging to an identity are named under the identity's namespace, with a unique
17**KeyId**::
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -070018
Yingdi Yu4e99f532014-08-25 19:40:57 -070019 /<identity_name>/[KeyId]
20
21For now, only two types of KeyId are specified: ``ksk-[timestamp]`` and
22``dsk-[timestamp]``. The first type of KeyId is used to denote Key-Signing-Key (KSK)
23which is supposed to have a long lifetime. The second type of KeyId is used to denote
24Data-Signing-Key (DSK) which is supposed to have a short lifetime. Both types of KeyId
25use timestamps (number of milliseconds since unix epoch) to provide relative uniqueness of
26key names. Replacing timestamp with key hash can bring stronger uniqueness but on the
27cost of longer name. Therefore, key hash is not used for now. For example,
28``/ndn/edu/ucla/alice/ksk-1234567890`` or
29``/ndn/edu/ucla/BoelterHall/4805/dsk-1357924680``.
30
31An identity may have more than one keys associated with it. For example, one may have a
32KSK to sign other keys and a DSK to sign data packets, or one may periodically replace its
33expired DSK/KSK with a new key.
34
35The private part of a key ("private key"), is stored in a :ndn-cxx:`Trusted Platform
36Module (TPM) <SecTpm>`. The public part ("public key"), is managed in a
37:ndn-cxx:`Public-key Information Base (PIB) <SecPublicInfo>`. The most important
38information managed by PIB is **certificates** of public keys. A certificate binds a
39public key to its key name or the corresponding identity. The signer (or issuer) of a
40certificate vouches for the binding through its own signature. With different signers
41vouching for the binding, a public key may have more than one certificates.
42
43The certificate name follows the naming convention of `NDNS (NDN Domain Name Service) <http://lasr.cs.ucla.edu/afanasyev/data/files/Afanasyev/afanasyev-phd-thesis.pdf>`_. The
44public key name will be broken into two parts:
45
46- The first part ("authoritative namespace") will be put before a name component ``KEY``
47 which serves as an application tag
48- The second part ("label") will be put between ``KEY`` and ``ID-CERT`` which serves as an
49 indicator of certificate.
50
51A version number of the certificate is appended after ``ID-CERT``. For example,
52``/ndn/edu/ucla/KEY/alice/ksk-1234567890/ID-CERT/%FD%01`` or
53``/ndn/edu/ucla/BoelterHall/4805/KEY/dsk-1357924680/ID-CERT/%FD%44``.
54
55The :ndn-cxx:`NDN certificate <IdentityCertificate>` is just an ordinary `NDN-TLV Data
56packet <http://named-data.net/doc/ndn-tlv/data.html>`_, with the content part in DER
57encoding that resembles X.509 certificate:
58
59.. code-block:: cpp
60
61 // NDN-TLV Encoding
62 Certificate ::= DATA-TLV TLV-LENGTH
63 Name
64 MetaInfo (= CertificateMetaInfo)
65 Content (= CertificateContent)
66 Signature
67
68 CertificateMetaInfo ::= META-INFO-TYPE TLV-LENGTH
69 ContentType (= KEY)
70 FreshnessPeriod (= ?)
71
72
73 CertificateContent ::= CONTENT-TYPE TLV-LENGTH
74 CertificateDerPayload
75
76
77 // DER Encoding
78 CertificateDerPayload ::= SEQUENCE {
79 validity Validity,
80 subject Name,
81 subjectPubKeyInfo SubjectPublicKeyInfo,
82 extension Extensions OPTIONAL }
83
84 Validity ::= SEQUENCE {
85 notBefore Time,
86 notAfter Time }
87
88 Time ::= CHOICE {
89 GeneralizedTime }
90
91 Name ::= CHOICE {
92 RDNSequence }
93
94 RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
95
96 RelativeDistinguishedName ::=
97 SET OF AttributeTypeAndValue
98
99 SubjectPublicKeyInfo ::= SEQUENCE {
100 algorithm AlgorithmIdentifier
101 keybits BIT STRING }
102
103 Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
104
105See `RFC 3280 <http://www.ietf.org/rfc/rfc3280.txt>`_ for more details about DER field
106definitions.
107
108Signing
109-------
110
111Key Management
112%%%%%%%%%%%%%%
113
114Create Identity/Keys/Certificate
115~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
116
117The simplest way to initialize an identity and its key and certificate is to call
118:ndn-cxx:`KeyChain::createIdentity`
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -0700119
120.. code-block:: cpp
121
122 KeyChain keyChain;
Yingdi Yu4e99f532014-08-25 19:40:57 -0700123 Name defaultCertName = keyChain.createIdentity(identity);
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -0700124
Yingdi Yu4e99f532014-08-25 19:40:57 -0700125This method guarantees that the default key and certificate of the supplied identity
126always exist in the KeyChain. This method checks if the supplied identity has already had
127a default key and a default certificate and returns the default certificate name if
128exists. If the default certificate is missing, KeyChain will automatically create a
129self-signed certificate of the default key. If the default key is missing, KeyChain will
130automatically create a new key and set it as the default key and create a self-signed
131certificate as well.
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -0700132
133Create Keys Manually
134~~~~~~~~~~~~~~~~~~~~
135
Yingdi Yu4e99f532014-08-25 19:40:57 -0700136One can call :ndn-cxx:`KeyChain::generateRsaKeyPair` to generate an RSA key pair or
Alexander Afanasyev7e721412017-01-11 13:36:08 -0800137:ndn-cxx:`KeyChain::generateEcKeyPair` to generate an EC key. Note that generated
Yingdi Yu4e99f532014-08-25 19:40:57 -0700138key pair is not set as the default key of the identity, so you need to set it manually by
139calling :ndn-cxx:`KeyChain::setDefaultKeyNameForIdentity`. There is also a helper method
140:ndn-cxx:`KeyChain::generateRsaKeyPairAsDefault`, which combines the two steps into one.
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -0700141
142.. code-block:: cpp
143
144 KeyChain keyChain;
145 Name alice("/ndn/test/alice");
146
Junxiao Shie9c3db32015-02-14 19:51:28 -0700147 Name aliceKeyName = keyChain.generateRsaKeyPair(alice);
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -0700148 keyChain.setDefaultKeyNameForIdentity(aliceKeyName);
149
Yingdi Yu4e99f532014-08-25 19:40:57 -0700150 // Now the key with the name aliceKeyName2 becomes alice's default key
Junxiao Shie9c3db32015-02-14 19:51:28 -0700151 Name aliceKeyName2 = keyChain.generateRsaKeyPairAsDefault(alice);
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -0700152
153Create Identity Certificate Manually
154~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
155
Yingdi Yu4e99f532014-08-25 19:40:57 -0700156If you have created a key pair, you can generate a self-signed certificate for the key by
157calling :ndn-cxx:`KeyChain::selfSign`.
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -0700158
159.. code-block:: cpp
160
161 KeyChain keyChain;
162 Name aliceKeyName("/ndn/test/alice/ksk-1394129695025");
163
164 shared_ptr<IdentityCertificate> aliceCert = keyChain.selfSign(aliceKeyName);
165
Yingdi Yu4e99f532014-08-25 19:40:57 -0700166You can sign a public key using a different key:
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -0700167
168.. code-block:: cpp
169
170 KeyChain keyChain;
171
Yingdi Yu4e99f532014-08-25 19:40:57 -0700172 shared_ptr<IdentityCertificate> certificate =
173 keyChain.prepareUnsignedIdentityCertificate(publicKeyName, publicKey,
174 signingIdentity,
175 notBefore, notAfter,
176 subjectDescription, prefix
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -0700177
Yingdi Yu4e99f532014-08-25 19:40:57 -0700178 keyChain.signByIdentity(*certificate, signingIdentity);
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -0700179
Yingdi Yu4e99f532014-08-25 19:40:57 -0700180Signing Data
181%%%%%%%%%%%%
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -0700182
Yingdi Yu4e99f532014-08-25 19:40:57 -0700183Although the security library does not have the intelligence to automatically determine
184the signing key for each data packet, it still provides a mechanism, called **Default
185Signing Settings**, to facilitate signing process.
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -0700186
Yingdi Yu4e99f532014-08-25 19:40:57 -0700187The basic signing process in the security library would be like this: create :ndn-cxx:`KeyChain`
188instance and supply the data packet and signing certificate name to :ndn-cxx:`KeyChain::sign`
189method.
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -0700190
Yingdi Yu4e99f532014-08-25 19:40:57 -0700191.. code-block:: cpp
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -0700192
Yingdi Yu4e99f532014-08-25 19:40:57 -0700193 KeyChain keyChain;
194 keyChain.sign(dataPacket, signingCertificateName);
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -0700195
Yingdi Yu4e99f532014-08-25 19:40:57 -0700196The :ndn-cxx:`KeyChain` instance will
197
198- construct ``SignatureInfo`` using the signing certificate name;
199- look up the corresponding private key in :ndn-cxx:`TPM <SecTpm>`;
200- sign the data packet if the private key exists.
201
202The basic process, however, requires application developers to supply the exact
203certificate name. Such a process has two shortages: first, it might be difficult to
204remember the certificate name; second, application developers have to be aware of
205certificate update and key roll-over. Therefore, the security library provides another
206signing process in which application developers only need to supply the signing identity:
207
208.. code-block:: cpp
209
210 KeyChain keyChain;
211 keyChain.signByIdentity(dataPacket, signingIdentity);
212
213The :ndn-cxx:`KeyChain` instance will
214
215- determine the default key of the signing identity;
216- determine the default certificate of the key;
217- construct ``SignatureInfo`` using the default certificate name;
218- look up the corresponding private key in :ndn-cxx:`TPM <SecTpm>`;
219- sign the data packet if the private key exists.
220
221The process above requires that each identity has a default key and that each key has a
222default certificate. All these default settings is managed in :ndn-cxx:`PIB
223<SecPublicInfo>`, one can get/set these default settings through :ndn-cxx:`KeyChain`
224directly:
225
226.. code-block:: cpp
227
228 KeyChain keyChain;
229 Name defaultKeyName = keyChain.getDefaultKeyNameForIdentity(identity);
230 Name defaultCertName = keyChain.getDefaultCertificateNameForKey(keyName);
231
232 keyChain.setDefaultKeyNameForIdentity(keyName);
233 keyChain.setDefaultCertificateNameForKey(certificateName);
234
235There is even a default identity which will be used when no identity information is
236supplied in signing method:
237
238.. code-block:: cpp
239
240 KeyChain keyChain;
241 keyChain.sign(dataPacket);
242
243And default identity can be got/set through :ndn-cxx:`KeyChain` as well:
244
245.. code-block:: cpp
246
247 KeyChain keyChain;
248 Name defaultIdentity = keyChain.getDefaultIdentity();
249 keyChain.setDefaultIdentity(identity);
250
251
252Signing Interests
253%%%%%%%%%%%%%%%%%
254
255The process of signing Interests according to the :doc:`Signed Interest specification
Yingdi Yu55ea01a2015-07-21 22:42:17 -0700256<../specs/signed-interest>` is exactly the same as the process of signing Data packets:
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -0700257
258.. code-block:: cpp
259
260 KeyChain keyChain;
261
Yingdi Yu4e99f532014-08-25 19:40:57 -0700262 keyChain.sign(interest, signingCertName);
263 keyChain.signByIdentity(interest, signingIdentity);
264 keyChain.sign(interest);
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -0700265
Yingdi Yu4e99f532014-08-25 19:40:57 -0700266Validation
267----------
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -0700268
Yingdi Yu4e99f532014-08-25 19:40:57 -0700269Interest and Data validation is done through a **Validator**. :ndn-cxx:`Validator` is a virtual
270class, two pure virtual methods must be implemented in order to construct a working
271validator:
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -0700272
273.. code-block:: cpp
274
Yingdi Yu4e99f532014-08-25 19:40:57 -0700275 class Validator
276 {
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -0700277 ...
278 protected:
279 virtual void
Yingdi Yu4e99f532014-08-25 19:40:57 -0700280 checkPolicy(const Data& data,
281 int nSteps,
282 const OnDataValidated& onValidated,
283 const OnDataValidationFailed& onValidationFailed,
284 std::vector<shared_ptr<ValidationRequest> >& nextSteps) = 0;
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -0700285
286 virtual void
Yingdi Yu4e99f532014-08-25 19:40:57 -0700287 checkPolicy(const Interest& interest,
288 int nSteps,
289 const OnInterestValidated& onValidated,
290 const OnInterestValidationFailed& onValidationFailed,
291 std::vector<shared_ptr<ValidationRequest> >& nextSteps) = 0;
292 ...
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -0700293 };
294
Yingdi Yu4e99f532014-08-25 19:40:57 -0700295What should be implemented in these two methods is to check:
296
297- whether the packet and signer comply with trust policies;
298- whether their signature can be verified.
299
300If the packet can be validated, the ``onValidated`` callback should be invoked, otherwise
301the ``onValidationFailed`` callback should be invoked. If more information (e.g., other
302certificates) is needed, express the request for missing information in one or more
303``ValidationRequest`` and push them into ``nextSteps``.
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -0700304
305.. code-block:: cpp
306
Yingdi Yu4e99f532014-08-25 19:40:57 -0700307 class ValidationRequest
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -0700308 {
309 public:
Yingdi Yu4e99f532014-08-25 19:40:57 -0700310 Interest m_interest; // The Interest for the requested data/certificate.
311 OnDataValidated m_onValidated; // Callback when the retrieved certificate is authenticated.
312 OnDataValidationFailed m_onDataValidated; // Callback when the retrieved certificate cannot be authenticated.
313 int m_nRetries; // The number of retries when the interest times out.
314 int m_nStep; // The number of validation steps that have been performed.
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -0700315 };
316
Yingdi Yu4e99f532014-08-25 19:40:57 -0700317Besides the two ``Validator::checkPolicy`` methods, the ``Validator`` also provides three
318hooks to control packet validation in a finer granularity.
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -0700319
320.. code-block:: cpp
321
Yingdi Yu4e99f532014-08-25 19:40:57 -0700322 class Validator
323 {
324 ...
325 protected:
326 virtual shared_ptr<const Data>
327 preCertificateValidation(const Data& data);
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -0700328
Yingdi Yu4e99f532014-08-25 19:40:57 -0700329 virtual void
330 onTimeout(const Interest& interest,
331 int nRemainingRetries,
332 const OnFailure& onFailure,
333 const shared_ptr<ValidationRequest>& validationRequest);
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -0700334
Yingdi Yu4e99f532014-08-25 19:40:57 -0700335 virtual void
336 afterCheckPolicy(const std::vector<shared_ptr<ValidationRequest> >& nextSteps,
337 const OnFailure& onFailure);
338 ...
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -0700339 };
Yingdi Yu4e99f532014-08-25 19:40:57 -0700340
341``Validator::preCertificateValidation`` is triggered before validating requested
342certificate. The Data supplied matches the interest in the ``ValidationRequest``. It may
343be certificate or a data encapsulating certificate. This hook returns a data (actually
344certificate) that is will be passed as Data into ``Validator::validate``;
345
346``Validator::onTimeout`` is triggered when interest for certificate times out. The logic
347to handle the timeout can be implemented in this hook. One could invoke onFailure or
348re-express the interest.
349
350``Validator::afterCheckPolicy`` is invoked after ``Validator::checkPolicy`` is done. One
351can implement the logic of how to process the set of ValidationRequests according to its
352trust model.
353
354Configuration-based Validator
355%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
356
357In most cases, the trust model of applications are simple. However, it is not trivial to
358implement the two ``Validator::checkPolicy`` methods. Therefore, we provide a more
359developer-friendly configuration-based validator, ``ValidatorConfig``. With
360``ValidatorConfig``, one can express the trust model using a policy language in a
361configuration file. See :doc:`security-validator-config` for more details.