def _decryptDKey(self, dKeyData, onPlainText, onError): """ Decrypt dKeyData. :param Data dKeyData: The D-KEY data packet. :param onPlainText: When the data packet is decrypted, this calls onPlainText(decryptedBlob) with the decrypted blob. :type onPlainText: function object :param onError: This calls onError(errorCode, message) for an error, where errorCode is from EncryptError.ErrorCode and message is a str. :type onError: function object """ # Get encrypted content. dataContent = dKeyData.getContent() # Process the nonce. # dataContent is a sequence of the two EncryptedContent. encryptedNonce = EncryptedContent() try: encryptedNonce.wireDecode(dataContent) except Exception as ex: try: onError(EncryptError.ErrorCode.InvalidEncryptedFormat, repr(ex)) except: logging.exception("Error in onError") return consumerKeyName = encryptedNonce.getKeyLocator().getKeyName() # Get consumer decryption key. try: consumerKeyBlob = self._getDecryptionKey(consumerKeyName) except Exception as ex: Consumer._callOnError(onError, EncryptError.ErrorCode.NoDecryptKey, "Database error: " + repr(ex)) return if consumerKeyBlob.size() == 0: try: onError(EncryptError.ErrorCode.NoDecryptKey, "The desired consumer decryption key in not in the database") except: logging.exception("Error in onError") return # Process the D-KEY. # Use the size of encryptedNonce to find the start of encryptedPayload. encryptedPayloadBlob = Blob( dataContent.buf()[encryptedNonce.wireEncode().size():], False) if encryptedPayloadBlob.size() == 0: try: onError(EncryptError.ErrorCode.InvalidEncryptedFormat, "The data packet does not satisfy the D-KEY packet format") except: logging.exception("Error in onError") # Decrypt the D-KEY. Consumer._decrypt( encryptedNonce, consumerKeyBlob, lambda nonceKeyBits: Consumer._decrypt( encryptedPayloadBlob, nonceKeyBits, onPlainText, onError), onError)
def sign(self, data, keyName, digestAlgorithm = DigestAlgorithm.SHA256): """ Fetch the private key for keyName and sign the data, returning a signature Blob. :param data: Pointer the input byte buffer to sign. :type data: An array type with int elements :param Name keyName: The name of the signing key. :param digestAlgorithm: (optional) the digest algorithm. If omitted, use DigestAlgorithm.SHA256. :type digestAlgorithm: int from DigestAlgorithm :return: The signature Blob. :rtype: Blob """ keyURI = keyName.toUri() if not self.doesKeyExist(keyName, KeyClass.PRIVATE): raise SecurityException( "FilePrivateKeyStorage.sign: private key doesn't exist") if digestAlgorithm != DigestAlgorithm.SHA256: raise SecurityException( "FilePrivateKeyStorage.sign: Unsupported digest algorithm") # Read the private key. base64Content = None with open(self.nameTransform(keyURI, ".pri")) as keyFile: base64Content = keyFile.read() der = Blob(base64.b64decode(base64Content), False) # Decode the PKCS #8 key to get the algorithm OID. parsedNode = DerNode.parse(der.buf(), 0) pkcs8Children = parsedNode.getChildren() algorithmIdChildren = DerNode.getSequence(pkcs8Children, 1).getChildren() oidString = algorithmIdChildren[0].toVal() privateKey = serialization.load_der_private_key( der.toBytes(), password = None, backend = default_backend()) # Sign the data. data = Blob(data, False).toBytes() if (oidString == PublicKey.RSA_ENCRYPTION_OID or oidString == PublicKey.EC_ENCRYPTION_OID): if oidString == PublicKey.RSA_ENCRYPTION_OID: signer = privateKey.signer(padding.PKCS1v15(), hashes.SHA256()) else: signer = privateKey.signer(ec.ECDSA(hashes.SHA256())) signer.update(data) signature = signer.finalize() return Blob(bytearray(signature), False) else: raise SecurityException( "FilePrivateKeyStorage.sign: Unrecognized private key type")
def capture(self, interest, transport): # print("capture cmd received start processing") interestName = interest.getName() if (interestName.size() >= 7): #right format segmentIndex = interestName.get(6).toSegment() # print "request segmentIndex : ",segmentIndex if segmentIndex == 0: # print("a new picture") #request a new picture self.stream = io.BytesIO() self.stream.flush() self.segmentList = [] self.dataList = [] self.camera.capture(self.stream, 'jpeg') #print("photo caputred in stream") imageBytes = self.stream.getvalue() print ("imageBytes %d" % len(imageBytes)) #segmentation self.segmentNumber = len(imageBytes)/(self.segmentSize+1)+1 print("segmentNumber: %d" % self.segmentNumber) for i in range(self.segmentNumber): startIndex = i*self.segmentSize if (i != self.segmentNumber -1): segBytes = imageBytes[startIndex:(startIndex+self.segmentSize)] else: segBytes = imageBytes[startIndex:] #self.segmentList.append(segBytes) newName = interestName.getPrefix(-1).appendSegment(i) #print newName.toUri() data = Data(newName) metaInfo = MetaInfo() metaInfo.setFinalBlockId(Blob.fromRawStr(str(self.segmentNumber-1))) data.setMetaInfo(metaInfo) #data.setContent(Blob.fromRawStr(self.segmentList[i])) data.setContent(Blob.fromRawStr(segBytes)) self.dataList.append(data) self.sendData(self.dataList[0], transport, sign=False) else: self.sendData(self.dataList[segmentIndex], transport, sign=False)
def __init__(self, value = None): if isinstance(value, Interest): # Copy the values. self._name = ChangeCounter(Name(value.getName())) self._minSuffixComponents = value._minSuffixComponents self._maxSuffixComponents = value._maxSuffixComponents self._didSetCanBePrefix = value._didSetCanBePrefix self._keyLocator = ChangeCounter(KeyLocator(value.getKeyLocator())) self._exclude = ChangeCounter(Exclude(value.getExclude())) self._childSelector = value._childSelector self._mustBeFresh = value._mustBeFresh self._nonce = value.getNonce() self._interestLifetimeMilliseconds = value._interestLifetimeMilliseconds self._forwardingHint = ChangeCounter(DelegationSet(value.getForwardingHint())) self._applicationParameters = value._applicationParameters self._linkWireEncoding = value._linkWireEncoding self._linkWireEncodingFormat = value._linkWireEncodingFormat self._link = ChangeCounter(None) if value._link.get() != None: self._link.set(Link(value._link.get())) self._selectedDelegationIndex = value._selectedDelegationIndex self._defaultWireEncoding = value.getDefaultWireEncoding() self._defaultWireEncodingFormat = value._defaultWireEncodingFormat else: self._name = ChangeCounter(Name(value)) self._minSuffixComponents = None self._maxSuffixComponents = None if Interest._defaultCanBePrefix else 1 # _didSetCanBePrefix is True if the app already called setDefaultCanBePrefix(). self._didSetCanBePrefix = Interest._didSetDefaultCanBePrefix self._keyLocator = ChangeCounter(KeyLocator()) self._exclude = ChangeCounter(Exclude()) self._childSelector = None self._mustBeFresh = True self._nonce = Blob() self._interestLifetimeMilliseconds = None self._forwardingHint = ChangeCounter(DelegationSet()) self._applicationParameters = Blob() self._linkWireEncoding = Blob() self._linkWireEncodingFormat = None self._link = ChangeCounter(None) self._selectedDelegationIndex = None self._defaultWireEncoding = SignedBlob() self._defaultWireEncodingFormat = None self._getNonceChangeCount = 0 self._getDefaultWireEncodingChangeCount = 0 self._changeCount = 0 self._lpPacket = None
def getLink(self): """ Get the link object. If necessary, decode it from the link wire encoding. :return: The link object, or None if not specified. :rtype: Link :raises ValueError: For error decoding the link wire encoding (if necessary). :deprecated: Use getForwardingHint. """ if self._link.get() != None: return self._link.get() elif not self._linkWireEncoding.isNull(): # Decode the link object from linkWireEncoding_. link = Link() link.wireDecode(self._linkWireEncoding, self._linkWireEncodingFormat) self._link.set(link) # Clear _linkWireEncoding since it is now managed by the link object. self._linkWireEncoding = Blob() self._linkWireEncodingFormat = None return link else: return None
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 __init__(self, keyDer = None): # TODO: Implementation of managed properties? if keyDer == None: self._keyDer = Blob() self._keyType = None return self._keyDer = keyDer # Get the public key OID. oidString = "" try: parsedNode = DerNode.parse(keyDer.buf(), 0) rootChildren = parsedNode.getChildren() algorithmIdChildren = DerNode.getSequence( rootChildren, 0).getChildren() oidString = algorithmIdChildren[0].toVal() except DerDecodingException as ex: raise UnrecognizedKeyFormatException( "PublicKey.decodeKeyType: Error decoding the public key" + str(ex)) # Verify that the we can decode. if oidString == self.RSA_ENCRYPTION_OID: self._keyType = KeyType.RSA RSA.importKey(keyDer.toRawStr()) elif oidString == self.EC_ENCRYPTION_OID: self._keyType = KeyType.ECDSA # TODO: Check EC decoding. else: raise UnrecognizedKeyFormatException( "PublicKey.decodeKeyType: Unrecognized OID " + oidString)
def __init__(self): self._socket = None self._socketPoller = None self._buffer = bytearray(Common.MAX_NDN_PACKET_SIZE) # Create a Blob and take its buf() since this creates a memoryview # which is more efficient for slicing. self._bufferView = Blob(self._buffer, False).buf() self._elementReader = None
def clear(self): """ Clear the fields and set the type to None. """ self._type = None self._keyName.get().clear() self._keyData = Blob() self._changeCount += 1
def _CFDataToBlob(cfData): length = cf.CFDataGetLength(cfData) array = (c_byte * length)() cf.CFDataGetBytes(cfData, CFRange(0, length), array) # Convert from signed byte to unsigned byte. unsignedArray = [(x if x >= 0 else x + 256) for x in array] return Blob(unsignedArray, False)
def murmurHash3Blob(nHashSeed, value): """ Interpret the value as a Blob and use it to compute the MurmurHash3. :param int nHashSeed: The hash seed. :param Blob value: If value is not already a Blob, use Blob(value) :return: The hash value. :rtype: int """ if not have_mmh3: raise RuntimeError( "murmurHash3Blob: Need to 'sudo python -m pip install mmh3'") if not isinstance(value, Blob): value = Blob(value, False) return mmh3.hash(value.toBytes(), nHashSeed, signed = False)
def __init__(self, value): if isinstance(value, EncryptKey): # Make a deep copy. self._keyBits = value._keyBits else: keyBits = value self._keyBits = keyBits if isinstance(keyBits, Blob) else Blob(keyBits)
def decrypt(key, cipherText): """ Use the macOS Keychain key to decrypt. :param c_void_p key: The macOS Keychain private key. :param cipherText: The cipher text byte buffer. :type cipherText: an array which implements the buffer protocol :return: The decrypted data. :rtype: Blob """ osx = Osx.get() dataRef = None decryptor = None output = None try: # We need a str (Python 2) or bytes (Python 3). Use Blob to convert data. dataStr = Blob(cipherText, False).toBytes() dataRef = c_void_p(cf.CFDataCreate(None, dataStr, len(cipherText))) error = c_void_p() decryptor = osx._security.SecDecryptTransformCreate( key, pointer(error)) if error.value != None: raise TpmBackEndOsx.Error("Failed to create the decryptor") osx._security.SecTransformSetAttribute( decryptor, osx._kSecTransformInputAttributeName, dataRef, pointer(error)) if error.value != None: raise TpmBackEndOsx.Error("Failed to configure the decryptor") osx._security.SecTransformSetAttribute(decryptor, osx._kSecPaddingKey, osx._kSecPaddingOAEPKey, pointer(error)) if error.value != None: raise TpmBackEndOsx.Error( "Failed to configure the decryptor #2") output = osx._security.SecTransformExecute(decryptor, pointer(error)) if error.value != None: raise TpmBackEndOsx.Error( "Failed to decrypt the cipherText. Try using the Keychain Access application to set the access control of the private key to \"Allow all applications to access this item\"." ) if output == None: raise TpmBackEndOsx.Error("The output is NULL") return TpmBackEndOsx._CFDataToBlob(output) finally: if dataRef != None: cf.CFRelease(dataRef) if decryptor != None: cf.CFRelease(decryptor) if output != None: cf.CFRelease(output)
def encode(self): """ Encode the contents of the certificate in DER format and set the Content and MetaInfo fields. """ root = self.toDer() outVal = root.encode() self.setContent(Blob(outVal)) self.getMetaInfo().setType(ContentType.KEY)
def __init__(self, value = None): if type(value) is Name.Component: # Use the existing Blob in the other Component. self._value = value._value elif value == None: self._value = Blob([]) else: # Blob will make a copy. self._value = value if isinstance(value, Blob) else Blob(value)
def unsetLink(self): """ Clear the link wire encoding and link object so that getLink() returns None. :return: This Interest so that you can chain calls to update values. :rtype: Interest """ return self.setLinkWireEncoding(Blob(), None)
def set(self, uri): """ Parse the uri according to the NDN URI Scheme and set the name with the components. :param str uri: The URI string. """ self.clear() uri = uri.strip() if len(uri) == 0: return iColon = uri.find(':') if iColon >= 0: # Make sure the colon came before a '/'. iFirstSlash = uri.find('/') if iFirstSlash < 0 or iColon < iFirstSlash: # Omit the leading protocol such as ndn: uri = uri[iColon + 1:].strip() # Trim the leading slash and possibly the authority. if uri[0] == '/': if len(uri) >= 2 and uri[1] == '/': # Strip the authority following "//". iAfterAuthority = uri.find('/', 2) if iAfterAuthority < 0: # Unusual case: there was only an authority. return else: uri = uri[iAfterAuthority + 1:].strip() else: uri = uri[1:].strip() iComponentStart = 0 # Unescape the components. sha256digestPrefix = "sha256digest=" while iComponentStart < len(uri): iComponentEnd = uri.find('/', iComponentStart) if iComponentEnd < 0: iComponentEnd = len(uri) if (uri[iComponentStart:iComponentStart + len(sha256digestPrefix)] == sha256digestPrefix): hexString = uri[iComponentStart + len(sha256digestPrefix):].strip() component = Name.Component.fromImplicitSha256Digest( Blob(bytearray.fromhex(hexString), False)) else: component = Name.Component( Name.fromEscapedString(uri, iComponentStart, iComponentEnd)) # Ignore illegal components. This also gets rid of a trailing '/'. if not component.getValue().isNull(): self.append(component) iComponentStart = iComponentEnd + 1
def setFragmentWireEncoding(self, fragmentWireEncoding): """ Set the fragment wire encoding. :param Blob fragmentWireEncoding: The fragment wire encoding or an isNull Blob if not specified. """ self._fragmentWireEncoding = (fragmentWireEncoding if isinstance( fragmentWireEncoding, Blob) else Blob(fragmentWireEncoding))
def loadPkcs8(self, encoding, keyType=None): """ Load the unencrypted private key from a buffer with the PKCS #8 encoding. This replaces any existing private key in this object. :param encoding: The byte buffer with the private key encoding. :type encoding: str, or an array type with int elements which is converted to str :param KeyType keyType: (optional) The KeyType, such as KeyType.RSA. If omitted or None, then partially decode the private key to determine the key type. :raises TpmPrivateKey.Error: For errors decoding the key. """ if keyType == None: # Decode the PKCS #8 DER to find the algorithm OID. oidString = None try: parsedNode = DerNode.parse(Blob(encoding, False).buf()) pkcs8Children = parsedNode.getChildren() algorithmIdChildren = DerNode.getSequence(pkcs8Children, 1).getChildren() oidString = "" + algorithmIdChildren[0].toVal() except Exception as ex: raise TpmPrivateKey.Error( "Cannot decode the PKCS #8 private key: " + str(ex)) if oidString == TpmPrivateKey.EC_ENCRYPTION_OID: keyType = KeyType.ECDSA elif oidString == TpmPrivateKey.RSA_ENCRYPTION_OID: keyType = KeyType.RSA else: raise TpmPrivateKey.Error( "loadPkcs8: Unrecognized private key OID: " + oidString) if keyType == KeyType.ECDSA or keyType == KeyType.RSA: self._privateKey = serialization.load_der_private_key( Blob(encoding, False).toBytes(), password=None, backend=default_backend()) else: raise TpmPrivateKey.Error("loadPkcs8: Unrecognized keyType: " + str(keyType)) self._keyType = keyType
def __init__(self, value = None): if type(value) is Interest: # Copy the values. self._name = ChangeCounter(Name(value.getName())) self._minSuffixComponents = value._minSuffixComponents self._maxSuffixComponents = value._maxSuffixComponents self._keyLocator = ChangeCounter(KeyLocator(value.getKeyLocator())) self._exclude = ChangeCounter(Exclude(value.getExclude())) self._childSelector = value._childSelector self._mustBeFresh = value._mustBeFresh self._nonce = value.getNonce() self._interestLifetimeMilliseconds = value._interestLifetimeMilliseconds self._linkWireEncoding = value._linkWireEncoding self._linkWireEncodingFormat = value._linkWireEncodingFormat self._link = ChangeCounter(None) if value._link.get() != None: self._link.set(Link(value._link.get())) self._selectedDelegationIndex = value._selectedDelegationIndex self._defaultWireEncoding = value.getDefaultWireEncoding() self._defaultWireEncodingFormat = value._defaultWireEncodingFormat else: self._name = ChangeCounter(Name(value) if type(value) is Name else Name()) self._minSuffixComponents = None self._maxSuffixComponents = None self._keyLocator = ChangeCounter(KeyLocator()) self._exclude = ChangeCounter(Exclude()) self._childSelector = None self._mustBeFresh = True self._nonce = Blob() self._interestLifetimeMilliseconds = None self._linkWireEncoding = Blob() self._linkWireEncodingFormat = None self._link = ChangeCounter(None) self._selectedDelegationIndex = None self._defaultWireEncoding = SignedBlob() self._defaultWireEncodingFormat = None self._getNonceChangeCount = 0 self._getDefaultWireEncodingChangeCount = 0 self._changeCount = 0 self._lpPacket = None
def __init__(self, value=None): if isinstance(value, Interest): # Copy the values. self._name = ChangeCounter(Name(value.getName())) self._canBePrefix = value._canBePrefix self._hopLimit = value._hopLimit self._keyLocator = ChangeCounter(KeyLocator(value.getKeyLocator())) self._mustBeFresh = value._mustBeFresh self._nonce = value.getNonce() self._interestLifetimeMilliseconds = value._interestLifetimeMilliseconds self._forwardingHint = ChangeCounter( DelegationSet(value.getForwardingHint())) self._applicationParameters = value._applicationParameters self._linkWireEncoding = value._linkWireEncoding self._linkWireEncodingFormat = value._linkWireEncodingFormat self._link = ChangeCounter(None) if value._link.get() != None: self._link.set(Link(value._link.get())) self._selectedDelegationIndex = value._selectedDelegationIndex self._defaultWireEncoding = value.getDefaultWireEncoding() self._defaultWireEncodingFormat = value._defaultWireEncodingFormat else: self._name = ChangeCounter(Name(value)) self._canBePrefix = Interest._defaultCanBePrefix self._hopLimit = Interest._defaultHopLimit self._keyLocator = ChangeCounter(KeyLocator()) self._mustBeFresh = False self._nonce = Blob() self._interestLifetimeMilliseconds = None self._forwardingHint = ChangeCounter(DelegationSet()) self._applicationParameters = Blob() self._linkWireEncoding = Blob() self._linkWireEncodingFormat = None self._link = ChangeCounter(None) self._selectedDelegationIndex = None self._defaultWireEncoding = SignedBlob() self._defaultWireEncodingFormat = None self._getNonceChangeCount = 0 self._getDefaultWireEncodingChangeCount = 0 self._changeCount = 0 self._lpPacket = None
def setContent(self, content): """ Set the content to the given value. :param content: The array with the content bytes. If content is not a Blob, then create a new Blob to copy the bytes (otherwise take another pointer to the same Blob). :type content: A Blob or an array type with int elements """ self._content = content if isinstance(content, Blob) else Blob(content)
def _updateHex(messageDigest, hex): """ Convert the hex string to bytes and call messageDigest.update. :param messageDigest: The digest to update. :type messageDigest: A HashContext object, for example from hashes.Hash(hashes.SHA256(), backend=default_backend()). :param str hex: The hex string. """ messageDigest.update(Blob(bytearray.fromhex(hex), False).toBytes())
def _getPublicKeyDer(self, keyLocator, failureReason): """ Look in the storage for the public key with the name in the KeyLocator. If the public key can't be found, return and empty Blob. :param KeyLocator keyLocator: The KeyLocator. :param Array<str> failureReason: If can't find the public key, set failureReason[0] to the failure reason string. :return: The public key DER or an empty Blob if not found. :rtype: Blob """ if (keyLocator.getType() == KeyLocatorType.KEYNAME and self._identityStorage != None): try: # Assume the key name is a certificate name. keyName = IdentityCertificate.certificateNameToPublicKeyName( keyLocator.getKeyName()) except Exception: failureReason[0] = ( "Cannot get a public key name from the certificate named: " + keyLocator.getKeyName().toUri()) return Blob() try: return self._identityStorage.getKey(keyName) except SecurityException: failureReason[0] = ( "The identityStorage doesn't have the key named " + keyName.toUri()) return Blob() elif (keyLocator.getType() == KeyLocatorType.KEYNAME and self._pibImpl != None): try: return self._pibImpl.getKeyBits(keyLocator.getKeyName()) except SecurityException: failureReason[0] = ("The pibImpl doesn't have the key named " + keyName.toUri()) return Blob() else: # Can't find a key to verify. failureReason[ 0] = "The signature KeyLocator doesn't have a key name" return Blob()
def sign(self, data, keyName, digestAlgorithm=DigestAlgorithm.SHA256): """ Fetch the private key for keyName and sign the data, returning a signature Blob. :param data: The input byte buffer to sign. :type data: an array which implements the buffer protocol :param Name keyName: The name of the signing key. :param digestAlgorithm: (optional) the digest algorithm. If omitted, use DigestAlgorithm.SHA256. :type digestAlgorithm: int from DigestAlgorithm :return: The signature Blob. :rtype: Blob :raises SecurityException: if can't find the private key with keyName. """ if digestAlgorithm != DigestAlgorithm.SHA256: raise SecurityException( "MemoryPrivateKeyStorage.sign: Unsupported digest algorithm") # Find the private key. keyUri = keyName.toUri() if not keyUri in self._privateKeyStore: raise SecurityException( "MemoryPrivateKeyStorage: Cannot find private key " + keyUri) privateKey = self._privateKeyStore[keyUri] # Sign the data. data = Blob(data, False).toBytes() if (privateKey.getKeyType() == KeyType.RSA or privateKey.getKeyType() == KeyType.ECDSA): if privateKey.getKeyType() == KeyType.RSA: signer = privateKey.getPrivateKey().signer( padding.PKCS1v15(), hashes.SHA256()) else: signer = privateKey.getPrivateKey().signer( ec.ECDSA(hashes.SHA256())) signer.update(data) return Blob(bytearray(signer.finalize()), False) else: raise SecurityException( "MemoryPrivateKeyStorage.sign: Unrecognized private key type")
def main(filepath=None, maxSuccess=None): with open('attacker2.csv', 'rb') as f: dataArray = [] readdata = f.read(8*1024) dataArray.append(readdata) manifestData = {} count = 0 seq = 0 while readdata: digest = hashes.Hash(hashes.SHA256(), backend=default_backend()) digest.update(readdata) manifestData[(seq+count)]=(str(digest.finalize())) #c = sys.getsizeof(manifestData) count = count + 1 if count == 100: #print(manifestData) s=json.dumps(manifestData).encode('utf-8') manifest_packet = Manifest(Name("prefix/data/"+str(seq))) manifest_packet.setContent(s) k = json.loads(Blob(manifest_packet.getContent()).toBytes().decode('utf-8')) print(sys.getsizeof(Blob(s))) #print(seq) if seq == 15150: print(manifestData[15150]) print(k["15150"]) #print(Blob(s).toBytes().decode('utf-8')) #print(json.loads(s.decode('utf-8'))) #print(manifest_packet.getName()) while count > 0: seq = seq + 1 datapacket = Data(Name("prefix/data/"+str(seq))) datapacket.setContent(dataArray[10-count]) print(datapacket.getContent()) count = count - 1 seq = seq + 1 manifestData = {} dataArray = [] readdata = f.read(8*1024) dataArray.append(readdata)
def loadCertificateV2FromFile(filename): """ :param str filename: :rtype: CertificateV2 """ with open(filename, 'r') as certFile: encodedData = certFile.read() decodedData = b64decode(encodedData) cert = CertificateV2() cert.wireDecode(Blob(decodedData, False)) return cert
def encodeName(self, name): """ Encode name in NDN-TLV and return the encoding. :param Name name: The Name object to encode. :return: A Blob containing the encoding. :rtype: Blob """ encoder = TlvEncoder(256) self._encodeName(name, encoder) return Blob(encoder.getOutput(), False)
def setNonce(self, nonce): """ :deprecated: You should let the wire encoder generate a random nonce internally before sending the interest. """ self._nonce = nonce if isinstance(nonce, Blob) else Blob(nonce) # Set _getNonceChangeCount so that the next call to getNonce() won't # clear _nonce. self._changeCount += 1 self._getNonceChangeCount = self.getChangeCount() return self
def wireEncode(self): encoder = TlvEncoder(500) saveLength = len(encoder) # if self.getValidityPeriod().hasPeriod(): # Tlv0_2WireFormat._encodeValidityPeriod(self.getValidityPeriod(), encoder) Tlv0_2WireFormat._encodeKeyLocator(Tlv.KeyLocator, self.getKeyLocator(), encoder) encoder.writeNonNegativeIntegerTlv(Tlv.SignatureType, Tlv.SignatureType_Sha256WithAbsSignature) encoder.writeTypeAndLength(Tlv.SignatureInfo, len(encoder) - saveLength) self.setSignatureInfoEncoding(Blob(encoder.getOutput(), False), Tlv.SignatureType_Sha256WithAbsSignature)
def __init__(self, keyType, keyData): self._keyType = keyType keyData = Blob(keyData, False).toBytes() if keyType == KeyType.ECDSA or keyType == KeyType.RSA: self._privateKey = serialization.load_der_private_key( keyData, password=None, backend=default_backend()) else: raise SecurityException( "PrivateKey constructor: Unrecognized keyType")
def sign(self, data, keyName, digestAlgorithm=DigestAlgorithm.SHA256): """ Fetch the private key for keyName and sign the data, returning a signature Blob. :param data: Pointer the input byte buffer to sign. :type data: An array type with int elements :param Name keyName: The name of the signing key. :param digestAlgorithm: (optional) the digest algorithm. If omitted, use DigestAlgorithm.SHA256. :type digestAlgorithm: int from DigestAlgorithm :return: The signature Blob. :rtype: Blob """ keyURI = keyName.toUri() if not self.doesKeyExist(keyName, KeyClass.PRIVATE): raise SecurityException( "FilePrivateKeyStorage.sign: private key doesn't exist") if digestAlgorithm != DigestAlgorithm.SHA256: raise SecurityException( "FilePrivateKeyStorage.sign: Unsupported digest algorithm") # Read the private key. base64Content = None with open(self.nameTransform(keyURI, ".pri")) as keyFile: base64Content = keyFile.read() der = base64.b64decode(base64Content) if not type(der) is str: der = "".join(map(chr, der)) privateKey = RSA.importKey(der) # Sign the hash of the data. if sys.version_info[0] == 2: # In Python 2.x, we need a str. Use Blob to convert data. data = Blob(data, False).toRawStr() signature = PKCS1_v1_5.new(privateKey).sign(SHA256.new(data)) # Convert the string to a Blob. return Blob(bytearray(signature), False)
def _recomputeRoot(self): """ Set _root to the digest of all digests in _digestnode. This sets _root to the hex value of the digest. """ sha256 = hashes.Hash(hashes.SHA256(), backend=default_backend()) for i in range(len(self._digestNode)): self._updateHex(sha256, self._digestNode[i].getDigest()) digestRoot = sha256.finalize() # Use Blob to convert a str (Python 2) or bytes (Python 3) to hex. self._root = Blob(digestRoot, False).toHex() logging.getLogger(__name__).info("update root to: %s", self._root)
def setPayload(self, payload): """ Set the encrypted payload. :param Blob payload: The payload. If not specified, set to the default Blob() where isNull() is True. :return: This EncryptedContent so that you can chain calls to update values. :rtype: EncryptedContent """ self._payload = payload if isinstance(payload, Blob) else Blob(payload) return self
def setKeyData(self, keyData): """ Set the key data to the given value. This is the digest bytes if getType() is KeyLocatorType.KEY_LOCATOR_DIGEST. :param keyData: The array with the key data bytes. If keyData is not a Blob, then create a new Blob to copy the bytes (otherwise take another pointer to the same Blob). :type keyData: A Blob or an array type with int elements """ self._keyData = keyData if isinstance(keyData, Blob) else Blob(keyData) self._changeCount += 1
def __init__(self, value = None): if value == None: self._signature = Blob() elif type(value) is DigestSha256Signature: # Copy its values. self._signature = value._signature else: raise RuntimeError( "Unrecognized type for DigestSha256Signature constructor: " + str(type(value))) self._changeCount = 0
def setSignature(self, signature): """ Set the signature bytes (which is the digest) to the given value. :param signature: The array with the signature bytes. If signature is not a Blob, then create a new Blob to copy the bytes (otherwise take another pointer to the same Blob). :type signature: A Blob or an array type with int elements """ self._signature = (signature if type(signature) is Blob else Blob(signature)) self._changeCount += 1
def fromNumber(number): """ Create a component whose value is the nonNegativeInteger encoding of the number. :param int number: The number to be encoded. :return: The component value. :rtype: Name.Component """ encoder = TlvEncoder(8) encoder.writeNonNegativeInteger(number) return Name.Component(Blob(encoder.getOutput(), False))
def _getPublicKeyDer(self, keyLocator): """ Look in the IdentityStorage for the public key with the name in the KeyLocator. If the public key can't be found, return and empty Blob. :param KeyLocator keyLocator: The KeyLocator. :return: The public key DER or an empty Blob if not found. :rtype: Blob """ if (keyLocator.getType() == KeyLocatorType.KEYNAME and self._identityStorage != None): try: # Assume the key name is a certificate name. return self._identityStorage.getKey( IdentityCertificate.certificateNameToPublicKeyName( keyLocator.getKeyName())) except SecurityException as ex: # The storage doesn't have the key. return Blob() else: return Blob()
def __init__(self, value = None): if type(value) is Name.Component: # Copy constructor. Use the existing Blob in the other Component. self._value = value._value self._type = value._type return if value == None: self._value = Blob([]) else: # Blob will make a copy. self._value = value if isinstance(value, Blob) else Blob(value) self._type = Name.Component.ComponentType.GENERIC
def _decode(encoding): """ Decode the IBLT from the Blob. This converts the Blob into a uint8_t array which is then decoded to a uint32_t array. :param Blob encoding: The encoded IBLT. :return: A uint32_t array representing the hash table of the IBLT. :rtype: Array<int> """ # Use Blob to convert bytes to an integer array. ibltValues = Blob(zlib.decompress(encoding.toBytes()), False) nEntries = int(len(ibltValues) / 4) values = [0] * nEntries ibltValuesBuf = ibltValues.buf() for i in range(0, 4 * nEntries, 4): t = ((ibltValuesBuf[i + 3] << 24) + (ibltValuesBuf[i + 2] << 16) + (ibltValuesBuf[i + 1] << 8) + ibltValuesBuf[i]) values[int(i / 4)] = t return values
def __init__(self, value = None): if value == None: self._type = None self._keyName = ChangeCounter(Name()) self._keyData = Blob() elif type(value) is KeyLocator: # Copy its values. self._type = value._type self._keyName = ChangeCounter(Name(value.getKeyName())) self._keyData = value._keyData else: raise RuntimeError( "Unrecognized type for KeyLocator constructor: " + str(type(value))) self._changeCount = 0
class PublicKey(object): """ Create a new PublicKey by decoding the keyDer. Set the key type from the decoding. :param Blob keyDer: The blob of the PublicKeyInfo in terms of DER. :raises: UnrecognizedKeyFormatException if can't decode the key DER. """ def __init__(self, keyDer = None): # TODO: Implementation of managed properties? if keyDer == None: self._keyDer = Blob() self._keyType = None return self._keyDer = keyDer # Get the public key OID. oidString = "" try: parsedNode = DerNode.parse(keyDer.buf(), 0) rootChildren = parsedNode.getChildren() algorithmIdChildren = DerNode.getSequence( rootChildren, 0).getChildren() oidString = algorithmIdChildren[0].toVal() except DerDecodingException as ex: raise UnrecognizedKeyFormatException( "PublicKey.decodeKeyType: Error decoding the public key" + str(ex)) # Verify that the we can decode. if oidString == self.RSA_ENCRYPTION_OID: self._keyType = KeyType.RSA RSA.importKey(keyDer.toRawStr()) elif oidString == self.EC_ENCRYPTION_OID: self._keyType = KeyType.ECDSA # TODO: Check EC decoding. else: raise UnrecognizedKeyFormatException( "PublicKey.decodeKeyType: Unrecognized OID " + oidString) def toDer(self): """ Encode the public key into DER. :return: The encoded DER syntax tree. :rtype: DerNode """ return DerNode.parse(self._keyDer) def getDigest(self, digestAlgorithm = DigestAlgorithm.SHA256): """ Get the digest of the public key. :param digestAlgorithm: (optional) The digest algorithm. If omitted, use DigestAlgorithm.SHA256 . :type digestAlgorithm: int from DigestAlgorithm :return: The digest value :rtype: Blob """ if digestAlgorithm == DigestAlgorithm.SHA256: hashFunc = SHA256.new() hashFunc.update(self._keyDer.buf()) return Blob(hashFunc.digest()) else: raise RuntimeError("Unimplemented digest algorithm") def getKeyType(self): """ Get the key type. :return: The key type :rtype: an int from KeyType """ return self._keyType def getKeyDer(self): """ Get the raw bytes of the public key in DER format. :return: The public key DER :rtype: Blob """ return self._keyDer RSA_ENCRYPTION_OID = "1.2.840.113549.1.1.1" EC_ENCRYPTION_OID = "1.2.840.10045.2.1"
class KeyLocator(object): """ Create a new KeyLocator object, possibly copying values from another object. :param KeyLocator value: (optional) If value is a KeyLocator, copy its values. If value is omitted, set the fields to unspecified. """ def __init__(self, value = None): if value == None: self._type = None self._keyName = ChangeCounter(Name()) self._keyData = Blob() elif type(value) is KeyLocator: # Copy its values. self._type = value._type self._keyName = ChangeCounter(Name(value.getKeyName())) self._keyData = value._keyData else: raise RuntimeError( "Unrecognized type for KeyLocator constructor: " + str(type(value))) self._changeCount = 0 def getType(self): """ Get the key locator type. If KeyLocatorType.KEYNAME, you may also getKeyName(). If KeyLocatorType.KEY_LOCATOR_DIGEST, you may also getKeyData() to get the digest. :return: The key locator type, or None if not specified. :rtype: an int from KeyLocatorType """ return self._type def getKeyName(self): """ Get the key name. This is meaningful if getType() is KeyLocatorType.KEYNAME. :return: The key name. If not specified, the Name is empty. :rtype: Name """ return self._keyName.get() def getKeyData(self): """ Get the key data. This is the digest bytes if getType() is KeyLocatorType.KEY_LOCATOR_DIGEST. :return: The key data as a Blob, which isNull() if unspecified. :rtype: Blob """ return self._keyData def setType(self, type): """ Set the key locator type. If KeyLocatorType.KEYNAME, you must also setKeyName(). If KeyLocatorType.KEY_LOCATOR_DIGEST, you must also setKeyData() to set the digest. :param type: The key locator type. If None, the type is unspecified. :type type: an int from KeyLocatorType """ self._type = None if type == None or type < 0 else type self._changeCount += 1 def setKeyName(self, keyName): """ Set key name to a copy of the given Name. This is the name if getType() is KeyLocatorType.KEYNAME. :param Name keyName: The key name which is copied. """ self._keyName.set(keyName if type(keyName) is Name else Name(keyName)) self._changeCount += 1 def setKeyData(self, keyData): """ Set the key data to the given value. This is the digest bytes if getType() is KeyLocatorType.KEY_LOCATOR_DIGEST. :param keyData: The array with the key data bytes. If keyData is not a Blob, then create a new Blob to copy the bytes (otherwise take another pointer to the same Blob). :type keyData: A Blob or an array type with int elements """ self._keyData = keyData if type(keyData) is Blob else Blob(keyData) self._changeCount += 1 def clear(self): """ Clear the fields and set the type to None. """ self._type = None self._keyName.get().clear() self._keyData = Blob() self._changeCount += 1 @staticmethod def canGetFromSignature(signature): """ If the signature is a type that has a KeyLocator (so that getFromSignature will succeed), return true. Note: This is a static method of KeyLocator instead of a method of Signature so that the Signature base class does not need to be overloaded with all the different kinds of information that various signature algorithms may use. :param Signature signature: An object of a subclass of Signature. :return: True if the signature is a type that has a KeyLocator, otherwise False. :rtype: bool """ return type(signature) is Sha256WithRsaSignature @staticmethod def getFromSignature(signature): """ If the signature is a type that has a KeyLocator, then return it. Otherwise throw an error. :param Signature signature: An object of a subclass of Signature. :return: The signature's KeyLocator. It is an error if signature doesn't have a KeyLocator. :rtype: KeyLocator """ if type(signature) is Sha256WithRsaSignature: return signature.getKeyLocator() else: raise RuntimeError( "KeyLocator.getFromSignature: Signature type does not have a KeyLocator") def getChangeCount(self): """ Get the change count, which is incremented each time this object (or a child object) is changed. :return: The change count. :rtype: int """ # Make sure each of the checkChanged is called. changed = self._keyName.checkChanged() if changed: # A child object has changed, so update the change count. self._changeCount += 1 return self._changeCount # Create managed properties for read/write properties of the class for more pythonic syntax. type = property(getType, setType) keyName = property(getKeyName, setKeyName) keyData = property(getKeyData, setKeyData) # Support property-based equivalence check # TODO: Desired syntax? def equals(self, other): if self is None and other is None: return True if other is None: return False if self._type != other._type: return False if self._keyName.get() != None and not self._keyName.get().equals(other._keyName.get()): return False if self._keyData != None and not self._keyData.equals(other._keyData): return False return True
class Interest(object): def __init__(self, value = None): if type(value) is Interest: # Copy the values. self._name = ChangeCounter(Name(value.getName())) self._minSuffixComponents = value._minSuffixComponents self._maxSuffixComponents = value._maxSuffixComponents self._keyLocator = ChangeCounter(KeyLocator(value.getKeyLocator())) self._exclude = ChangeCounter(Exclude(value.getExclude())) self._childSelector = value._childSelector self._mustBeFresh = value._mustBeFresh self._nonce = value.getNonce() self._interestLifetimeMilliseconds = value._interestLifetimeMilliseconds self._linkWireEncoding = value._linkWireEncoding self._linkWireEncodingFormat = value._linkWireEncodingFormat self._link = ChangeCounter(None) if value._link.get() != None: self._link.set(Link(value._link.get())) self._selectedDelegationIndex = value._selectedDelegationIndex self._defaultWireEncoding = value.getDefaultWireEncoding() self._defaultWireEncodingFormat = value._defaultWireEncodingFormat else: self._name = ChangeCounter(Name(value) if type(value) is Name else Name()) self._minSuffixComponents = None self._maxSuffixComponents = None self._keyLocator = ChangeCounter(KeyLocator()) self._exclude = ChangeCounter(Exclude()) self._childSelector = None self._mustBeFresh = True self._nonce = Blob() self._interestLifetimeMilliseconds = None self._linkWireEncoding = Blob() self._linkWireEncodingFormat = None self._link = ChangeCounter(None) self._selectedDelegationIndex = None self._defaultWireEncoding = SignedBlob() self._defaultWireEncodingFormat = None self._getNonceChangeCount = 0 self._getDefaultWireEncodingChangeCount = 0 self._changeCount = 0 self._lpPacket = None def getName(self): """ Get the interest Name. :return: The name. The name size() may be 0 if not specified. :rtype: Name """ return self._name.get() def getMinSuffixComponents(self): """ Get the min suffix components. :return: The min suffix components, or None if not specified. :rtype: int """ return self._minSuffixComponents def getMaxSuffixComponents(self): """ Get the max suffix components. :return: The max suffix components, or None if not specified. :rtype: int """ return self._maxSuffixComponents def getKeyLocator(self): """ Get the interest key locator. :return: The key locator. If getType() is None, then the key locator is not specified. :rtype: KeyLocator """ return self._keyLocator.get() def getExclude(self): """ Get the exclude object. :return: The exclude object. If the exclude size() is zero, then the exclude is not specified. :rtype: Exclude """ return self._exclude.get() def getChildSelector(self): """ Get the child selector. :return: The child selector, or None if not specified. :rtype: int """ return self._childSelector def getMustBeFresh(self): """ Get the must be fresh flag. :return: The must be fresh flag. If not specified, the default is True. :rtype: bool """ return self._mustBeFresh def getNonce(self): """ Return the nonce value from the incoming interest. If you change any of the fields in this Interest object, then the nonce value is cleared. :return: The nonce. If isNull() then the nonce is omitted. :rtype: Blob """ if self._getNonceChangeCount != self.getChangeCount(): # The values have changed, so the existing nonce is invalidated. self._nonce = Blob() self._getNonceChangeCount = self.getChangeCount() return self._nonce def hasLink(self): """ Check if this interest has a link object (or a link wire encoding which can be decoded to make the link object). :return: True if this interest has a link object, False if not. :rtype: bool """ return self._link.get() != None or not self._linkWireEncoding.isNull() def getLink(self): """ Get the link object. If necessary, decode it from the link wire encoding. :return: The link object, or null if not specified. :rtype: Link :raises ValueError: For error decoding the link wire encoding (if necessary). """ if self._link.get() != None: return self._link.get() elif not self._linkWireEncoding.isNull(): # Decode the link object from linkWireEncoding_. link = Link() link.wireDecode(self._linkWireEncoding, self._linkWireEncodingFormat) self._link.set(link) # Clear _linkWireEncoding since it is now managed by the link object. self._linkWireEncoding = Blob() self._linkWireEncodingFormat = None return link else: return None def getLinkWireEncoding(self, wireFormat = None): """ Get the wire encoding of the link object. If there is already a wire encoding then return it. Otherwise encode from the link object (if available). :param WireFormat wireFormat: (optional) A WireFormat object used to encode the Link. If omitted, use WireFormat.getDefaultWireFormat(). :return: The wire encoding, or an isNull Blob if the link is not specified. :rtype: Blob """ if wireFormat == None: # Don't use a default argument since getDefaultWireFormat can change. wireFormat = WireFormat.getDefaultWireFormat() if (not self._linkWireEncoding.isNull() and self._linkWireEncodingFormat == wireFormat): return self._linkWireEncoding link = self.getLink() if link != None: return link.wireEncode(wireFormat) else: return Blob() def getSelectedDelegationIndex(self): """ Get the selected delegation index. :return: The selected delegation index. If not specified, return None. :rtype: int """ return self._selectedDelegationIndex def getInterestLifetimeMilliseconds(self): """ Get the interest lifetime. :return: The interest lifetime in milliseconds, or None if not specified. :rtype: float """ return self._interestLifetimeMilliseconds def getIncomingFaceId(self): """ Get the incoming face ID according to the incoming packet header. :return: The incoming face ID. If not specified, return None. :rtype: int """ field = (None if self._lpPacket == None else IncomingFaceId.getFirstHeader(self._lpPacket)) return None if field == None else field.getFaceId() def setName(self, name): """ Set the interest name. :note: You can also call getName and change the name values directly. :param Name name: The interest name. This makes a copy of the name. :return: This Interest so that you can chain calls to update values. :rtype: Interest """ self._name.set(name if type(name) is Name else Name(name)) self._changeCount += 1 return self def setMinSuffixComponents(self, minSuffixComponents): """ Set the min suffix components count. :param int minSuffixComponents: The min suffix components count. If not specified, set to None. :return: This Interest so that you can chain calls to update values. :rtype: Interest """ self._minSuffixComponents = Common.nonNegativeIntOrNone(minSuffixComponents) self._changeCount += 1 return self def setMaxSuffixComponents(self, maxSuffixComponents): """ Set the max suffix components count. :param int maxSuffixComponents: The max suffix components count. If not specified, set to None. :return: This Interest so that you can chain calls to update values. :rtype: Interest """ self._maxSuffixComponents = Common.nonNegativeIntOrNone(maxSuffixComponents) self._changeCount += 1 return self def setKeyLocator(self, keyLocator): """ Set this interest to use a copy of the given KeyLocator object. :note: You can also call getKeyLocator and change the key locator directly. :param KeyLocator keyLocator: The KeyLocator object. This makes a copy of the object. If no key locator is specified, set to a new default KeyLocator(), or to a KeyLocator with an unspecified type. :return: This Interest so that you can chain calls to update values. :rtype: Interest """ self._keyLocator.set( KeyLocator(keyLocator) if type(keyLocator) is KeyLocator else KeyLocator()) self._changeCount += 1 return self def setExclude(self, exclude): """ Set this interest to use a copy of the given Exclude object. :note: You can also call getExclude and change the exclude entries directly. :param Exclude exclude: The Exclude object. This makes a copy of the object. If no exclude is specified, set to a new default Exclude(), or to an Exclude with size() 0. :return: This Interest so that you can chain calls to update values. :rtype: Interest """ self._exclude.set( Exclude(exclude) if type(exclude) is Exclude else Exclude()) self._changeCount += 1 return self def setLinkWireEncoding(self, encoding, wireFormat = None): """ Set the link wire encoding bytes, without decoding them. If there is a link object, set it to null. If you later call getLink(), it will decode the wireEncoding to create the link object. :param Blob encoding: The Blob with the bytes of the link wire encoding. If no link is specified, set to an empty Blob() or call unsetLink(). :param WireFormat wireFormat: The wire format of the encoding, to be used later if necessary to decode. If omitted, use WireFormat.getDefaultWireFormat(). :return: This Interest so that you can chain calls to update values. :rtype: Interest """ if wireFormat == None: # Don't use a default argument since getDefaultWireFormat can change. wireFormat = WireFormat.getDefaultWireFormat() self._linkWireEncoding = encoding self._linkWireEncodingFormat = wireFormat # Clear the link object, assuming that it has a different encoding. self._link.set(None) self._changeCount += 1 return self def unsetLink(self): """ Clear the link wire encoding and link object so that getLink() returns None. :return: This Interest so that you can chain calls to update values. :rtype: Interest """ return self.setLinkWireEncoding(Blob(), None) def setSelectedDelegationIndex(self, selectedDelegationIndex): """ Set the selected delegation index. :param int selectedDelegationIndex: The selected delegation index. If not specified, set to None. :return: This Interest so that you can chain calls to update values. :rtype: Interest """ self._selectedDelegationIndex = Common.nonNegativeIntOrNone(selectedDelegationIndex) self._changeCount += 1 return self def setChildSelector(self, childSelector): """ Set the child selector. :param int childSelector: The child selector. If not specified, set to None. :return: This Interest so that you can chain calls to update values. :rtype: Interest """ self._childSelector = Common.nonNegativeIntOrNone(childSelector) self._changeCount += 1 return self def setMustBeFresh(self, mustBeFresh): """ Set the MustBeFresh flag. :param bool mustBeFresh: True if the content must be fresh, otherwise False. If you do not set this flag, the default value is true. :return: This Interest so that you can chain calls to update values. :rtype: Interest """ self._mustBeFresh = True if mustBeFresh else False self._changeCount += 1 return self def setNonce(self, nonce): """ :deprecated: You should let the wire encoder generate a random nonce internally before sending the interest. """ self._nonce = nonce if isinstance(nonce, Blob) else Blob(nonce) # Set _getNonceChangeCount so that the next call to getNonce() won't # clear _nonce. self._changeCount += 1 self._getNonceChangeCount = self.getChangeCount() return self def setInterestLifetimeMilliseconds(self, interestLifetimeMilliseconds): """ Set the interest lifetime. :param float interestLifetimeMilliseconds: The interest lifetime in milliseconds. If not specified, set to None. :return: This Interest so that you can chain calls to update values. :rtype: Interest """ self._interestLifetimeMilliseconds = Common.nonNegativeFloatOrNone( interestLifetimeMilliseconds) self._changeCount += 1 return self def wireEncode(self, wireFormat = None): """ Encode this Interest for a particular wire format. If wireFormat is the default wire format, also set the defaultWireEncoding field to the encoded result. :param wireFormat: (optional) A WireFormat object used to encode this Interest. If omitted, use WireFormat.getDefaultWireFormat(). :type wireFormat: A subclass of WireFormat :return: The encoded buffer. :rtype: SignedBlob """ if wireFormat == None: # Don't use a default argument since getDefaultWireFormat can change. wireFormat = WireFormat.getDefaultWireFormat() if (not self.getDefaultWireEncoding().isNull() and self.getDefaultWireEncodingFormat() == wireFormat): # We already have an encoding in the desired format. return self.getDefaultWireEncoding() (encoding, signedPortionBeginOffset, signedPortionEndOffset) = \ wireFormat.encodeInterest(self) wireEncoding = SignedBlob( encoding, signedPortionBeginOffset, signedPortionEndOffset) if wireFormat == WireFormat.getDefaultWireFormat(): # This is the default wire encoding. self._setDefaultWireEncoding( wireEncoding, WireFormat.getDefaultWireFormat()) return wireEncoding def wireDecode(self, input, wireFormat = None): """ Decode the input using a particular wire format and update this Interest. If wireFormat is the default wire format, also set the defaultWireEncoding to another pointer to the input. :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 Interest. 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() if isinstance(input, Blob): # Input is a blob, so get its buf() and set copy False. result = wireFormat.decodeInterest(self, input.buf(), False) else: result = wireFormat.decodeInterest(self, input, True) (signedPortionBeginOffset, signedPortionEndOffset) = result if wireFormat == WireFormat.getDefaultWireFormat(): # This is the default wire encoding. In the Blob constructor, set # copy true, but if input is already a Blob, it won't copy. self._setDefaultWireEncoding(SignedBlob( Blob(input, True), signedPortionBeginOffset, signedPortionEndOffset), WireFormat.getDefaultWireFormat()) else: self._setDefaultWireEncoding(SignedBlob(), None) def toUri(self): """ Encode the name according to the "NDN URI Scheme". If there are interest selectors, append "?" and add the selectors as a query string. For example "/test/name?ndn.ChildSelector=1". :note: This is an experimental feature. See the API docs for more detail at http://named-data.net/doc/ndn-ccl-api/interest.html#interest-touri-method . :return: The URI string. :rtype: string """ selectors = "" if self._minSuffixComponents != None: selectors += "&ndn.MinSuffixComponents=" + repr( self._minSuffixComponents) if self._maxSuffixComponents != None: selectors += "&ndn.MaxSuffixComponents=" + repr( self._maxSuffixComponents) if self._childSelector != None: selectors += "&ndn.ChildSelector=" + repr(self._childSelector) if self._mustBeFresh: selectors += "&ndn.MustBeFresh=true" if self._interestLifetimeMilliseconds != None: selectors += "&ndn.InterestLifetime=" + repr( int(round(self._interestLifetimeMilliseconds))) if self.getNonce().size() > 0: selectors += ("&ndn.Nonce=" + Name.toEscapedString(self.getNonce().buf())) if self.getExclude().size() > 0: selectors += "&ndn.Exclude=" + self.getExclude().toUri() result = self.getName().toUri() if selectors != "": # Replace the first & with ?. result += "?" + selectors[1:] return result def refreshNonce(self): """ Update the bytes of the nonce with new random values. This ensures that the new nonce value is different than the current one. If the current nonce is not specified, this does nothing. """ currentNonce = self.getNonce() if currentNonce.size() == 0: return while True: value = bytearray(currentNonce.size()) for i in range(len(value)): value[i] = self._systemRandom.randint(0, 0xff) newNonce = Blob(value, False) if newNonce != currentNonce: break self._nonce = newNonce # Set _getNonceChangeCount so that the next call to getNonce() won't # clear _nonce. self._changeCount += 1 self._getNonceChangeCount = self.getChangeCount() def matchesName(self, name): """ Check if this interest's name matches the given name (using Name.match) and the given name also conforms to the interest selectors. :param Name name: The name to check. :return: True if the name and interest selectors match, False otherwise. :rtype: bool """ if not self.getName().match(name): return False if (self._minSuffixComponents != None and # Add 1 for the implicit digest. not (name.size() + 1 - self.getName().size() >= self._minSuffixComponents)): return False if (self._maxSuffixComponents != None and # Add 1 for the implicit digest. not (name.size() + 1 - self.getName().size() <= self._maxSuffixComponents)): return False if (self.getExclude().size() > 0 and name.size() > self.getName().size() and self.getExclude().matches(name[self.getName().size()])): return False return True def matchesData(self, data, wireFormat = None): """ Check if the given Data packet can satisfy this Interest. This method considers the Name, MinSuffixComponents, MaxSuffixComponents, PublisherPublicKeyLocator, and Exclude. It does not consider the ChildSelector or MustBeFresh. This uses the given wireFormat to get the Data packet encoding for the full Name. :param Data data: The Data packet to check. :param wireFormat: (optional) A WireFormat object used to encode the Data packet to get its full Name. If omitted, use WireFormat.getDefaultWireFormat(). :type wireFormat: A subclass of WireFormat :return: True if the given Data packet can satisfy this Interest. :rtype: bool """ # Imitate ndn-cxx Interest::matchesData. interestNameLength = self.getName().size() dataName = data.getName() fullNameLength = dataName.size() + 1 # Check MinSuffixComponents. hasMinSuffixComponents = (self.getMinSuffixComponents() != None) minSuffixComponents = (self.getMinSuffixComponents() if hasMinSuffixComponents else 0) if not (interestNameLength + minSuffixComponents <= fullNameLength): return False # Check MaxSuffixComponents. hasMaxSuffixComponents = (self.getMaxSuffixComponents() != None) if (hasMaxSuffixComponents and not (interestNameLength + self.getMaxSuffixComponents() >= fullNameLength)): return False # Check the prefix. if interestNameLength == fullNameLength: if self.getName().get(-1).isImplicitSha256Digest(): if not self.getName().equals(data.getFullName(wireFormat)): return False else: # The Interest Name is the same length as the Data full Name, # but the last component isn't a digest so there's no # possibility of matching. return False else: # The Interest Name should be a strict prefix of the Data full Name. if not self.getName().isPrefixOf(dataName): return False # Check the Exclude. # The Exclude won't be violated if the Interest Name is the same as the # Data full Name. if self.getExclude().size() > 0 and fullNameLength > interestNameLength: if interestNameLength == fullNameLength - 1: # The component to exclude is the digest. if self.getExclude().matches( data.getFullName(wireFormat).get(interestNameLength)): return False else: # The component to exclude is not the digest. if self.getExclude().matches(dataName.get(interestNameLength)): return False # Check the KeyLocator. publisherPublicKeyLocator = self.getKeyLocator() if publisherPublicKeyLocator.getType() != None: signature = data.getSignature() if not KeyLocator.canGetFromSignature(signature): # No KeyLocator in the Data packet. return False if not publisherPublicKeyLocator.equals( (KeyLocator.getFromSignature(signature))): return False return True def getDefaultWireEncoding(self): """ Return the default wire encoding, which was encoded with getDefaultWireEncodingFormat(). :return: The default wire encoding, whose isNull() may be true if there is no default wire encoding. :rtype: SignedBlob """ if self._getDefaultWireEncodingChangeCount != self.getChangeCount(): # The values have changed, so the default wire encoding is # invalidated. self._defaultWireEncoding = SignedBlob() self._defaultWireEncodingFormat = None self._getDefaultWireEncodingChangeCount = self.getChangeCount() return self._defaultWireEncoding def getDefaultWireEncodingFormat(self): """ Get the WireFormat which is used by getDefaultWireEncoding(). :return: The WireFormat, which is only meaningful if the getDefaultWireEncoding() is not isNull(). :rtype: WireFormat """ return self._defaultWireEncodingFormat def setLpPacket(self, lpPacket): """ An internal library method to set the LpPacket for an incoming packet. The application should not call this. :param LpPacket lpPacket: The LpPacket. This does not make a copy. :return: This Interest so that you can chain calls to update values. :rtype: Interest :note: This is an experimental feature. This API may change in the future. """ self._lpPacket = lpPacket # Don't update _changeCount since this doesn't affect the wire encoding. return self def getChangeCount(self): """ Get the change count, which is incremented each time this object (or a child object) is changed. :return: The change count. :rtype: int """ # Make sure each of the checkChanged is called. changed = self._name.checkChanged() changed = self._keyLocator.checkChanged() or changed changed = self._exclude.checkChanged() or changed if changed: # A child object has changed, so update the change count. self._changeCount += 1 return self._changeCount def _setDefaultWireEncoding( self, defaultWireEncoding, defaultWireEncodingFormat): self._defaultWireEncoding = defaultWireEncoding self._defaultWireEncodingFormat = defaultWireEncodingFormat # Set _getDefaultWireEncodingChangeCount so that the next call to # getDefaultWireEncoding() won't clear _defaultWireEncoding. self._getDefaultWireEncodingChangeCount = self.getChangeCount() _systemRandom = SystemRandom() # Create managed properties for read/write properties of the class for more pythonic syntax. name = property(getName, setName) minSuffixComponents = property(getMinSuffixComponents, setMinSuffixComponents) maxSuffixComponents = property(getMaxSuffixComponents, setMaxSuffixComponents) keyLocator = property(getKeyLocator, setKeyLocator) exclude = property(getExclude, setExclude) childSelector = property(getChildSelector, setChildSelector) mustBeFresh = property(getMustBeFresh, setMustBeFresh) nonce = property(getNonce, setNonce) interestLifetimeMilliseconds = property(getInterestLifetimeMilliseconds, setInterestLifetimeMilliseconds)
class Component(object): """ Create a new Name.Component. :param value: (optional) If value is already a Blob or Name.Component, then take another pointer to the value. Otherwise, create a new Blob with a copy of the value. If omitted, create an empty component. :type value: Blob or Name.Component or value for Blob constructor """ def __init__(self, value = None): if type(value) is Name.Component: # Use the existing Blob in the other Component. self._value = value._value elif value == None: self._value = Blob([]) else: # Blob will make a copy. self._value = value if isinstance(value, Blob) else Blob(value) def getValue(self): """ Get the value of the component. :return: The component value. :rtype: Blob """ return self._value def toEscapedString(self, result = None): """ Convert this component to a string, escaping characters according to the NDN URI Scheme. This also adds "..." to a value with zero or more ".". :param BytesIO result: (optional) The BytesIO stream to write to. If omitted, return a str with the result. :return: The result as a string (only if result is omitted). :rtype: str """ if result == None: return Name.toEscapedString(self._value.buf()) else: Name.toEscapedString(self._value.buf(), result) def toNumber(self): """ Interpret this name component as a network-ordered number and return an integer. :return: The integer number. :rtype: int """ result = 0 for i in range(self._value.size()): result *= 256 result += self._value.buf()[i] return result def toNumberWithMarker(self, marker): """ Interpret this name component as a network-ordered number with a marker and return an integer. :param int marker: The required first byte of the component. :return: The integer number. :rtype: int :raises RuntimeError: If the first byte of the component does not equal the marker. """ if self._value.size() <= 0 or self._value.buf()[0] != marker: raise RuntimeError( "Name component does not begin with the expected marker") result = 0 for i in range(1, self._value.size()): result *= 256 result += self._value.buf()[i] return result def toSegment(self): """ Interpret this name component as a segment number according to NDN naming conventions for "Segment number" (marker 0x00). http://named-data.net/doc/tech-memos/naming-conventions.pdf :return: The integer segment number. :rtype: int :raises RuntimeError: If the first byte of the component is not the expected marker. """ return self.toNumberWithMarker(0x00) def toSegmentOffset(self): """ Interpret this name component as a segment byte offset according to NDN naming conventions for segment "Byte offset" (marker 0xFB). http://named-data.net/doc/tech-memos/naming-conventions.pdf :return: The integer segment byte offset. :rtype: int :raises RuntimeError: If the first byte of the component is not the expected marker. """ return self.toNumberWithMarker(0xFB) def toVersion(self): """ Interpret this name component as a version number according to NDN naming conventions for "Versioning" (marker 0xFD). Note that this returns the exact number from the component without converting it to a time representation. http://named-data.net/doc/tech-memos/naming-conventions.pdf :return: The integer version number. :rtype: int :raises RuntimeError: If the first byte of the component is not the expected marker. """ return self.toNumberWithMarker(0xFD) def toTimestamp(self): """ Interpret this name component as a timestamp according to NDN naming conventions for "Timestamp" (marker 0xFC). http://named-data.net/doc/tech-memos/naming-conventions.pdf :return: The number of microseconds since the UNIX epoch (Thursday, 1 January 1970) not counting leap seconds. :rtype: int :raises RuntimeError: If the first byte of the component is not the expected marker. """ return self.toNumberWithMarker(0xFC) def toSequenceNumber(self): """ Interpret this name component as a sequence number according to NDN naming conventions for "Sequencing" (marker 0xFE). http://named-data.net/doc/tech-memos/naming-conventions.pdf :return: The integer sequence number. :rtype: int :raises RuntimeError: If the first byte of the component is not the expected marker. """ return self.toNumberWithMarker(0xFE) def equals(self, other): """ Check if this is the same component as other. :param Name.Component other: The other Component to compare with. :return: True if the components are equal, otherwise False. :rtype: bool """ return self._value.equals(other._value) def compare(self, other): """ Compare this to the other Component using NDN canonical ordering. :param Name.Component other: The other Component to compare with. :return: 0 If they compare equal, -1 if self comes before other in the canonical ordering, or 1 if self comes after other in the canonical ordering. :rtype: int :see: http://named-data.net/doc/0.2/technical/CanonicalOrder.html """ if self._value.size() < other._value.size(): return -1 if self._value.size() > other._value.size(): return 1 # The components are equal length. Just do a byte compare. return self._value.compare(other._value) @staticmethod def fromNumber(number): """ Create a component whose value is the nonNegativeInteger encoding of the number. :param int number: The number to be encoded. :return: The component value. :rtype: Name.Component """ encoder = TlvEncoder(8) encoder.writeNonNegativeInteger(number) return Name.Component(Blob(encoder.getOutput(), False)) @staticmethod def fromNumberWithMarker(number, marker): """ Create a component whose value is the marker appended with the nonNegativeInteger encoding of the number. :param int number: The number to be encoded. :param int marker: The marker to use as the first byte of the component. :return: The component value. :rtype: Name.Component """ encoder = TlvEncoder(9) # Encode backwards. encoder.writeNonNegativeInteger(number) encoder.writeNonNegativeInteger(marker) return Name.Component(Blob(encoder.getOutput(), False)) # Python operators def __eq__(self, other): return type(other) is Name.Component and self.equals(other) def __ne__(self, other): return not self == other def __le__(self, other): return self.compare(other) <= 0 def __lt__(self, other): return self.compare(other) < 0 def __ge__(self, other): return self.compare(other) >= 0 def __gt__(self, other): return self.compare(other) > 0 def __len__(self): return self._value.size() def __str__(self): return self.toEscapedString()
class Component(object): """ Create a new GENERIC Name.Component. :param value: (optional) If value is already a Blob or Name.Component, then take another pointer to the value. Otherwise, create a new Blob with a copy of the value. If omitted, create an empty component. :type value: Blob or Name.Component or value for Blob constructor """ def __init__(self, value = None): if type(value) is Name.Component: # Copy constructor. Use the existing Blob in the other Component. self._value = value._value self._type = value._type return if value == None: self._value = Blob([]) else: # Blob will make a copy. self._value = value if isinstance(value, Blob) else Blob(value) self._type = Name.Component.ComponentType.GENERIC class ComponentType(object): """ A Name.Component.ComponentType specifies the recognized types of a name component. """ IMPLICIT_SHA256_DIGEST = 1 GENERIC = 8 def getValue(self): """ Get the value of the component. :return: The component value. :rtype: Blob """ return self._value def toEscapedString(self, result = None): """ Convert this component to a string, escaping characters according to the NDN URI Scheme. This also adds "..." to a value with zero or more ".". This adds a type code prefix as needed, such as "sha256digest=". :param BytesIO result: (optional) The BytesIO stream to write to. If omitted, return a str with the result. :return: The result as a string (only if result is omitted). :rtype: str """ if result == None: result = BytesIO() self.toEscapedString(result) return Common.getBytesIOString(result) else: if self._type == Name.Component.ComponentType.IMPLICIT_SHA256_DIGEST: result.write("sha256digest=".encode('utf-8')) self._value.toHex(result) else: Name.toEscapedString(self._value.buf(), result) def isSegment(self): """ Check if this component is a segment number according to NDN naming conventions for "Segment number" (marker 0x00). http://named-data.net/doc/tech-memos/naming-conventions.pdf :return: True if this is a segment number. :rtype: bool """ return (self._value.size() >= 1 and self._value.buf()[0] == 0x00 and self.isGeneric()) def isSegmentOffset(self): """ Check if this component is a segment byte offset according to NDN naming conventions for segment "Byte offset" (marker 0xFB). http://named-data.net/doc/tech-memos/naming-conventions.pdf :return: True if this is a segment byte offset. :rtype: bool """ return (self._value.size() >= 1 and self._value.buf()[0] == 0xFB and self.isGeneric()) def isVersion(self): """ Check if this component is a version number according to NDN naming conventions for "Versioning" (marker 0xFD). http://named-data.net/doc/tech-memos/naming-conventions.pdf :return: True if this is a version number. :rtype: bool """ return (self._value.size() >= 1 and self._value.buf()[0] == 0xFD and self.isGeneric()) def isTimestamp(self): """ Check if this component is a timestamp according to NDN naming conventions for "Timestamp" (marker 0xFC). http://named-data.net/doc/tech-memos/naming-conventions.pdf :return: True if this is a timestamp. :rtype: bool """ return (self._value.size() >= 1 and self._value.buf()[0] == 0xFC and self.isGeneric()) def isSequenceNumber(self): """ Check if this component is a sequence number according to NDN naming conventions for "Sequencing" (marker 0xFE). http://named-data.net/doc/tech-memos/naming-conventions.pdf :return: True if this is a sequence number. :rtype: bool """ return (self._value.size() >= 1 and self._value.buf()[0] == 0xFE and self.isGeneric()) def isGeneric(self): """ Check if this component is a generic component. :return: True if this is an generic component. :rtype: bool """ return self._type == Name.Component.ComponentType.GENERIC def isImplicitSha256Digest(self): """ Check if this component is an ImplicitSha256Digest component. :return: True if this is an ImplicitSha256Digest component. :rtype: bool """ return self._type == Name.Component.ComponentType.IMPLICIT_SHA256_DIGEST def toNumber(self): """ Interpret this name component as a network-ordered number and return an integer. :return: The integer number. :rtype: int """ result = 0 for i in range(self._value.size()): result *= 256 result += self._value.buf()[i] return result def toNumberWithMarker(self, marker): """ Interpret this name component as a network-ordered number with a marker and return an integer. :param int marker: The required first byte of the component. :return: The integer number. :rtype: int :raises RuntimeError: If the first byte of the component does not equal the marker. """ if self._value.size() <= 0 or self._value.buf()[0] != marker: raise RuntimeError( "Name component does not begin with the expected marker") result = 0 for i in range(1, self._value.size()): result *= 256 result += self._value.buf()[i] return result def toSegment(self): """ Interpret this name component as a segment number according to NDN naming conventions for "Segment number" (marker 0x00). http://named-data.net/doc/tech-memos/naming-conventions.pdf :return: The integer segment number. :rtype: int :raises RuntimeError: If the first byte of the component is not the expected marker. """ return self.toNumberWithMarker(0x00) def toSegmentOffset(self): """ Interpret this name component as a segment byte offset according to NDN naming conventions for segment "Byte offset" (marker 0xFB). http://named-data.net/doc/tech-memos/naming-conventions.pdf :return: The integer segment byte offset. :rtype: int :raises RuntimeError: If the first byte of the component is not the expected marker. """ return self.toNumberWithMarker(0xFB) def toVersion(self): """ Interpret this name component as a version number according to NDN naming conventions for "Versioning" (marker 0xFD). Note that this returns the exact number from the component without converting it to a time representation. http://named-data.net/doc/tech-memos/naming-conventions.pdf :return: The integer version number. :rtype: int :raises RuntimeError: If the first byte of the component is not the expected marker. """ return self.toNumberWithMarker(0xFD) def toTimestamp(self): """ Interpret this name component as a timestamp according to NDN naming conventions for "Timestamp" (marker 0xFC). http://named-data.net/doc/tech-memos/naming-conventions.pdf :return: The number of microseconds since the UNIX epoch (Thursday, 1 January 1970) not counting leap seconds. :rtype: int :raises RuntimeError: If the first byte of the component is not the expected marker. """ return self.toNumberWithMarker(0xFC) def toSequenceNumber(self): """ Interpret this name component as a sequence number according to NDN naming conventions for "Sequencing" (marker 0xFE). http://named-data.net/doc/tech-memos/naming-conventions.pdf :return: The integer sequence number. :rtype: int :raises RuntimeError: If the first byte of the component is not the expected marker. """ return self.toNumberWithMarker(0xFE) def equals(self, other): """ Check if this is the same component as other. :param Name.Component other: The other Component to compare with. :return: True if the components are equal, otherwise False. :rtype: bool """ return self._value.equals(other._value) and self._type == other._type def compare(self, other): """ Compare this to the other Component using NDN canonical ordering. :param Name.Component other: The other Component to compare with. :return: 0 If they compare equal, -1 if self comes before other in the canonical ordering, or 1 if self comes after other in the canonical ordering. :rtype: int :see: http://named-data.net/doc/0.2/technical/CanonicalOrder.html """ if self._type < other._type: return -1 if self._type > other._type: return 1 if self._value.size() < other._value.size(): return -1 if self._value.size() > other._value.size(): return 1 # The components are equal length. Just do a byte compare. return self._value.compare(other._value) @staticmethod def fromNumber(number): """ Create a component whose value is the nonNegativeInteger encoding of the number. :param int number: The number to be encoded. :return: The component value. :rtype: Name.Component """ encoder = TlvEncoder(8) encoder.writeNonNegativeInteger(number) return Name.Component(Blob(encoder.getOutput(), False)) @staticmethod def fromNumberWithMarker(number, marker): """ Create a component whose value is the marker appended with the nonNegativeInteger encoding of the number. :param int number: The number to be encoded. :param int marker: The marker to use as the first byte of the component. :return: The component value. :rtype: Name.Component """ encoder = TlvEncoder(9) # Encode backwards. encoder.writeNonNegativeInteger(number) encoder.writeNonNegativeInteger(marker) return Name.Component(Blob(encoder.getOutput(), False)) @staticmethod def fromSegment(segment): """ Create a component with the encoded segment number according to NDN naming conventions for "Segment number" (marker 0x00). http://named-data.net/doc/tech-memos/naming-conventions.pdf :param int segment: The segment number. :return: The new Component. :rtype: Name.Component """ return Name.Component.fromNumberWithMarker(segment, 0x00) @staticmethod def fromSegmentOffset(segmentOffset): """ Create a component with the encoded segment byte offset according to NDN naming conventions for segment "Byte offset" (marker 0xFB). http://named-data.net/doc/tech-memos/naming-conventions.pdf :param int segmentOffset: The segment byte offset. :return: The new Component. :rtype: Name.Component """ return Name.Component.fromNumberWithMarker(segmentOffset, 0xFB) @staticmethod def fromVersion(version): """ Create a component with the encoded version number according to NDN naming conventions for "Versioning" (marker 0xFD). http://named-data.net/doc/tech-memos/naming-conventions.pdf Note that this encodes the exact value of version without converting from a time representation. :param int version: The version number. :return: The new Component. :rtype: Name.Component """ return Name.Component.fromNumberWithMarker(version, 0xFD) @staticmethod def fromTimestamp(timestamp): """ Create a component with the encoded timestamp according to NDN naming conventions for "Timestamp" (marker 0xFC). http://named-data.net/doc/tech-memos/naming-conventions.pdf :param int timestamp: The number of microseconds since the UNIX epoch (Thursday, 1 January 1970) not counting leap seconds. :return: The new Component. :rtype: Name.Component """ return Name.Component.fromNumberWithMarker(timestamp, 0xFC) @staticmethod def fromSequenceNumber(sequenceNumber): """ Create a component with the encoded sequence number according to NDN naming conventions for "Sequencing" (marker 0xFE). http://named-data.net/doc/tech-memos/naming-conventions.pdf :param int sequenceNumber: The sequence number. :return: The new Component. :rtype: Name.Component """ return Name.Component.fromNumberWithMarker(sequenceNumber, 0xFE) @staticmethod def fromImplicitSha256Digest(digest): """ Create a component of type ImplicitSha256DigestComponent, so that isImplicitSha256Digest() is true. :param digest: The SHA-256 digest value. :type digest: Blob or value for Blob constructor :return: The new Component. :rtype: Name.Component :raises RuntimeError: If the digest length is not 32 bytes. """ digestBlob = digest if isinstance(digest, Blob) else Blob(digest) if digestBlob.size() != 32: raise RuntimeError( "Name.Component.fromImplicitSha256Digest: The digest length must be 32 bytes") result = Name.Component(digestBlob) result._type = Name.Component.ComponentType.IMPLICIT_SHA256_DIGEST return result def getSuccessor(self): """ Get the successor of this component, as described in Name.getSuccessor. :return: A new Name.Component which is the successor of this. :rtype: Name.Component """ # Allocate an extra byte in case the result is larger. result = bytearray(self._value.size() + 1) carry = True for i in range(self._value.size() - 1, -1, -1): if carry: result[i] = (self._value.buf()[i] + 1) & 0xff carry = (result[i] == 0) else: result[i] = self._value.buf()[i] if carry: # Assume all the bytes were set to zero (or the component was # empty). In NDN ordering, carry does not mean to prepend a 1, # but to make a component one byte longer of all zeros. result[len(result) - 1] = 0 else: # We didn't need the extra byte. result = result[0:self._value.size()] return Name.Component(Blob(result, False)) # Python operators def __eq__(self, other): return type(other) is Name.Component and self.equals(other) def __ne__(self, other): return not self == other def __le__(self, other): return self.compare(other) <= 0 def __lt__(self, other): return self.compare(other) < 0 def __ge__(self, other): return self.compare(other) >= 0 def __gt__(self, other): return self.compare(other) > 0 def __len__(self): return self._value.size() def __str__(self): return self.toEscapedString() def __hash__(self): return hash(self._value)
def verifySignature(buffer, signature, publicKey, digestAlgorithm = DigestAlgorithm.SHA256): """ Verify the buffer against the signature using the public key. :param buffer: The input buffer to verify. :type buffer: Blob or an object which is the same as the bytes() operator :param signature: The signature bytes. :type signature: Blob or an object which is the same as the bytes() operator :param publicKey: The object containing the public key, or the public key DER which is used to make the PublicKey object. :type publicKey: PublicKey or Blob or an object which is the same as the bytes() operator :param digestAlgorithm: (optional) The digest algorithm. If omitted, use DigestAlgorithm.SHA256. :type digestAlgorithm: int from DigestAlgorithm :return: True if verification succeeds, False if verification fails. :rtype: bool :raises: ValueError for an invalid public key type or digestAlgorithm. """ if digestAlgorithm == None: digestAlgorithm = DigestAlgorithm.SHA256 if isinstance(buffer, Blob): buffer = buffer.toBytes() if isinstance(signature, Blob): signature = signature.toBytes() if not isinstance(publicKey, PublicKey): # Turn publicKey into a PublicKey object. if not isinstance(publicKey, Blob): publicKey = Blob(publicKey) publicKey = PublicKey(publicKey) if digestAlgorithm == DigestAlgorithm.SHA256: if publicKey.getKeyType() == KeyType.RSA: # Get the public key. try: cryptoPublicKey = load_der_public_key( publicKey.getKeyDer().toBytes(), backend = default_backend()) except: return False try: cryptoPublicKey.verify( signature, buffer, padding.PKCS1v15(), hashes.SHA256()) return True except: return False elif publicKey.getKeyType() == KeyType.EC: # Get the public key. try: cryptoPublicKey = load_der_public_key( publicKey.getKeyDer().toBytes(), backend = default_backend()) except: return False try: cryptoPublicKey.verify( signature, buffer, ec.ECDSA(hashes.SHA256())) return True except: return False else: raise ValueError("verifySignature: Invalid key type") else: raise ValueError("verifySignature: Invalid digest algorithm")
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 PublicKey(object): """ Create a new PublicKey by decoding the keyDer. Set the key type from the decoding. :param Blob keyDer: The blob of the PublicKeyInfo in terms of DER. :raises: UnrecognizedKeyFormatException if can't decode the key DER. """ def __init__(self, keyDer = None): # TODO: Implementation of managed properties? if keyDer == None: self._keyDer = Blob() self._keyType = None return self._keyDer = keyDer # Get the public key OID. oidString = "" try: parsedNode = DerNode.parse(keyDer.buf(), 0) rootChildren = parsedNode.getChildren() algorithmIdChildren = DerNode.getSequence( rootChildren, 0).getChildren() oidString = algorithmIdChildren[0].toVal() except DerDecodingException as ex: raise UnrecognizedKeyFormatException( "PublicKey.decodeKeyType: Error decoding the public key: " + str(ex)) # Verify that the we can decode. if oidString == self.RSA_ENCRYPTION_OID: self._keyType = KeyType.RSA serialization.load_der_public_key( keyDer.toBytes(), backend = default_backend()) elif oidString == self.EC_ENCRYPTION_OID: self._keyType = KeyType.EC # TODO: Check EC decoding. else: raise UnrecognizedKeyFormatException( "PublicKey.decodeKeyType: Unrecognized OID " + oidString) def toDer(self): """ Encode the public key into DER. :return: The encoded DER syntax tree. :rtype: DerNode """ return DerNode.parse(self._keyDer) def getDigest(self, digestAlgorithm = DigestAlgorithm.SHA256): """ Get the digest of the public key. :param digestAlgorithm: (optional) The digest algorithm. If omitted, use DigestAlgorithm.SHA256 . :type digestAlgorithm: int from DigestAlgorithm :return: The digest value :rtype: Blob """ if digestAlgorithm == DigestAlgorithm.SHA256: sha256 = hashes.Hash(hashes.SHA256(), backend=default_backend()) sha256.update(self._keyDer.toBytes()) digest = sha256.finalize() return Blob(bytearray(digest), False) else: raise RuntimeError("Unimplemented digest algorithm") def getKeyType(self): """ Get the key type. :return: The key type :rtype: an int from KeyType """ return self._keyType def getKeyDer(self): """ Get the raw bytes of the public key in DER format. :return: The public key DER :rtype: Blob """ return self._keyDer def encrypt(self, plainData, algorithmType): """ Encrypt the plainData using the keyBits according the encrypt algorithm type. :param plainData: The data to encrypt. :type plainData: Blob or an object which is the same as the bytes() operator :param int algorithmType: The algorithm type from EncryptAlgorithmType. This encrypts according to the algorithm type, e.g., RsaOaep. :return: The encrypted data. :rtype: Blob """ if isinstance(plainData, Blob): plainData = plainData.toBytes() publicKey = serialization.load_der_public_key( self._keyDer.toBytes(), backend = default_backend()) if algorithmType == EncryptAlgorithmType.RsaOaep: if self._keyType != KeyType.RSA: raise RuntimeError("The key type must be RSA") paddingObject = padding.OAEP( mgf = padding.MGF1(algorithm = hashes.SHA1()), algorithm = hashes.SHA1(), label = None) elif algorithmType == EncryptAlgorithmType.RsaPkcs: if self._keyType != KeyType.RSA: raise RuntimeError("The key type must be RSA") paddingObject = padding.PKCS1v15() else: raise RuntimeError("unsupported encryption mode") result = publicKey.encrypt(plainData, paddingObject) return Blob(result, False) RSA_ENCRYPTION_OID = "1.2.840.113549.1.1.1" EC_ENCRYPTION_OID = "1.2.840.10045.2.1"