blob: 4f88f72034590644436e54ed2961a679f538cf9a [file] [log] [blame]
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -07001Security Library Tutorial
2=========================
3
Yingdi Yu4e99f532014-08-25 19:40:57 -07004.. contents::
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -07005
6Identity, Key and Certificates
Yingdi Yu4e99f532014-08-25 19:40:57 -07007------------------------------
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -07008
Yingdi Yu4e99f532014-08-25 19:40:57 -07009All keys, certificates and their corresponding identities are managed by :ndn-cxx:`KeyChain`.
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -070010
Yingdi Yu4e99f532014-08-25 19:40:57 -070011An real world **identity** can be expressed by a namespace. (e.g.,
12``/ndn/edu/ucla/alice``, or ``/ndn/edu/ucla/BoelterHall/4805``).
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -070013
Yingdi Yu4e99f532014-08-25 19:40:57 -070014**Keys** belonging to an identity are named under the identity's namespace, with a unique
15**KeyId**::
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -070016
Yingdi Yu4e99f532014-08-25 19:40:57 -070017 /<identity_name>/[KeyId]
18
19For now, only two types of KeyId are specified: ``ksk-[timestamp]`` and
20``dsk-[timestamp]``. The first type of KeyId is used to denote Key-Signing-Key (KSK)
21which is supposed to have a long lifetime. The second type of KeyId is used to denote
22Data-Signing-Key (DSK) which is supposed to have a short lifetime. Both types of KeyId
23use timestamps (number of milliseconds since unix epoch) to provide relative uniqueness of
24key names. Replacing timestamp with key hash can bring stronger uniqueness but on the
25cost of longer name. Therefore, key hash is not used for now. For example,
26``/ndn/edu/ucla/alice/ksk-1234567890`` or
27``/ndn/edu/ucla/BoelterHall/4805/dsk-1357924680``.
28
29An identity may have more than one keys associated with it. For example, one may have a
30KSK to sign other keys and a DSK to sign data packets, or one may periodically replace its
31expired DSK/KSK with a new key.
32
33The private part of a key ("private key"), is stored in a :ndn-cxx:`Trusted Platform
34Module (TPM) <SecTpm>`. The public part ("public key"), is managed in a
35:ndn-cxx:`Public-key Information Base (PIB) <SecPublicInfo>`. The most important
36information managed by PIB is **certificates** of public keys. A certificate binds a
37public key to its key name or the corresponding identity. The signer (or issuer) of a
38certificate vouches for the binding through its own signature. With different signers
39vouching for the binding, a public key may have more than one certificates.
40
41The 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
42public key name will be broken into two parts:
43
44- The first part ("authoritative namespace") will be put before a name component ``KEY``
45 which serves as an application tag
46- The second part ("label") will be put between ``KEY`` and ``ID-CERT`` which serves as an
47 indicator of certificate.
48
49A version number of the certificate is appended after ``ID-CERT``. For example,
50``/ndn/edu/ucla/KEY/alice/ksk-1234567890/ID-CERT/%FD%01`` or
51``/ndn/edu/ucla/BoelterHall/4805/KEY/dsk-1357924680/ID-CERT/%FD%44``.
52
53The :ndn-cxx:`NDN certificate <IdentityCertificate>` is just an ordinary `NDN-TLV Data
54packet <http://named-data.net/doc/ndn-tlv/data.html>`_, with the content part in DER
55encoding that resembles X.509 certificate:
56
57.. code-block:: cpp
58
59 // NDN-TLV Encoding
60 Certificate ::= DATA-TLV TLV-LENGTH
61 Name
62 MetaInfo (= CertificateMetaInfo)
63 Content (= CertificateContent)
64 Signature
65
66 CertificateMetaInfo ::= META-INFO-TYPE TLV-LENGTH
67 ContentType (= KEY)
68 FreshnessPeriod (= ?)
69
70
71 CertificateContent ::= CONTENT-TYPE TLV-LENGTH
72 CertificateDerPayload
73
74
75 // DER Encoding
76 CertificateDerPayload ::= SEQUENCE {
77 validity Validity,
78 subject Name,
79 subjectPubKeyInfo SubjectPublicKeyInfo,
80 extension Extensions OPTIONAL }
81
82 Validity ::= SEQUENCE {
83 notBefore Time,
84 notAfter Time }
85
86 Time ::= CHOICE {
87 GeneralizedTime }
88
89 Name ::= CHOICE {
90 RDNSequence }
91
92 RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
93
94 RelativeDistinguishedName ::=
95 SET OF AttributeTypeAndValue
96
97 SubjectPublicKeyInfo ::= SEQUENCE {
98 algorithm AlgorithmIdentifier
99 keybits BIT STRING }
100
101 Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
102
103See `RFC 3280 <http://www.ietf.org/rfc/rfc3280.txt>`_ for more details about DER field
104definitions.
105
106Signing
107-------
108
109Key Management
110%%%%%%%%%%%%%%
111
112Create Identity/Keys/Certificate
113~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
114
115The simplest way to initialize an identity and its key and certificate is to call
116:ndn-cxx:`KeyChain::createIdentity`
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -0700117
118.. code-block:: cpp
119
120 KeyChain keyChain;
Yingdi Yu4e99f532014-08-25 19:40:57 -0700121 Name defaultCertName = keyChain.createIdentity(identity);
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -0700122
Yingdi Yu4e99f532014-08-25 19:40:57 -0700123This method guarantees that the default key and certificate of the supplied identity
124always exist in the KeyChain. This method checks if the supplied identity has already had
125a default key and a default certificate and returns the default certificate name if
126exists. If the default certificate is missing, KeyChain will automatically create a
127self-signed certificate of the default key. If the default key is missing, KeyChain will
128automatically create a new key and set it as the default key and create a self-signed
129certificate as well.
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -0700130
131Create Keys Manually
132~~~~~~~~~~~~~~~~~~~~
133
Yingdi Yu4e99f532014-08-25 19:40:57 -0700134One can call :ndn-cxx:`KeyChain::generateRsaKeyPair` to generate an RSA key pair or
135:ndn-cxx:`KeyChain::generateEcdsaKeyPair` to generate an ECDSA key. Note that generated
136key pair is not set as the default key of the identity, so you need to set it manually by
137calling :ndn-cxx:`KeyChain::setDefaultKeyNameForIdentity`. There is also a helper method
138:ndn-cxx:`KeyChain::generateRsaKeyPairAsDefault`, which combines the two steps into one.
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -0700139
140.. code-block:: cpp
141
142 KeyChain keyChain;
143 Name alice("/ndn/test/alice");
144
145 Name aliceKeyName = keyChain.generateRSAKeyPair(alice);
146 keyChain.setDefaultKeyNameForIdentity(aliceKeyName);
147
Yingdi Yu4e99f532014-08-25 19:40:57 -0700148 // Now the key with the name aliceKeyName2 becomes alice's default key
149 Name aliceKeyName2 = keyChain.generateRSAKeyPairAsDefault(alice);
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -0700150
151Create Identity Certificate Manually
152~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
153
Yingdi Yu4e99f532014-08-25 19:40:57 -0700154If you have created a key pair, you can generate a self-signed certificate for the key by
155calling :ndn-cxx:`KeyChain::selfSign`.
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -0700156
157.. code-block:: cpp
158
159 KeyChain keyChain;
160 Name aliceKeyName("/ndn/test/alice/ksk-1394129695025");
161
162 shared_ptr<IdentityCertificate> aliceCert = keyChain.selfSign(aliceKeyName);
163
Yingdi Yu4e99f532014-08-25 19:40:57 -0700164You can sign a public key using a different key:
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -0700165
166.. code-block:: cpp
167
168 KeyChain keyChain;
169
Yingdi Yu4e99f532014-08-25 19:40:57 -0700170 shared_ptr<IdentityCertificate> certificate =
171 keyChain.prepareUnsignedIdentityCertificate(publicKeyName, publicKey,
172 signingIdentity,
173 notBefore, notAfter,
174 subjectDescription, prefix
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -0700175
Yingdi Yu4e99f532014-08-25 19:40:57 -0700176 keyChain.signByIdentity(*certificate, signingIdentity);
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -0700177
Yingdi Yu4e99f532014-08-25 19:40:57 -0700178Signing Data
179%%%%%%%%%%%%
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -0700180
Yingdi Yu4e99f532014-08-25 19:40:57 -0700181Although the security library does not have the intelligence to automatically determine
182the signing key for each data packet, it still provides a mechanism, called **Default
183Signing Settings**, to facilitate signing process.
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -0700184
Yingdi Yu4e99f532014-08-25 19:40:57 -0700185The basic signing process in the security library would be like this: create :ndn-cxx:`KeyChain`
186instance and supply the data packet and signing certificate name to :ndn-cxx:`KeyChain::sign`
187method.
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -0700188
Yingdi Yu4e99f532014-08-25 19:40:57 -0700189.. code-block:: cpp
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -0700190
Yingdi Yu4e99f532014-08-25 19:40:57 -0700191 KeyChain keyChain;
192 keyChain.sign(dataPacket, signingCertificateName);
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -0700193
Yingdi Yu4e99f532014-08-25 19:40:57 -0700194The :ndn-cxx:`KeyChain` instance will
195
196- construct ``SignatureInfo`` using the signing certificate name;
197- look up the corresponding private key in :ndn-cxx:`TPM <SecTpm>`;
198- sign the data packet if the private key exists.
199
200The basic process, however, requires application developers to supply the exact
201certificate name. Such a process has two shortages: first, it might be difficult to
202remember the certificate name; second, application developers have to be aware of
203certificate update and key roll-over. Therefore, the security library provides another
204signing process in which application developers only need to supply the signing identity:
205
206.. code-block:: cpp
207
208 KeyChain keyChain;
209 keyChain.signByIdentity(dataPacket, signingIdentity);
210
211The :ndn-cxx:`KeyChain` instance will
212
213- determine the default key of the signing identity;
214- determine the default certificate of the key;
215- construct ``SignatureInfo`` using the default certificate name;
216- look up the corresponding private key in :ndn-cxx:`TPM <SecTpm>`;
217- sign the data packet if the private key exists.
218
219The process above requires that each identity has a default key and that each key has a
220default certificate. All these default settings is managed in :ndn-cxx:`PIB
221<SecPublicInfo>`, one can get/set these default settings through :ndn-cxx:`KeyChain`
222directly:
223
224.. code-block:: cpp
225
226 KeyChain keyChain;
227 Name defaultKeyName = keyChain.getDefaultKeyNameForIdentity(identity);
228 Name defaultCertName = keyChain.getDefaultCertificateNameForKey(keyName);
229
230 keyChain.setDefaultKeyNameForIdentity(keyName);
231 keyChain.setDefaultCertificateNameForKey(certificateName);
232
233There is even a default identity which will be used when no identity information is
234supplied in signing method:
235
236.. code-block:: cpp
237
238 KeyChain keyChain;
239 keyChain.sign(dataPacket);
240
241And default identity can be got/set through :ndn-cxx:`KeyChain` as well:
242
243.. code-block:: cpp
244
245 KeyChain keyChain;
246 Name defaultIdentity = keyChain.getDefaultIdentity();
247 keyChain.setDefaultIdentity(identity);
248
249
250Signing Interests
251%%%%%%%%%%%%%%%%%
252
253The process of signing Interests according to the :doc:`Signed Interest specification
254<signed-interest>` is exactly the same as the process of signing Data packets:
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -0700255
256.. code-block:: cpp
257
258 KeyChain keyChain;
259
Yingdi Yu4e99f532014-08-25 19:40:57 -0700260 keyChain.sign(interest, signingCertName);
261 keyChain.signByIdentity(interest, signingIdentity);
262 keyChain.sign(interest);
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -0700263
Yingdi Yu4e99f532014-08-25 19:40:57 -0700264Validation
265----------
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -0700266
Yingdi Yu4e99f532014-08-25 19:40:57 -0700267Interest and Data validation is done through a **Validator**. :ndn-cxx:`Validator` is a virtual
268class, two pure virtual methods must be implemented in order to construct a working
269validator:
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -0700270
271.. code-block:: cpp
272
Yingdi Yu4e99f532014-08-25 19:40:57 -0700273 class Validator
274 {
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -0700275 ...
276 protected:
277 virtual void
Yingdi Yu4e99f532014-08-25 19:40:57 -0700278 checkPolicy(const Data& data,
279 int nSteps,
280 const OnDataValidated& onValidated,
281 const OnDataValidationFailed& onValidationFailed,
282 std::vector<shared_ptr<ValidationRequest> >& nextSteps) = 0;
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -0700283
284 virtual void
Yingdi Yu4e99f532014-08-25 19:40:57 -0700285 checkPolicy(const Interest& interest,
286 int nSteps,
287 const OnInterestValidated& onValidated,
288 const OnInterestValidationFailed& onValidationFailed,
289 std::vector<shared_ptr<ValidationRequest> >& nextSteps) = 0;
290 ...
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -0700291 };
292
Yingdi Yu4e99f532014-08-25 19:40:57 -0700293What should be implemented in these two methods is to check:
294
295- whether the packet and signer comply with trust policies;
296- whether their signature can be verified.
297
298If the packet can be validated, the ``onValidated`` callback should be invoked, otherwise
299the ``onValidationFailed`` callback should be invoked. If more information (e.g., other
300certificates) is needed, express the request for missing information in one or more
301``ValidationRequest`` and push them into ``nextSteps``.
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -0700302
303.. code-block:: cpp
304
Yingdi Yu4e99f532014-08-25 19:40:57 -0700305 class ValidationRequest
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -0700306 {
307 public:
Yingdi Yu4e99f532014-08-25 19:40:57 -0700308 Interest m_interest; // The Interest for the requested data/certificate.
309 OnDataValidated m_onValidated; // Callback when the retrieved certificate is authenticated.
310 OnDataValidationFailed m_onDataValidated; // Callback when the retrieved certificate cannot be authenticated.
311 int m_nRetries; // The number of retries when the interest times out.
312 int m_nStep; // The number of validation steps that have been performed.
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -0700313 };
314
Yingdi Yu4e99f532014-08-25 19:40:57 -0700315Besides the two ``Validator::checkPolicy`` methods, the ``Validator`` also provides three
316hooks to control packet validation in a finer granularity.
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -0700317
318.. code-block:: cpp
319
Yingdi Yu4e99f532014-08-25 19:40:57 -0700320 class Validator
321 {
322 ...
323 protected:
324 virtual shared_ptr<const Data>
325 preCertificateValidation(const Data& data);
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -0700326
Yingdi Yu4e99f532014-08-25 19:40:57 -0700327 virtual void
328 onTimeout(const Interest& interest,
329 int nRemainingRetries,
330 const OnFailure& onFailure,
331 const shared_ptr<ValidationRequest>& validationRequest);
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -0700332
Yingdi Yu4e99f532014-08-25 19:40:57 -0700333 virtual void
334 afterCheckPolicy(const std::vector<shared_ptr<ValidationRequest> >& nextSteps,
335 const OnFailure& onFailure);
336 ...
Alexander Afanasyev7c6aeb02014-04-10 19:59:19 -0700337 };
Yingdi Yu4e99f532014-08-25 19:40:57 -0700338
339``Validator::preCertificateValidation`` is triggered before validating requested
340certificate. The Data supplied matches the interest in the ``ValidationRequest``. It may
341be certificate or a data encapsulating certificate. This hook returns a data (actually
342certificate) that is will be passed as Data into ``Validator::validate``;
343
344``Validator::onTimeout`` is triggered when interest for certificate times out. The logic
345to handle the timeout can be implemented in this hook. One could invoke onFailure or
346re-express the interest.
347
348``Validator::afterCheckPolicy`` is invoked after ``Validator::checkPolicy`` is done. One
349can implement the logic of how to process the set of ValidationRequests according to its
350trust model.
351
352Configuration-based Validator
353%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
354
355In most cases, the trust model of applications are simple. However, it is not trivial to
356implement the two ``Validator::checkPolicy`` methods. Therefore, we provide a more
357developer-friendly configuration-based validator, ``ValidatorConfig``. With
358``ValidatorConfig``, one can express the trust model using a policy language in a
359configuration file. See :doc:`security-validator-config` for more details.