def onReceivedElement(self, element): """ This is called by the transport's ElementReader to process an entire received Data or Interest element. :param element: The bytes of the incoming element. :type element: An array type with int elements """ lpPacket = None if element[0] == Tlv.LpPacket_LpPacket: # Decode the LpPacket and replace element with the fragment. lpPacket = LpPacket() # Set copy False so that the fragment is a slice which will be # copied below. The header fields are all integers and don't need to # be copied. TlvWireFormat.get().decodeLpPacket(lpPacket, element, False) element = lpPacket.getFragmentWireEncoding().buf() # First, decode as Interest or Data. data = None decoder = TlvDecoder(element) if decoder.peekType(Tlv.Data, len(element)): data = Data() data.wireDecode(element, TlvWireFormat.get()) if lpPacket != None: data.setLpPacket(lpPacket) # Now process as Interest or Data. if data != None: if self._onBtleData: self._onBtleData(data)
def onReceivedElement(self, element): """ This is called by the transport's ElementReader to process an entire received Data or Interest element. :param element: The bytes of the incoming element. :type element: An array type with int elements """ # First, decode as Interest or Data. interest = None data = None decoder = TlvDecoder(element) if decoder.peekType(Tlv.Interest, len(element)): interest = Interest() interest.wireDecode(element, TlvWireFormat.get()) elif decoder.peekType(Tlv.Data, len(element)): data = Data() data.wireDecode(element, TlvWireFormat.get()) # Now process as Interest or Data. if interest != None: # Call all interest filter callbacks which match. for i in range(len(self._interestFilterTable)): entry = self._interestFilterTable[i] if entry.getFilter().doesMatch(interest.getName()): includeFilter = True # Use getcallargs to test if onInterest accepts 5 args. try: inspect.getcallargs(entry.getOnInterest(), None, None, None, None, None) except TypeError: # Assume onInterest is old-style with 4 arguments. includeFilter = False if includeFilter: try: entry.getOnInterest()( entry.getFilter().getPrefix(), interest, entry.getFace(), entry.getInterestFilterId(), entry.getFilter()) except: logging.exception("Error in onInterest") else: # Old-style onInterest without the filter argument. We # still pass a Face instead of Transport since Face also # has a send method. try: entry.getOnInterest()( entry.getFilter().getPrefix(), interest, entry.getFace(), entry.getInterestFilterId()) except: logging.exception("Error in onInterest") elif data != None: pendingInterests = self._extractEntriesForExpressedInterest( data.getName()) for pendingInterest in pendingInterests: try: pendingInterest.getOnData()(pendingInterest.getInterest(), data) except: logging.exception("Error in onData")
def wireDecode(self, buf, wireFormat=None): """ Override to call the base class wireDecode then check the certificate format. :param input: The array with the bytes to decode. If input is not a Blob, then copy the bytes to save the defaultWireEncoding (otherwise take another pointer to the same Blob). :type input: A Blob or an array type with int elements :param wireFormat: (optional) A WireFormat object used to decode this Data object. If omitted, use WireFormat.getDefaultWireFormat(). :type wireFormat: A subclass of WireFormat """ Data.wireDecode(self, buf, wireFormat) self._checkFormat()
def wireDecode(self, buf, wireFormat = None): """ Override to call the base class wireDecode then check the certificate format. :param input: The array with the bytes to decode. If input is not a Blob, then copy the bytes to save the defaultWireEncoding (otherwise take another pointer to the same Blob). :type input: A Blob or an array type with int elements :param wireFormat: (optional) A WireFormat object used to decode this Data object. If omitted, use WireFormat.getDefaultWireFormat(). :type wireFormat: A subclass of WireFormat """ Data.wireDecode(self, buf, wireFormat) self._checkFormat()
def wireDecode(self, input, wireFormat = None): """ Override to call the base class wireDecode then populate the list of delegations from the content. :param input: The array with the bytes to decode. :type input: A Blob or an array type with int elements :param wireFormat: (optional) A WireFormat object used to decode this DelegationSet. If omitted, use WireFormat.getDefaultWireFormat(). :type wireFormat: A subclass of WireFormat """ if wireFormat == None: # Don't use a default argument since getDefaultWireFormat can change. wireFormat = WireFormat.getDefaultWireFormat() Data.wireDecode(self, input, wireFormat) if self.getMetaInfo().getType() != ContentType.LINK: raise RuntimeError( "Link.wireDecode: MetaInfo ContentType is not LINK.") self._delegations.wireDecode(self.getContent())
def wireDecode(self, input, wireFormat=None): """ Override to call the base class wireDecode then populate the list of delegations from the content. :param input: The array with the bytes to decode. :type input: A Blob or an array type with int elements :param wireFormat: (optional) A WireFormat object used to decode this DelegationSet. If omitted, use WireFormat.getDefaultWireFormat(). :type wireFormat: A subclass of WireFormat """ if wireFormat == None: # Don't use a default argument since getDefaultWireFormat can change. wireFormat = WireFormat.getDefaultWireFormat() Data.wireDecode(self, input, wireFormat) if self.getMetaInfo().getType() != ContentType.LINK: raise RuntimeError( "Link.wireDecode: MetaInfo ContentType is not LINK.") self._delegations.wireDecode(self.getContent())
def onReceivedElement(self, element): """ This is called by the transport's ElementReader to process an entire received Data or Interest element. :param element: The bytes of the incoming element. :type element: An array type with int elements """ # The type codes for TLV Interest and Data packets are chosen to not # conflict with the first byte of a binary XML packet, so we canjust # look at the first byte. if not (element[0] == Tlv.Interest or element[0] == Tlv.Data): # Ignore non-TLV elements. return # First, decode as Interest or Data. interest = None data = None decoder = TlvDecoder(element) if decoder.peekType(Tlv.Interest, len(element)): interest = Interest() interest.wireDecode(element, TlvWireFormat.get()) elif decoder.peekType(Tlv.Data, len(element)): data = Data() data.wireDecode(element, TlvWireFormat.get()) # Now process as Interest or Data. if interest != None: entry = self._getEntryForRegisteredPrefix(interest.getName()) if entry != None: entry.getOnInterest()(entry.getPrefix(), interest, self._transport, entry.getRegisteredPrefixId()) elif data != None: pendingInterests = self._extractEntriesForExpressedInterest( data.getName()) for pendingInterest in pendingInterests: pendingInterest.getOnData()(pendingInterest.getInterest(), data)
def onReceivedElement(self, element): """ This is called by the transport's ElementReader to process an entire received Data or Interest element. :param element: The bytes of the incoming element. :type element: An array type with int elements """ # The type codes for TLV Interest and Data packets are chosen to not # conflict with the first byte of a binary XML packet, so we canjust # look at the first byte. if not (element[0] == Tlv.Interest or element[0] == Tlv.Data): # Ignore non-TLV elements. return # First, decode as Interest or Data. interest = None data = None decoder = TlvDecoder(element) if decoder.peekType(Tlv.Interest, len(element)): interest = Interest() interest.wireDecode(element, TlvWireFormat.get()) elif decoder.peekType(Tlv.Data, len(element)): data = Data() data.wireDecode(element, TlvWireFormat.get()) # Now process as Interest or Data. if interest != None: entry = self._getEntryForRegisteredPrefix(interest.getName()) if entry != None: entry.getOnInterest()( entry.getPrefix(), interest, self._transport, entry.getRegisteredPrefixId()) elif data != None: pendingInterests = self._extractEntriesForExpressedInterest( data.getName()) for pendingInterest in pendingInterests: pendingInterest.getOnData()(pendingInterest.getInterest(), data)
def wireDecode(self, buf, wireFormat = None): """ Make sure the fields are populated after decoding """ Data.wireDecode(self, buf, wireFormat) self.decode()
def onReceivedElement(self, element): """ This is called by the transport's ElementReader to process an entire received Data or Interest element. :param element: The bytes of the incoming element. :type element: An array type with int elements """ lpPacket = None if element[0] == Tlv.LpPacket_LpPacket: # Decode the LpPacket and replace element with the fragment. lpPacket = LpPacket() # Set copy False so that the fragment is a slice which will be # copied below. The header fields are all integers and don't need to # be copied. TlvWireFormat.get().decodeLpPacket(lpPacket, element, False) element = lpPacket.getFragmentWireEncoding().buf() # First, decode as Interest or Data. interest = None data = None decoder = TlvDecoder(element) if decoder.peekType(Tlv.Interest, len(element)): interest = Interest() interest.wireDecode(element, TlvWireFormat.get()) if lpPacket != None: interest.setLpPacket(lpPacket) elif decoder.peekType(Tlv.Data, len(element)): data = Data() data.wireDecode(element, TlvWireFormat.get()) if lpPacket != None: data.setLpPacket(lpPacket) if lpPacket != None: # We have decoded the fragment, so remove the wire encoding to save # memory. lpPacket.setFragmentWireEncoding(Blob()) networkNack = NetworkNack.getFirstHeader(lpPacket) if networkNack != None: if interest == None: # We got a Nack but not for an Interest, so drop the packet. return pendingInterests = [] self._pendingInterestTable.extractEntriesForNackInterest( interest, pendingInterests) for pendingInterest in pendingInterests: try: pendingInterest.getOnNetworkNack()( pendingInterest.getInterest(), networkNack) except: logging.exception("Error in onNetworkNack") # We have processed the network Nack packet. return # Now process as Interest or Data. if interest != None: # Call all interest filter callbacks which match. matchedFilters = [] self._interestFilterTable.getMatchedFilters( interest, matchedFilters) for i in range(len(matchedFilters)): entry = matchedFilters[i] includeFilter = True onInterestCall = entry.getOnInterest() # If onInterest is not a function nor a method assumes it is a # calleable object if (not inspect.isfunction(onInterestCall) and not inspect.ismethod(onInterestCall)): onInterestCall = onInterestCall.__call__ # Use getcallargs to test if onInterest accepts 5 args. try: inspect.getcallargs(onInterestCall, None, None, None, None, None) except TypeError: # Assume onInterest is old-style with 4 arguments. includeFilter = False if includeFilter: try: entry.getOnInterest()(entry.getFilter().getPrefix(), interest, entry.getFace(), entry.getInterestFilterId(), entry.getFilter()) except: logging.exception("Error in onInterest") else: # Old-style onInterest without the filter argument. We # still pass a Face instead of Transport since Face also # has a send method. try: entry.getOnInterest()(entry.getFilter().getPrefix(), interest, entry.getFace(), entry.getInterestFilterId()) except: logging.exception("Error in onInterest") elif data != None: pendingInterests = [] self._pendingInterestTable.extractEntriesForExpressedInterest( data, pendingInterests) for pendingInterest in pendingInterests: try: pendingInterest.getOnData()(pendingInterest.getInterest(), data) except: logging.exception("Error in onData")
def onReceivedElement(self, element): """ This is called by the transport's ElementReader to process an entire received Data or Interest element. :param element: The bytes of the incoming element. :type element: An array type with int elements """ lpPacket = None if element[0] == Tlv.LpPacket_LpPacket: # Decode the LpPacket and replace element with the fragment. lpPacket = LpPacket() # Set copy False so that the fragment is a slice which will be # copied below. The header fields are all integers and don't need to # be copied. TlvWireFormat.get().decodeLpPacket(lpPacket, element, False) element = lpPacket.getFragmentWireEncoding().buf() # First, decode as Interest or Data. interest = None data = None decoder = TlvDecoder(element) if decoder.peekType(Tlv.Interest, len(element)): interest = Interest() interest.wireDecode(element, TlvWireFormat.get()) if lpPacket != None: interest.setLpPacket(lpPacket) elif decoder.peekType(Tlv.Data, len(element)): data = Data() data.wireDecode(element, TlvWireFormat.get()) if lpPacket != None: data.setLpPacket(lpPacket) if lpPacket != None: # We have decoded the fragment, so remove the wire encoding to save # memory. lpPacket.setFragmentWireEncoding(Blob()) networkNack = NetworkNack.getFirstHeader(lpPacket) if networkNack != None: if interest == None: # We got a Nack but not for an Interest, so drop the packet. return pendingInterests = [] self._pendingInterestTable.extractEntriesForNackInterest( interest, pendingInterests) for pendingInterest in pendingInterests: try: pendingInterest.getOnNetworkNack()( pendingInterest.getInterest(), networkNack) except: logging.exception("Error in onNetworkNack") # We have processed the network Nack packet. return # Now process as Interest or Data. if interest != None: # Call all interest filter callbacks which match. matchedFilters = [] self._interestFilterTable.getMatchedFilters(interest, matchedFilters) for i in range(len(matchedFilters)): entry = matchedFilters[i] includeFilter = True onInterestCall = entry.getOnInterest() # If onInterest is not a function nor a method assumes it is a # calleable object if (not inspect.isfunction(onInterestCall) and not inspect.ismethod(onInterestCall)): onInterestCall = onInterestCall.__call__ # Use getcallargs to test if onInterest accepts 5 args. try: inspect.getcallargs(onInterestCall, None, None, None, None, None) except TypeError: # Assume onInterest is old-style with 4 arguments. includeFilter = False if includeFilter: try: entry.getOnInterest()( entry.getFilter().getPrefix(), interest, entry.getFace(), entry.getInterestFilterId(), entry.getFilter()) except: logging.exception("Error in onInterest") else: # Old-style onInterest without the filter argument. We # still pass a Face instead of Transport since Face also # has a send method. try: entry.getOnInterest()( entry.getFilter().getPrefix(), interest, entry.getFace(), entry.getInterestFilterId()) except: logging.exception("Error in onInterest") elif data != None: pendingInterests = [] self._pendingInterestTable.extractEntriesForExpressedInterest( data, pendingInterests) for pendingInterest in pendingInterests: try: pendingInterest.getOnData()(pendingInterest.getInterest(), data) except: logging.exception("Error in onData")
def onReceivedElement(self, element): """ This is called by the transport's ElementReader to process an entire received Data or Interest element. :param element: The bytes of the incoming element. :type element: An array type with int elements """ # The type codes for TLV Interest and Data packets are chosen to not # conflict with the first byte of a binary XML packet, so we canjust # look at the first byte. if not (element[0] == Tlv.Interest or element[0] == Tlv.Data): # Ignore non-TLV elements. # Assume it is Binary XML. if not WireFormat.ENABLE_NDNX: raise RuntimeError( "BinaryXmlWireFormat (NDNx) is deprecated. To enable while you upgrade your network to use NDN-TLV, set WireFormat.ENABLE_NDNX = True") return # First, decode as Interest or Data. interest = None data = None decoder = TlvDecoder(element) if decoder.peekType(Tlv.Interest, len(element)): interest = Interest() interest.wireDecode(element, TlvWireFormat.get()) elif decoder.peekType(Tlv.Data, len(element)): data = Data() data.wireDecode(element, TlvWireFormat.get()) # Now process as Interest or Data. if interest != None: # Call all interest filter callbacks which match. for i in range(len(self._interestFilterTable)): entry = self._interestFilterTable[i] if entry.getFilter().doesMatch(interest.getName()): includeFilter = True # Use getcallargs to test if onInterest accepts 5 args. try: inspect.getcallargs(entry.getOnInterest(), None, None, None, None, None) except TypeError: # Assume onInterest is old-style with 4 arguments. includeFilter = False if includeFilter: entry.getOnInterest()( entry.getFilter().getPrefix(), interest, entry.getFace(), entry.getInterestFilterId(), entry.getFilter()) else: # Old-style onInterest without the filter argument. We # still pass a Face instead of Transport since Face also # has a send method. entry.getOnInterest()( entry.getFilter().getPrefix(), interest, entry.getFace(), entry.getInterestFilterId()) elif data != None: pendingInterests = self._extractEntriesForExpressedInterest( data.getName()) for pendingInterest in pendingInterests: pendingInterest.getOnData()(pendingInterest.getInterest(), data)
def onReceivedElement(self, element): """ This is called by the transport's ElementReader to process an entire received Data or Interest element. :param element: The bytes of the incoming element. :type element: An array type with int elements """ lpPacket = None if element[0] == Tlv.LpPacket_LpPacket: # Decode the LpPacket and replace element with the fragment. lpPacket = LpPacket() # Set copy False so that the fragment is a slice which will be # copied below. The header fields are all integers and don't need to # be copied. TlvWireFormat.get().decodeLpPacket(lpPacket, element, False) element = lpPacket.getFragmentWireEncoding().buf() # First, decode as Interest or Data. interest = None data = None decoder = TlvDecoder(element) if decoder.peekType(Tlv.Interest, len(element)): interest = Interest() interest.wireDecode(element, TlvWireFormat.get()) if lpPacket != None: interest.setLpPacket(lpPacket) elif decoder.peekType(Tlv.Data, len(element)): data = Data() data.wireDecode(element, TlvWireFormat.get()) if lpPacket != None: data.setLpPacket(lpPacket) if lpPacket != None: # We have decoded the fragment, so remove the wire encoding to save # memory. lpPacket.setFragmentWireEncoding(Blob()) networkNack = NetworkNack.getFirstHeader(lpPacket) if networkNack != None: if interest == None: # We got a Nack but not for an Interest, so drop the packet. return pendingInterests = [] self._pendingInterestTable.extractEntriesForNackInterest( interest, pendingInterests) for pendingInterest in pendingInterests: try: pendingInterest.getOnNetworkNack()( pendingInterest.getInterest(), networkNack) except: logging.exception("Error in onNetworkNack") # We have processed the network Nack packet. return # Now process as Interest or Data. if interest != None: self._dispatchInterest(interest) elif data != None: self._satisfyPendingInterests(data)
class SafeBag(object): """ There are three forms of the SafeBag constructor: SafeBag(certificate, privateKeyBag) - Create a SafeBag with the given certificate and private key. SafeBag(keyName, privateKeyBag, publicKeyEncoding [, password, digestAlgorithm, wireFormat]) - Create a SafeBag with given private key and a new self-signed certificate for the given public key. SafeBag(input) - Create a SafeBag by decoding the input as an NDN-TLV SafeBag. :param Data certificate: The certificate data packet (used only for SafeBag(certificate, privateKeyBag)). This copies the object. :param Blob privateKeyBag: The encoded private key. If encrypted, this is a PKCS #8 EncryptedPrivateKeyInfo. If not encrypted, this is an unencrypted PKCS #8 PrivateKeyInfo. :param password: (optional) The password for decrypting the private key in order to sign the self-signed certificate, which should have characters in the range of 1 to 127. If the password is supplied, use it to decrypt the PKCS #8 EncryptedPrivateKeyInfo. If the password is omitted or None, privateKeyBag is an unencrypted PKCS #8 PrivateKeyInfo. :type password: an array which implements the buffer protocol :param int digestAlgorithm: (optional) The digest algorithm for signing the self-signed certificate. If omitted, use DigestAlgorithm.SHA256 . :type digestAlgorithm: int from the DigestAlgorithm enum :param WireFormat wireFormat: (optional) A WireFormat object used to encode the self-signed certificate in order to sign it. If omitted, use WireFormat.getDefaultWireFormat(). :param input: The array with the bytes to decode. :type input: A Blob or an array type with int elements """ def __init__(self, arg1, privateKeyBag = None, publicKeyEncoding = None, password = None, digestAlgorithm = DigestAlgorithm.SHA256, wireFormat = None): if isinstance(arg1, Name): keyName = arg1 if wireFormat == None: # Don't use a default argument since getDefaultWireFormat can change. wireFormat = WireFormat.getDefaultWireFormat() self._certificate = SafeBag._makeSelfSignedCertificate( keyName, privateKeyBag, publicKeyEncoding, password, digestAlgorithm, wireFormat) self._privateKeyBag = privateKeyBag elif isinstance(arg1, Data): # The certificate is supplied. self._certificate = Data(arg1) self._privateKeyBag = privateKeyBag else: # Assume the first argument is the encoded SafeBag. self.wireDecode(arg1) def getCertificate(self): """ Get the certificate data packet. :return: The certificate as a Data packet. If you need to process it as a certificate object then you must create a new CertificateV2(data). :rtype: Data """ return self._certificate def getPrivateKeyBag(self): """ Get the encoded private key. :return: The encoded private key. If encrypted, this is a PKCS #8 EncryptedPrivateKeyInfo. If not encrypted, this is an unencrypted PKCS #8 PrivateKeyInfo. :rtype: Blob """ return self._privateKeyBag def wireDecode(self, input): """ Decode the input as an NDN-TLV SafeBag and update this object. :param input: The array with the bytes to decode. :type input: A Blob or an array type with int elements """ if isinstance(input, Blob): input = input.buf() # Decode directly as TLV. We don't support the WireFormat abstraction # because this isn't meant to go directly on the wire. decoder = TlvDecoder(input) endOffset = decoder.readNestedTlvsStart(Tlv.SafeBag_SafeBag) # Get the bytes of the certificate and decode. certificateBeginOffset = decoder.getOffset() certificateEndOffset = decoder.readNestedTlvsStart(Tlv.Data) decoder.seek(certificateEndOffset) self._certificate = Data() self._certificate.wireDecode( decoder.getSlice(certificateBeginOffset, certificateEndOffset), TlvWireFormat.get()) self._privateKeyBag = Blob( decoder.readBlobTlv(Tlv.SafeBag_EncryptedKeyBag), True) decoder.finishNestedTlvs(endOffset) def wireEncode(self, wireFormat = None): """ Encode this as an NDN-TLV SafeBag. :return: The encoded byte array as a Blob. :rtype: Blob """ # Encode directly as TLV. We don't support the WireFormat abstraction # because this isn't meant to go directly on the wire. encoder = TlvEncoder(256) saveLength = len(encoder) # Encode backwards. encoder.writeBlobTlv( Tlv.SafeBag_EncryptedKeyBag, self._privateKeyBag.buf()) # Add the entire Data packet encoding as is. encoder.writeBuffer( self._certificate.wireEncode(TlvWireFormat.get()).buf()) encoder.writeTypeAndLength( Tlv.SafeBag_SafeBag, len(encoder) - saveLength) return Blob(encoder.getOutput(), False) @staticmethod def _makeSelfSignedCertificate( keyName, privateKeyBag, publicKeyEncoding, password, digestAlgorithm, wireFormat): certificate = CertificateV2() # Set the name. now = Common.getNowMilliseconds() certificateName = Name(keyName) certificateName.append("self").appendVersion(int(now)) certificate.setName(certificateName) # Set the MetaInfo. certificate.getMetaInfo().setType(ContentType.KEY) # Set a one-hour freshness period. certificate.getMetaInfo().setFreshnessPeriod(3600 * 1000.0) # Set the content. publicKey = PublicKey(publicKeyEncoding) certificate.setContent(publicKey.getKeyDer()) # Create a temporary in-memory Tpm and import the private key. tpm = Tpm("", "", TpmBackEndMemory()) tpm._importPrivateKey(keyName, privateKeyBag.toBytes(), password) # Set the signature info. if publicKey.getKeyType() == KeyType.RSA: certificate.setSignature(Sha256WithRsaSignature()) elif publicKey.getKeyType() == KeyType.EC: certificate.setSignature(Sha256WithEcdsaSignature()) else: raise ValueError("Unsupported key type") signatureInfo = certificate.getSignature() KeyLocator.getFromSignature(signatureInfo).setType(KeyLocatorType.KEYNAME) KeyLocator.getFromSignature(signatureInfo).setKeyName(keyName) # Set a 20-year validity period. ValidityPeriod.getFromSignature(signatureInfo).setPeriod( now, now + 20 * 365 * 24 * 3600 * 1000.0) # Encode once to get the signed portion. encoding = certificate.wireEncode(wireFormat) signatureBytes = tpm.sign(encoding.toSignedBytes(), keyName, digestAlgorithm) signatureInfo.setSignature(signatureBytes) # Encode again to include the signature. certificate.wireEncode(wireFormat) return certificate
class SafeBag(object): """ There are three forms of the SafeBag constructor: SafeBag(certificate, privateKeyBag) - Create a SafeBag with the given certificate and private key. SafeBag(keyName, privateKeyBag, publicKeyEncoding [, password, digestAlgorithm, wireFormat]) - Create a SafeBag with given private key and a new self-signed certificate for the given public key. SafeBag(input) - Create a SafeBag by decoding the input as an NDN-TLV SafeBag. :param Data certificate: The certificate data packet (used only for SafeBag(certificate, privateKeyBag)). This copies the object. :param Blob privateKeyBag: The encoded private key. If encrypted, this is a PKCS #8 EncryptedPrivateKeyInfo. If not encrypted, this is an unencrypted PKCS #8 PrivateKeyInfo. :param password: (optional) The password for decrypting the private key in order to sign the self-signed certificate, which should have characters in the range of 1 to 127. If the password is supplied, use it to decrypt the PKCS #8 EncryptedPrivateKeyInfo. If the password is omitted or None, privateKeyBag is an unencrypted PKCS #8 PrivateKeyInfo. :type password: an array which implements the buffer protocol :param int digestAlgorithm: (optional) The digest algorithm for signing the self-signed certificate. If omitted, use DigestAlgorithm.SHA256 . :type digestAlgorithm: int from the DigestAlgorithm enum :param WireFormat wireFormat: (optional) A WireFormat object used to encode the self-signed certificate in order to sign it. If omitted, use WireFormat.getDefaultWireFormat(). :param input: The array with the bytes to decode. :type input: A Blob or an array type with int elements """ def __init__(self, arg1, privateKeyBag=None, publicKeyEncoding=None, password=None, digestAlgorithm=DigestAlgorithm.SHA256, wireFormat=None): if isinstance(arg1, Name): keyName = arg1 if wireFormat == None: # Don't use a default argument since getDefaultWireFormat can change. wireFormat = WireFormat.getDefaultWireFormat() self._certificate = SafeBag._makeSelfSignedCertificate( keyName, privateKeyBag, publicKeyEncoding, password, digestAlgorithm, wireFormat) self._privateKeyBag = privateKeyBag elif isinstance(arg1, Data): # The certificate is supplied. self._certificate = Data(arg1) self._privateKeyBag = privateKeyBag else: # Assume the first argument is the encoded SafeBag. self.wireDecode(arg1) def getCertificate(self): """ Get the certificate data packet. :return: The certificate as a Data packet. If you need to process it as a certificate object then you must create a new CertificateV2(data). :rtype: Data """ return self._certificate def getPrivateKeyBag(self): """ Get the encoded private key. :return: The encoded private key. If encrypted, this is a PKCS #8 EncryptedPrivateKeyInfo. If not encrypted, this is an unencrypted PKCS #8 PrivateKeyInfo. :rtype: Blob """ return self._privateKeyBag def wireDecode(self, input): """ Decode the input as an NDN-TLV SafeBag and update this object. :param input: The array with the bytes to decode. :type input: A Blob or an array type with int elements """ if isinstance(input, Blob): input = input.buf() # Decode directly as TLV. We don't support the WireFormat abstraction # because this isn't meant to go directly on the wire. decoder = TlvDecoder(input) endOffset = decoder.readNestedTlvsStart(Tlv.SafeBag_SafeBag) # Get the bytes of the certificate and decode. certificateBeginOffset = decoder.getOffset() certificateEndOffset = decoder.readNestedTlvsStart(Tlv.Data) decoder.seek(certificateEndOffset) self._certificate = Data() self._certificate.wireDecode( decoder.getSlice(certificateBeginOffset, certificateEndOffset), TlvWireFormat.get()) self._privateKeyBag = Blob( decoder.readBlobTlv(Tlv.SafeBag_EncryptedKeyBag), True) decoder.finishNestedTlvs(endOffset) def wireEncode(self, wireFormat=None): """ Encode this as an NDN-TLV SafeBag. :return: The encoded byte array as a Blob. :rtype: Blob """ # Encode directly as TLV. We don't support the WireFormat abstraction # because this isn't meant to go directly on the wire. encoder = TlvEncoder(256) saveLength = len(encoder) # Encode backwards. encoder.writeBlobTlv(Tlv.SafeBag_EncryptedKeyBag, self._privateKeyBag.buf()) # Add the entire Data packet encoding as is. encoder.writeBuffer( self._certificate.wireEncode(TlvWireFormat.get()).buf()) encoder.writeTypeAndLength(Tlv.SafeBag_SafeBag, len(encoder) - saveLength) return Blob(encoder.getOutput(), False) @staticmethod def _makeSelfSignedCertificate(keyName, privateKeyBag, publicKeyEncoding, password, digestAlgorithm, wireFormat): certificate = CertificateV2() # Set the name. now = Common.getNowMilliseconds() certificateName = Name(keyName) certificateName.append("self").appendVersion(int(now)) certificate.setName(certificateName) # Set the MetaInfo. certificate.getMetaInfo().setType(ContentType.KEY) # Set a one-hour freshness period. certificate.getMetaInfo().setFreshnessPeriod(3600 * 1000.0) # Set the content. publicKey = PublicKey(publicKeyEncoding) certificate.setContent(publicKey.getKeyDer()) # Create a temporary in-memory Tpm and import the private key. tpm = Tpm("", "", TpmBackEndMemory()) tpm._importPrivateKey(keyName, privateKeyBag.toBytes(), password) # Set the signature info. if publicKey.getKeyType() == KeyType.RSA: certificate.setSignature(Sha256WithRsaSignature()) elif publicKey.getKeyType() == KeyType.EC: certificate.setSignature(Sha256WithEcdsaSignature()) else: raise ValueError("Unsupported key type") signatureInfo = certificate.getSignature() KeyLocator.getFromSignature(signatureInfo).setType( KeyLocatorType.KEYNAME) KeyLocator.getFromSignature(signatureInfo).setKeyName(keyName) # Set a 20-year validity period. ValidityPeriod.getFromSignature(signatureInfo).setPeriod( now, now + 20 * 365 * 24 * 3600 * 1000.0) # Encode once to get the signed portion. encoding = certificate.wireEncode(wireFormat) signatureBytes = tpm.sign(encoding.toSignedBytes(), keyName, digestAlgorithm) signatureInfo.setSignature(signatureBytes) # Encode again to include the signature. certificate.wireEncode(wireFormat) return certificate