Ejemplo n.º 1
0
    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)
Ejemplo n.º 2
0
    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")
Ejemplo n.º 3
0
    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)
Ejemplo n.º 4
0
    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
Ejemplo n.º 5
0
    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
Ejemplo n.º 6
0
    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)
Ejemplo n.º 7
0
    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)
Ejemplo n.º 8
0
 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
Ejemplo n.º 9
0
 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
Ejemplo n.º 10
0
    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)
Ejemplo n.º 11
0
    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)
Ejemplo n.º 12
0
 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
Ejemplo n.º 13
0
 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)
Ejemplo n.º 14
0
    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)
Ejemplo n.º 15
0
 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)
Ejemplo n.º 16
0
Archivo: name.py Proyecto: MAHIS/PyNDN2
 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)
Ejemplo n.º 17
0
    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)
Ejemplo n.º 18
0
    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
Ejemplo n.º 19
0
    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))
Ejemplo n.º 20
0
    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
Ejemplo n.º 21
0
    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
Ejemplo n.º 22
0
    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
Ejemplo n.º 23
0
    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)
Ejemplo n.º 24
0
    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())
Ejemplo n.º 25
0
    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()
Ejemplo n.º 26
0
    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")
Ejemplo n.º 27
0
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)
Ejemplo n.º 28
0
 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
Ejemplo n.º 29
0
    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)
Ejemplo n.º 30
0
 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)
Ejemplo n.º 32
0
        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")
Ejemplo n.º 33
0
    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)
Ejemplo n.º 34
0
 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)
Ejemplo n.º 35
0
    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
Ejemplo n.º 36
0
    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
Ejemplo n.º 37
0
    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
Ejemplo n.º 38
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
Ejemplo n.º 39
0
        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))
Ejemplo n.º 40
0
    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()
Ejemplo n.º 41
0
        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
Ejemplo n.º 43
0
    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
Ejemplo n.º 44
0
    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
Ejemplo n.º 45
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"
Ejemplo n.º 46
0
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
Ejemplo n.º 47
0
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)
Ejemplo n.º 48
0
    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()
Ejemplo n.º 49
0
    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)
Ejemplo n.º 50
0
    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")
Ejemplo n.º 51
0
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
Ejemplo n.º 52
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
            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"