blob: 5af7b0cfcf71a05beb7e245235f7e708e5fd71b7 [file] [log] [blame]
Alexander Afanasyev5ba90362013-07-15 19:58:38 -07001## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
2#
3# Copyright (c) 2011-2013, Regents of the University of California
4# Alexander Afanasyev
5#
6# GNU 3.0 license, See the LICENSE file for more information
7#
8# Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
9#
10
11#
12# Based on PyCCN code, copyrighted and licensed as follows
13#
14# Copyright (c) 2011-2013, Regents of the University of California
15# BSD license, See the COPYING file for more information
16# Written by: Derek Kulinski <takeda@takeda.tk>
17# Jeff Burke <jburke@ucla.edu>
18#
19
20from . import _ndn
21import utils
22
23class ContentType(utils.Enum):
24 _prefix = "ndn"
25
26CONTENT_DATA = ContentType.new_flag('CONTENT_DATA', 0x0C04C0)
27CONTENT_ENCR = ContentType.new_flag('CONTENT_ENCR', 0x10D091)
28CONTENT_GONE = ContentType.new_flag('CONTENT_GONE', 0x18E344)
29CONTENT_KEY = ContentType.new_flag('CONTENT_KEY', 0x28463F)
30CONTENT_LINK = ContentType.new_flag('CONTENT_LINK', 0x2C834A)
31CONTENT_NACK = ContentType.new_flag('CONTENT_NACK', 0x34008A)
32
33class ContentObject(object):
34 def __init__(self, name = None, content = None, signed_info = None):
35 self.name = name
36 self.content = content
37
38 self.signedInfo = signed_info or SignedInfo()
39 self.digestAlgorithm = None # Default
40
41 # generated
42 self.signature = None
43 self.verified = False
44
45 # py-ndn
46 self.ccn = None # Reference to CCN object
47 self.ccn_data_dirty = True
48 self.ccn_data = None # backing charbuf
49
50 # this is the finalization step
51 # must pass a key here, there is no "default key" because
52 # an NDN Face is not required to create the content object
53 # thus there is no access to the ccn library keystore.
54 #
55 def sign(self, key):
56 self.ccn_data = _ndn.encode_ContentObject(self, self.name.ccn_data, \
57 self.content, self.signedInfo.ccn_data, key)
58 self.ccn_data_dirty = False
59
60 def digest(self):
61 return _ndn.digest_contentobject(self.ccn_data)
62
63 def verify_content(self, handle):
64 return _ndn.verify_content(handle.ccn_data, self.ccn_data)
65
66 def verify_signature(self, key):
67 return _ndn.verify_signature(self.ccn_data, key.ccn_data_public)
68
69 def matchesInterest(self, interest):
70 return _ndn.content_matches_interest(self.ccn_data, interest.ccn_data)
71
72 def __setattr__(self, name, value):
73 if name == 'name' or name == 'content' or name == 'signedInfo' or name == 'digestAlgorithm':
74 self.ccn_data_dirty = True
75
76 if name == 'content':
77 object.__setattr__(self, name, _ndn.content_to_bytes(value))
78 else:
79 object.__setattr__(self, name, value)
80
81 def __getattribute__(self, name):
82 if name == "ccn_data":
83 if object.__getattribute__(self, 'ccn_data_dirty'):
84 raise _ndn.CCNContentObjectError("Call sign() to finalize \
85 before accessing ccn_data for a ContentObject")
86 return object.__getattribute__(self, name)
87
88 # Where do we support versioning and segmentation?
89
90 def __str__(self):
91 ret = []
92 ret.append("Name: %s" % self.name)
93 ret.append("Content: %r" % self.content)
94 ret.append("DigestAlg: %r" % self.digestAlgorithm)
95 ret.append("SignedInfo: %s" % self.signedInfo)
96 ret.append("Signature: %s" % self.signature)
97 return "\n".join(ret)
98
99 def __repr__(self):
100 args = []
101
102 if self.name is not None:
103 args += ["name=%r" % self.name]
104
105 if self.content is not None:
106 args += ["content=%r" % self.content]
107
108 if self.signedInfo is not None:
109 args += ["signed_info=%r" % self.signedInfo]
110
111 if self.signature is not None:
112 args += ["<signed>"]
113
114 return "ndn.ContentObject(%s)" % ", ".join(args)
115
116 def get_ccnb(self):
117 return _ndn.dump_charbuf(self.ccn_data)
118
119 @staticmethod
120 def from_ccnb (ccnb):
121 return _ndn.ContentObject_obj_from_ccn_buffer (ccnb)
122
123class Signature(object):
124 def __init__(self):
125 self.digestAlgorithm = None
126 self.witness = None
127 self.signatureBits = None
128
129 # py-ndn
130 self.ccn_data_dirty = False
131 self.ccn_data = None
132
133 def __setattr__(self, name, value):
134 if name == 'witness' or name == 'signatureBits' or name == 'digestAlgorithm':
135 self.ccn_data_dirty = True
136 object.__setattr__(self, name, value)
137
138 def __getattribute__(self, name):
139 if name == "ccn_data":
140 if object.__getattribute__(self, 'ccn_data_dirty'):
141 self.ccn_data = _ndn.Signature_obj_to_ccn(self)
142 self.ccn_data_dirty = False
143 return object.__getattribute__(self, name)
144
145 def __str__(self):
146 res = []
147 res.append("digestAlgorithm = %s" % self.digestAlgorithm)
148 res.append("witness = %s" % self.witness)
149 res.append("signatureBits = %r" % self.signatureBits)
150 return "\n".join(res)
151
152class SignedInfo(object):
153 def __init__(self, key_digest = None, key_locator = None, type = CONTENT_DATA,
154 freshness = None, final_block = None, py_timestamp = None,
155 timestamp = None):
156
157 self.publisherPublicKeyDigest = key_digest
158
159 if py_timestamp is not None:
160 if timestamp:
161 raise ValueError("You can define only timestamp or py_timestamp")
162 self.timeStamp = utils.py2ccn_time(py_timestamp)
163 else:
164 self.timeStamp = timestamp
165
166 self.type = type
167 self.freshnessSeconds = freshness
168 self.finalBlockID = final_block
169 self.keyLocator = key_locator
170
171 # py-ndn
172 self.ccn_data_dirty = True
173 self.ccn_data = None # backing charbuf
174
175 def __setattr__(self, name, value):
176 if name != "ccn_data" and name != "ccn_data_dirty":
177 self.ccn_data_dirty = True
178
179 if name == "type" and type(value) is not ContentType:
180 value = ContentType(value)
181
182 object.__setattr__(self, name, value)
183
184 def __getattribute__(self, name):
185 if name == "ccn_data":
186 if object.__getattribute__(self, 'ccn_data_dirty'):
187 key_locator = self.keyLocator.ccn_data if self.keyLocator else None
188 self.ccn_data = _ndn.SignedInfo_to_ccn(\
189 self.publisherPublicKeyDigest, self.type, self.timeStamp, \
190 self.freshnessSeconds or (-1), self.finalBlockID, key_locator)
191 self.ccn_data_dirty = False
192
193 if name == "py_timestamp":
194 ts = self.timeStamp
195 if ts is None:
196 return None
197 return None if ts is None else utils.ccn2py_time(ts)
198
199 return object.__getattribute__(self, name)
200
201 def __repr__(self):
202 args = []
203
204 if self.publisherPublicKeyDigest is not None:
205 args += ["key_digest=%r" % self.publisherPublicKeyDigest]
206 if self.keyLocator is not None:
207 args += ["key_locator=%r" % self.keyLocator]
208 if self.type is not None:
209 args += ["type=%r" % self.type]
210 if self.freshnessSeconds is not None:
211 args += ["freshness=%r" % self.freshnessSeconds]
212 if self.finalBlockID is not None:
213 args += ["final_block=%r" % self.finalBlockID]
214 if self.timeStamp is not None:
215 args += ["py_timestamp=%r" % self.py_timestamp]
216
217 return "ndn.SignedInfo(%s)" % ", ".join(args)
218
219#
220#
221# These are not used in signing in Python (all the info needed is in SignedInfo)
222# But it is here in case the parsing of the c library version of signing params
223# is needed.
224
225class SigningParams(object):
226 CCN_SP_TEMPL_TIMESTAMP = 0x0001
227 CCN_SP_TEMPL_FINAL_BLOCK_ID = 0x0002
228 CCN_SP_TEMPL_FRESHNESS = 0x0004
229 CCN_SP_TEMPL_KEY_LOCATOR = 0x0008
230 CCN_SP_FINAL_BLOCK = 0x0010
231 CCN_SP_OMIT_KEY_LOCATOR = 0x0020
232
233 def __init__(self):
234 self.flags; # Use the CCN_SP flags above
235 self.type; # Content type, really should be somewhere else, it's not that related to signing
236 self.freshness;
237
238 # These three are only relevant, for now, if they are coming *from* a c object
239 # otherwise, API version is filled in from CCN_SIGNING_PARAMS_INIT and
240 # both template and key will come from the ContentObject's SignedInfo object
241 self.apiVersion;
242 self.template; # SignedInfo referred to by this content object,
243 self.key; # Key to use - this should filled by a lookup against content object's signedinfo,
244
245 # py-ndn
246 self.ccn_data_dirty = False
247 self.ccn_data = None # backing ccn_signing_params
248
249 def __setattr__(self, name, value):
250 if name != "ccn_data" and name != "ccn_data_dirty":
251 self.ccn_data_dirty = True
252 object.__setattr__(self, name, value)
253
254 def __getattribute__(self, name):
255 if name == "ccn_data":
256 if object.__getattribute__(self, 'ccn_data_dirty'):
257 self.ccn_data = _ndn._ndn_SigningParams_to_ccn(self)
258 self.ccn_data_dirty = False
259 return object.__getattribute__(self, name)
260
261 def __get_ccn(self):
262 pass
263 # Call ccn_signed_info_create