def _decryptDKey(self, dKeyData, onPlainText, onError): """ Decrypt dKeyData. :param Data dKeyData: The D-KEY data packet. :param onPlainText: When the data packet is decrypted, this calls onPlainText(decryptedBlob) with the decrypted blob. :type onPlainText: function object :param onError: This calls onError(errorCode, message) for an error, where errorCode is from EncryptError.ErrorCode and message is a str. :type onError: function object """ # Get encrypted content. dataContent = dKeyData.getContent() # Process the nonce. # dataContent is a sequence of the two EncryptedContent. encryptedNonce = EncryptedContent() try: encryptedNonce.wireDecode(dataContent) except Exception as ex: try: onError(EncryptError.ErrorCode.InvalidEncryptedFormat, repr(ex)) except: logging.exception("Error in onError") return consumerKeyName = encryptedNonce.getKeyLocator().getKeyName() # Get consumer decryption key. try: consumerKeyBlob = self._getDecryptionKey(consumerKeyName) except Exception as ex: Consumer._callOnError(onError, EncryptError.ErrorCode.NoDecryptKey, "Database error: " + repr(ex)) return if consumerKeyBlob.size() == 0: try: onError(EncryptError.ErrorCode.NoDecryptKey, "The desired consumer decryption key in not in the database") except: logging.exception("Error in onError") return # Process the D-KEY. # Use the size of encryptedNonce to find the start of encryptedPayload. encryptedPayloadBlob = Blob( dataContent.buf()[encryptedNonce.wireEncode().size():], False) if encryptedPayloadBlob.size() == 0: try: onError(EncryptError.ErrorCode.InvalidEncryptedFormat, "The data packet does not satisfy the D-KEY packet format") except: logging.exception("Error in onError") # Decrypt the D-KEY. Consumer._decrypt( encryptedNonce, consumerKeyBlob, lambda nonceKeyBits: Consumer._decrypt( encryptedPayloadBlob, nonceKeyBits, onPlainText, onError), onError)
def _encryptSymmetric(payload, key, keyName, params): """ Encrypt the payload using the symmetric key according to params, and return an EncryptedContent. :param Blob payload: The data to encrypt. :param Blob key: The key value. :param Name keyName: The key name for the EncryptedContent key locator. :param EncryptParams params: The parameters for encryption. :return: A new EncryptedContent. :rtype: EncryptedContent """ algorithmType = params.getAlgorithmType() initialVector = params.getInitialVector() keyLocator = KeyLocator() keyLocator.setType(KeyLocatorType.KEYNAME) keyLocator.setKeyName(keyName) if (algorithmType == EncryptAlgorithmType.AesCbc or algorithmType == EncryptAlgorithmType.AesEcb): if (algorithmType == EncryptAlgorithmType.AesCbc): if initialVector.size() != AesAlgorithm.BLOCK_SIZE: raise RuntimeError("incorrect initial vector size") encryptedPayload = AesAlgorithm.encrypt(key, payload, params) result = EncryptedContent() result.setAlgorithmType(algorithmType) result.setKeyLocator(keyLocator) result.setPayload(encryptedPayload) result.setInitialVector(initialVector) return result else: raise RuntimeError("Unsupported encryption method")
def _decryptAndImportKdk(self, kdkData, onError): """ :param Data kdkData: :param onError: On error, this calls onError(errorCode, message) :type onError: function object :return: True for success, false for error (where this has called onError). :rtype: bool """ try: logging.getLogger(__name__).info("Decrypting and importing KDK " + kdkData.getName().toUri()) encryptedContent = EncryptedContent() encryptedContent.wireDecodeV2(kdkData.getContent()) safeBag = SafeBag(encryptedContent.getPayload()) secret = self._keyChain.getTpm().decrypt( encryptedContent.getPayloadKey().toBytes(), self._credentialsKey.getName()) if secret.isNull(): onError(EncryptError.ErrorCode.TpmKeyNotFound, "Could not decrypt secret, " + self._credentialsKey.getName().toUri() + " not found in TPM") return False self._internalKeyChain.importSafeBag(safeBag, secret.toBytes()) return True except Exception as ex: onError(EncryptError.ErrorCode.DecryptionFailure, "Failed to decrypt KDK [" + kdkData.getName().toUri() + "]: " + repr(ex)) return False
def _decrypt(encryptedContent, keyBits, onPlainText, onError): """ Decrypt encryptedContent using keyBits. :param encryptedContent: The EncryptedContent to decrypt, or a Blob which is first decoded as an EncryptedContent. :type encryptedContent: Blob or EncryptedContent :param {Blob} keyBits The key value. :param onPlainText: When encryptedBlob 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 """ if isinstance(encryptedContent, Blob): # Decode as EncryptedContent. encryptedBlob = encryptedContent encryptedContent = EncryptedContent() encryptedContent.wireDecode(encryptedBlob) payload = encryptedContent.getPayload() if encryptedContent.getAlgorithmType() == EncryptAlgorithmType.AesCbc: # Prepare the parameters. decryptParams = EncryptParams(EncryptAlgorithmType.AesCbc) decryptParams.setInitialVector(encryptedContent.getInitialVector()) # Decrypt the content. try: content = AesAlgorithm.decrypt(keyBits, payload, decryptParams) except Exception as ex: try: onError(EncryptError.ErrorCode.InvalidEncryptedFormat, repr(ex)) except: logging.exception("Error in onError") return onPlainText(content) elif encryptedContent.getAlgorithmType( ) == EncryptAlgorithmType.RsaOaep: # Prepare the parameters. decryptParams = EncryptParams(EncryptAlgorithmType.RsaOaep) # Decrypt the content. try: content = RsaAlgorithm.decrypt(keyBits, payload, decryptParams) except Exception as ex: Consumer._callOnError( onError, EncryptError.ErrorCode.InvalidEncryptedFormat, repr(ex)) return onPlainText(content) else: Consumer._callOnError( onError, EncryptError.ErrorCode.UnsupportedEncryptionScheme, repr(encryptedContent.getAlgorithmType()))
def _decryptCKey(self, cKeyData, onPlainText, onError): """ Decrypt cKeyData. :param Data cKeyData: The C-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 the encrypted content. cKeyContent = cKeyData.getContent() cKeyEncryptedContent = EncryptedContent() try: cKeyEncryptedContent.wireDecode(cKeyContent) except Exception as ex: try: onError(EncryptError.ErrorCode.InvalidEncryptedFormat, repr(ex)) except: logging.exception("Error in onError") return eKeyName = cKeyEncryptedContent.getKeyLocator().getKeyName() dKeyName = eKeyName.getPrefix(-3) dKeyName.append(Encryptor.NAME_COMPONENT_D_KEY).append( eKeyName.getSubName(-2)) # Check if the decryption key is already in the store. if dKeyName in self._dKeyMap: dKey = self._dKeyMap[dKeyName] Consumer._decrypt(cKeyEncryptedContent, dKey, onPlainText, onError) else: # Get the D-Key Data. interestName = Name(dKeyName) interestName.append(Encryptor.NAME_COMPONENT_FOR).append( self._consumerName) interest = Interest(interestName) def onVerified(validDKeyData): def localOnPlainText(dKeyBits): # dKeyName is already a local copy. self._dKeyMap[dKeyName] = dKeyBits Consumer._decrypt(cKeyEncryptedContent, dKeyBits, onPlainText, onError) self._decryptDKey(validDKeyData, localOnPlainText, onError) self._sendInterest(interest, 1, self._dKeyLink, onVerified, onError)
def _encryptAsymmetric(payload, key, keyName, params): """ Encrypt the payload using the asymmetric key according to params, and return an EncryptedContent. :param Blob payload: The data to encrypt. The size should be within range of the key. :param Blob key: The key value. :param Name keyName: The key name for the EncryptedContent key locator. :param EncryptParams params: The parameters for encryption. :return: A new EncryptedContent. :rtype: EncryptedContent """ algorithmType = params.getAlgorithmType() keyLocator = KeyLocator() keyLocator.setType(KeyLocatorType.KEYNAME) keyLocator.setKeyName(keyName) if (algorithmType == EncryptAlgorithmType.RsaPkcs or algorithmType == EncryptAlgorithmType.RsaOaep): encryptedPayload = RsaAlgorithm.encrypt(key, payload, params) result = EncryptedContent() result.setAlgorithmType(algorithmType) result.setKeyLocator(keyLocator) result.setPayload(encryptedPayload) return result else: raise RuntimeError("Unsupported encryption method")
def encrypt(self, plainData): """ Encrypt the plainData using the existing Content Key (CK) and return a new EncryptedContent. :param plainData: The data to encrypt. :type plainData: Blob or an array which implements the buffer protocol :return: The new EncryptedContent. :rtype: EncryptedContent """ # Generate the initial vector. initialVector = bytearray(EncryptorV2.AES_IV_SIZE) for i in range(len(initialVector)): initialVector[i] = _systemRandom.randint(0, 0xff) params = EncryptParams(EncryptAlgorithmType.AesCbc) params.setInitialVector(Blob(initialVector, False)) encryptedData = AesAlgorithm.encrypt(Blob(self._ckBits, False), Blob(plainData, False), params) content = EncryptedContent() content.setInitialVector(params.getInitialVector()) content.setPayload(encryptedData) content.setKeyLocatorName(self._ckName) return content
def _decryptCKey(self, cKeyData, onPlainText, onError): """ Decrypt cKeyData. :param Data cKeyData: The C-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 the encrypted content. cKeyContent = cKeyData.getContent() cKeyEncryptedContent = EncryptedContent() try: cKeyEncryptedContent.wireDecode(cKeyContent) except Exception as ex: try: onError(EncryptError.ErrorCode.InvalidEncryptedFormat, repr(ex)) except: logging.exception("Error in onError") return eKeyName = cKeyEncryptedContent.getKeyLocator().getKeyName() dKeyName = eKeyName.getPrefix(-3) dKeyName.append(Encryptor.NAME_COMPONENT_D_KEY).append( eKeyName.getSubName(-2)) # Check if the decryption key is already in the store. if dKeyName in self._dKeyMap: dKey = self._dKeyMap[dKeyName] Consumer._decrypt(cKeyEncryptedContent, dKey, onPlainText, onError) else: # Get the D-Key Data. interestName = Name(dKeyName) interestName.append(Encryptor.NAME_COMPONENT_FOR).append( self._consumerName) interest = Interest(interestName) def onVerified(validDKeyData): def localOnPlainText(dKeyBits): # dKeyName is already a local copy. self._dKeyMap[dKeyName] = dKeyBits Consumer._decrypt( cKeyEncryptedContent, dKeyBits, onPlainText, onError) self._decryptDKey(validDKeyData, localOnPlainText, onError) self._sendInterest(interest, 1, self._dKeyLink, onVerified, onError)
def _decryptContent(self, data, onPlainText, onError): """ Decrypt the data packet. :param Data data: The data packet. This does not verify the 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 the encrypted content. dataEncryptedContent = EncryptedContent() try: dataEncryptedContent.wireDecode(data.getContent()) except Exception as ex: Consumer._callOnError( onError, EncryptError.ErrorCode.InvalidEncryptedFormat, repr(ex)) return cKeyName = dataEncryptedContent.getKeyLocator().getKeyName() # Check if the content key is already in the store. if cKeyName in self._cKeyMap: cKey = self._cKeyMap[cKeyName] self._decrypt(dataEncryptedContent, cKey, onPlainText, onError) else: # Retrieve the C-KEY Data from the network. interestName = Name(cKeyName) interestName.append(Encryptor.NAME_COMPONENT_FOR).append( self._groupName) interest = Interest(interestName) def onVerified(validCKeyData): def localOnPlainText(cKeyBits): # cKeyName is already a copy inside the local # dataEncryptedContent. self._cKeyMap[cKeyName] = cKeyBits Consumer._decrypt(dataEncryptedContent, cKeyBits, onPlainText, onError) self._decryptCKey(validCKeyData, localOnPlainText, onError) self._sendInterest(interest, 1, self._cKeyLink, onVerified, onError)
def encrypt(self, plainData): """ Encrypt the plainData using the existing Content Key (CK) and return a new EncryptedContent. :param plainData: The data to encrypt. :type plainData: Blob or an array which implements the buffer protocol :return: The new EncryptedContent. :rtype: EncryptedContent """ # Generate the initial vector. initialVector = bytearray(EncryptorV2.AES_IV_SIZE) for i in range(len(initialVector)): initialVector[i] = _systemRandom.randint(0, 0xff) params = EncryptParams(EncryptAlgorithmType.AesCbc) params.setInitialVector(Blob(initialVector, False)) encryptedData = AesAlgorithm.encrypt( Blob(self._ckBits, False), Blob(plainData, False), params) content = EncryptedContent() content.setInitialVector(params.getInitialVector()) content.setPayload(encryptedData) content.setKeyLocatorName(self._ckName) return content
def _decrypt(encryptedContent, keyBits, onPlainText, onError): """ Decrypt encryptedContent using keyBits. :param encryptedContent: The EncryptedContent to decrypt, or a Blob which is first decoded as an EncryptedContent. :type encryptedContent: Blob or EncryptedContent :param {Blob} keyBits The key value. :param onPlainText: When encryptedBlob 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 """ if isinstance(encryptedContent, Blob): # Decode as EncryptedContent. encryptedBlob = encryptedContent encryptedContent = EncryptedContent() encryptedContent.wireDecode(encryptedBlob) payload = encryptedContent.getPayload() if encryptedContent.getAlgorithmType() == EncryptAlgorithmType.AesCbc: # Prepare the parameters. decryptParams = EncryptParams(EncryptAlgorithmType.AesCbc) decryptParams.setInitialVector(encryptedContent.getInitialVector()) # Decrypt the content. try: content = AesAlgorithm.decrypt(keyBits, payload, decryptParams) except Exception as ex: try: onError(EncryptError.ErrorCode.InvalidEncryptedFormat, repr(ex)) except: logging.exception("Error in onError") return onPlainText(content) elif encryptedContent.getAlgorithmType() == EncryptAlgorithmType.RsaOaep: # Prepare the parameters. decryptParams = EncryptParams(EncryptAlgorithmType.RsaOaep) # Decrypt the content. try: content = RsaAlgorithm.decrypt(keyBits, payload, decryptParams) except Exception as ex: Consumer._callOnError(onError, EncryptError.ErrorCode.InvalidEncryptedFormat, repr(ex)) return onPlainText(content) else: Consumer._callOnError(onError, EncryptError.ErrorCode.UnsupportedEncryptionScheme, repr(encryptedContent.getAlgorithmType()))
def _decryptContent(self, data, onPlainText, onError): """ Decrypt the data packet. :param Data data: The data packet. This does not verify the 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 the encrypted content. dataEncryptedContent = EncryptedContent() try: dataEncryptedContent.wireDecode(data.getContent()) except Exception as ex: Consumer._callOnError(onError, EncryptError.ErrorCode.InvalidEncryptedFormat, repr(ex)) return cKeyName = dataEncryptedContent.getKeyLocator().getKeyName() # Check if the content key is already in the store. if cKeyName in self._cKeyMap: cKey = self._cKeyMap[cKeyName] self._decrypt(dataEncryptedContent, cKey, onPlainText, onError) else: # Retrieve the C-KEY Data from the network. interestName = Name(cKeyName) interestName.append(Encryptor.NAME_COMPONENT_FOR).append(self._groupName) interest = Interest(interestName) def onVerified(validCKeyData): def localOnPlainText(cKeyBits): # cKeyName is already a copy inside the local # dataEncryptedContent. self._cKeyMap[cKeyName] = cKeyBits Consumer._decrypt( dataEncryptedContent, cKeyBits, onPlainText, onError) self._decryptCKey(validCKeyData, localOnPlainText, onError) self._sendInterest(interest, 1, self._cKeyLink, onVerified, onError)
def _makeAndPublishCkData(self, onError): """ Make a CK Data packet for _ckName encrypted by the KEK in _kekData and insert it in the _storage. :param onError: On failure, this calls onError(errorCode, message) where errorCode is from EncryptError.ErrorCode, and message is an error string. :type onError: function object :return: True on success, else False. :rtype: bool """ try: kek = PublicKey(self._kekData.getContent()) content = EncryptedContent() content.setPayload( kek.encrypt(Blob(self._ckBits, False), EncryptAlgorithmType.RsaOaep)) ckData = Data( Name(self._ckName).append( EncryptorV2.NAME_COMPONENT_ENCRYPTED_BY).append( self._kekData.getName())) ckData.setContent(content.wireEncodeV2()) # FreshnessPeriod can serve as a soft access control for revoking access. ckData.getMetaInfo().setFreshnessPeriod( EncryptorV2.DEFAULT_CK_FRESHNESS_PERIOD_MS) self._keyChain.sign(ckData, self._ckDataSigningInfo) self._storage.insert(ckData) logging.getLogger(__name__).info("Publishing CK data: " + ckData.getName().toUri()) return True except Exception as ex: onError( EncryptError.ErrorCode.EncryptionFailure, "Failed to encrypt generated CK with KEK " + self._kekData.getName().toUri()) return False
def _decryptAndImportKdk(self, kdkData, onError): """ :param Data kdkData: :param onError: On error, this calls onError(errorCode, message) :type onError: function object :return: True for success, false for error (where this has called onError). :rtype: bool """ try: logging.getLogger(__name__).info("Decrypting and importing KDK " + kdkData.getName().toUri()) encryptedContent = EncryptedContent() encryptedContent.wireDecodeV2(kdkData.getContent()) safeBag = SafeBag(encryptedContent.getPayload()) secret = self._keyChain.getTpm().decrypt( encryptedContent.getPayloadKey().toBytes(), self._credentialsKey.getName()) if secret.isNull(): onError( EncryptError.ErrorCode.TpmKeyNotFound, "Could not decrypt secret, " + credentialsKey_.getName().toUri() + " not found in TPM") return False self._internalKeyChain.importSafeBag(safeBag, secret.toBytes()) return True except Exception as ex: onError( EncryptError.ErrorCode.DecryptionFailure, "Failed to decrypt KDK [" + kdkData.getName().toUri() + "]: " + repr(ex)) return False
def _decryptCkAndProcessPendingDecrypts(self, contentKey, ckData, kdkKeyName, onError): logging.getLogger(__name__).info("Decrypting CK data ", ckData.getName().toUri()) content = EncryptedContent() try: content.wireDecodeV2(ckData.getContent()) except Exception as ex: onError(EncryptError.ErrorCode.InvalidEncryptedFormat, "Error decrypting EncryptedContent: " + repr(ex)) return try: ckBits = self._internalKeyChain.getTpm().decrypt( content.getPayload().toBytes(), kdkKeyName) except Exception as ex: # We don't expect this from the in-memory KeyChain. onError(EncryptError.ErrorCode.DecryptionFailure, "Error decrypting the CK EncryptedContent " + repr(ex)) return if ckBits.isNull(): onError( EncryptError.ErrorCode.TpmKeyNotFound, "Could not decrypt secret, " + kdkKeyName.toUri() + " not found in TPM") return contentKey.bits = ckBits contentKey.isRetrieved = True for pendingDecrypt in contentKey.pendingDecrypts: # TODO: If this calls onError, should we quit? DecryptorV2._doDecrypt(pendingDecrypt.encryptedContent, contentKey.bits, pendingDecrypt.onSuccess, pendingDecrypt.onError) contentKey.pendingDecrypts = []
def _decryptCkAndProcessPendingDecrypts( self, contentKey, ckData, kdkKeyName, onError): logging.getLogger(__name__).info("Decrypting CK data " + ckData.getName().toUri()) content = EncryptedContent() try: content.wireDecodeV2(ckData.getContent()) except Exception as ex: onError(EncryptError.ErrorCode.InvalidEncryptedFormat, "Error decrypting EncryptedContent: " + repr(ex)) return try: ckBits = self._internalKeyChain.getTpm().decrypt( content.getPayload().toBytes(), kdkKeyName) except Exception as ex: # We don't expect this from the in-memory KeyChain. onError(EncryptError.ErrorCode.DecryptionFailure, "Error decrypting the CK EncryptedContent " + repr(ex)) return if ckBits.isNull(): onError(EncryptError.ErrorCode.TpmKeyNotFound, "Could not decrypt secret, " + kdkKeyName.toUri() + " not found in TPM") return contentKey.bits = ckBits contentKey.isRetrieved = True for pendingDecrypt in contentKey.pendingDecrypts: # TODO: If this calls onError, should we quit? DecryptorV2._doDecrypt( pendingDecrypt.encryptedContent, contentKey.bits, pendingDecrypt.onSuccess, pendingDecrypt.onError) contentKey.pendingDecrypts = []
def addMember(self, memberCertificate): """ Authorize a member identified by memberCertificate to decrypt data under the policy. :param CertificateV2 memberCertificate: The certificate that identifies the member to authorize. :return: The published KDK Data packet. :rtype: Data """ kdkName = Name(self._nacKey.getIdentityName()) kdkName.append(EncryptorV2.NAME_COMPONENT_KDK).append( # key-id self._nacKey.getName().get(-1)).append( EncryptorV2.NAME_COMPONENT_ENCRYPTED_BY).append( memberCertificate.getKeyName()) secretLength = 32 secret = bytearray(secretLength) for i in range(secretLength): secret[i] = _systemRandom.randint(0, 0xff) # To be compatible with OpenSSL which uses a null-terminated string, # replace each 0 with 1. And to be compatible with the Java security # library which interprets the secret as a char array converted to UTF8, # limit each byte to the ASCII range 1 to 127. for i in range(secretLength): if secret[i] == 0: secret[i] = 1 secret[i] &= 0x7f kdkSafeBag = self._keyChain.exportSafeBag( self._nacKey.getDefaultCertificate(), Blob(secret, False).toBytes()) memberKey = PublicKey(memberCertificate.getPublicKey()) encryptedContent = EncryptedContent() encryptedContent.setPayload(kdkSafeBag.wireEncode()) encryptedContent.setPayloadKey( memberKey.encrypt( Blob(secret, False).toBytes(), EncryptAlgorithmType.RsaOaep)) kdkData = Data(kdkName) kdkData.setContent(encryptedContent.wireEncodeV2()) # FreshnessPeriod can serve as a soft access control for revoking access. kdkData.getMetaInfo().setFreshnessPeriod( AccessManagerV2.DEFAULT_KDK_FRESHNESS_PERIOD_MS) self._keyChain.sign(kdkData, SigningInfo(self._identity)) self._storage.insert(kdkData) return kdkData
def _makeAndPublishCkData(self, onError): """ Make a CK Data packet for _ckName encrypted by the KEK in _kekData and insert it in the _storage. :param onError: On failure, this calls onError(errorCode, message) where errorCode is from EncryptError.ErrorCode, and message is an error string. :type onError: function object :return: True on success, else False. :rtype: bool """ try: kek = PublicKey(self._kekData.getContent()) content = EncryptedContent() content.setPayload(kek.encrypt (Blob(self._ckBits, False), EncryptAlgorithmType.RsaOaep)) ckData = Data( Name(self._ckName).append(EncryptorV2.NAME_COMPONENT_ENCRYPTED_BY) .append(self._kekData.getName())) ckData.setContent(content.wireEncodeV2()) # FreshnessPeriod can serve as a soft access control for revoking access. ckData.getMetaInfo().setFreshnessPeriod( EncryptorV2.DEFAULT_CK_FRESHNESS_PERIOD_MS) self._keyChain.sign(ckData, self._ckDataSigningInfo) self._storage.insert(ckData) logging.getLogger(__name__).info("Publishing CK data: " + ckData.getName().toUri()) return True except Exception as ex: onError(EncryptError.ErrorCode.EncryptionFailure, "Failed to encrypt generated CK with KEK " + self._kekData.getName().toUri()) return False
def _decryptCKey(self, cKeyData, onPlainText, onError): """ Decrypt cKeyData. :param Data cKeyData: The C-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 the encrypted content. cKeyContent = cKeyData.getContent() cKeyEncryptedContent = EncryptedContent() try: cKeyEncryptedContent.wireDecode(cKeyContent) except Exception as ex: try: onError(EncryptError.ErrorCode.InvalidEncryptedFormat, repr(ex)) except: logging.exception("Error in onError") return eKeyName = cKeyEncryptedContent.getKeyLocator().getKeyName() dKeyName = eKeyName.getPrefix(-3) dKeyName.append(Encryptor.NAME_COMPONENT_D_KEY).append( eKeyName.getSubName(-2)) # Check if the decryption key is already in the store. if dKeyName in self._dKeyMap: dKey = self._dKeyMap[dKeyName] Consumer._decrypt(cKeyEncryptedContent, dKey, onPlainText, onError) else: # Get the D-Key Data. interestName = Name(dKeyName) interestName.append(Encryptor.NAME_COMPONENT_FOR).append( self._consumerName) interest = Interest(interestName) # Prepare the callback functions. def onData(dKeyInterest, dKeyData): # The Interest has no selectors, so assume the library correctly # matched with the Data name before calling onData. try: def onVerified(validDKeyData): def localOnPlainText(dKeyBits): # dKeyName is already a local copy. self._dKeyMap[dKeyName] = dKeyBits Consumer._decrypt( cKeyEncryptedContent, dKeyBits, onPlainText, onError) self._decryptDKey(validDKeyData, localOnPlainText, onError) self._keyChain.verifyData( dKeyData, onVerified, lambda d: Consumer._callOnError(onError, EncryptError.ErrorCode.Validation, "verifyData failed")) except Exception as ex: try: onError(EncryptError.ErrorCode.General, "verifyData error: " + repr(ex)) except: logging.exception("Error in onError") def onTimeout(dKeyInterest): # We should re-try at least once. try: self._face.expressInterest( interest, onData, lambda contentInterest: Consumer._callOnError(onError, EncryptError.ErrorCode.Timeout, interest.getName().toUri())) except Exception as ex: try: onError(EncryptError.ErrorCode.General, "expressInterest error: " + repr(ex)) except: logging.exception("Error in onError") # Express the Interest. try: self._face.expressInterest(interest, onData, onTimeout) except Exception as ex: try: onError(EncryptError.ErrorCode.General, "expressInterest error: " + repr(ex)) except: logging.exception("Error in onError")
def _decryptCKey(self, cKeyData, onPlainText, onError): """ Decrypt cKeyData. :param Data cKeyData: The C-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 the encrypted content. cKeyContent = cKeyData.getContent() cKeyEncryptedContent = EncryptedContent() try: cKeyEncryptedContent.wireDecode(cKeyContent) except Exception as ex: try: onError(EncryptError.ErrorCode.InvalidEncryptedFormat, repr(ex)) except: logging.exception("Error in onError") return eKeyName = cKeyEncryptedContent.getKeyLocator().getKeyName() dKeyName = eKeyName.getPrefix(-3) dKeyName.append(Encryptor.NAME_COMPONENT_D_KEY).append( eKeyName.getSubName(-2)) # Check if the decryption key is already in the store. if dKeyName in self._dKeyMap: dKey = self._dKeyMap[dKeyName] Consumer._decrypt(cKeyEncryptedContent, dKey, onPlainText, onError) else: # Get the D-Key Data. interestName = Name(dKeyName) interestName.append(Encryptor.NAME_COMPONENT_FOR).append( self._consumerName) interest = Interest(interestName) # Prepare the callback functions. def onData(dKeyInterest, dKeyData): # The Interest has no selectors, so assume the library correctly # matched with the Data name before calling onData. try: def onVerified(validDKeyData): def localOnPlainText(dKeyBits): # dKeyName is already a local copy. self._dKeyMap[dKeyName] = dKeyBits Consumer._decrypt(cKeyEncryptedContent, dKeyBits, onPlainText, onError) self._decryptDKey(validDKeyData, localOnPlainText, onError) self._keyChain.verifyData( dKeyData, onVerified, lambda d: Consumer._callOnError( onError, EncryptError.ErrorCode.Validation, "verifyData failed")) except Exception as ex: try: onError(EncryptError.ErrorCode.General, "verifyData error: " + repr(ex)) except: logging.exception("Error in onError") def onTimeout(dKeyInterest): # We should re-try at least once. try: self._face.expressInterest( interest, onData, lambda contentInterest: Consumer._callOnError( onError, EncryptError.ErrorCode.Timeout, interest.getName().toUri())) except Exception as ex: try: onError(EncryptError.ErrorCode.General, "expressInterest error: " + repr(ex)) except: logging.exception("Error in onError") # Express the Interest. try: self._face.expressInterest(interest, onData, onTimeout) except Exception as ex: try: onError(EncryptError.ErrorCode.General, "expressInterest error: " + repr(ex)) except: logging.exception("Error in onError")
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") return # Decrypt the D-KEY. Consumer._decrypt( encryptedNonce, consumerKeyBlob, lambda nonceKeyBits: Consumer._decrypt( encryptedPayloadBlob, nonceKeyBits, onPlainText, onError), onError)