def _processValidCertificate(self, data): # unpack the cert from the HMAC signed packet and verify try: newCert = IdentityCertificate() newCert.wireDecode(data.getContent()) self.log.info("Received certificate from controller") self.log.debug(str(newCert)) # NOTE: we download and install the root certificate without verifying it (!) # otherwise our policy manager will reject it. # we may need a static method on KeyChain to allow verifying before adding rootCertName = newCert.getSignature().getKeyLocator().getKeyName() # update trust rules so we trust the controller self._policyManager.setDeviceIdentity(self._configureIdentity) self._policyManager.updateTrustRules() def onRootCertificateDownload(interest, data): try: self._identityStorage.addCertificate(data) except SecurityException: # already exists pass self._keyChain.verifyData(newCert, self._finalizeCertificateDownload, self._certificateValidationFailed) def onRootCertificateTimeout(interest): # TODO: limit number of tries, then revert trust root + network prefix # reset salt, create new Hmac key self.face.expressInterest(rootCertName, onRootCertificateDownload, onRootCertificateTimeout) self.face.expressInterest(rootCertName, onRootCertificateDownload, onRootCertificateTimeout) except Exception as e: self.log.exception("Could not import new certificate", exc_info=True)
def getCertificate(self, certificateName, allowAny = False): """ Get a certificate from the identity storage. :param Name certificateName: The name of the requested certificate. :param bool allowAny: (optional) If False, only a valid certificate will be returned, otherwise validity is disregarded. If omitted, allowAny is False. :return: The requested certificate. If not found, return None. :rtype: Data """ chosenCert = None certificateUri = certificateName.toUri() cursor = self._database.cursor() #if not allowAny: # validityClause = " AND valid_flag=1" #else: validityClause = "" # use LIKE because key locators chop off timestamps # need to escape any percent signs in the certificate uri for sql's # sake, but still append % for LIKE escapedUri = certificateUri.replace('%', '\\%') full_statement = "SELECT certificate_data FROM Certificate WHERE cert_name LIKE ?"+validityClause+" ESCAPE '\\' ORDER BY cert_name DESC" #full_statement = "SELECT certificate_data FROM Certificate WHERE cert_name=?"+validityClause cursor.execute(full_statement, (escapedUri+'%', )) try: (certData, ) = cursor.fetchone() except TypeError: pass else: chosenCert = IdentityCertificate() chosenCert.wireDecode(bytearray(certData)) return chosenCert
def _processValidCertificate(self, data): # unpack the cert from the HMAC signed packet and verify try: newCert = IdentityCertificate() newCert.wireDecode(data.getContent()) self.log.info("Received certificate from controller") # NOTE: we download and install the root certificate without verifying it (!) # otherwise our policy manager will reject it. # we may need a static method on KeyChain to allow verifying before adding rootCertName = newCert.getSignature().getKeyLocator().getKeyName() # update trust rules so we trust the controller self._policyManager.setDeviceIdentity(self._configureIdentity) self._policyManager.updateTrustRules() def onRootCertificateDownload(interest, data): try: # zhehao: the root cert is downloaded and installed without verifying; should the root cert be preconfigured? # Insert root certificate so that we can verify newCert self._policyManager._certificateCache.insertCertificate(data) # Set the root cert as default for root identity try: self._identityManager.addCertificateAsIdentityDefault(IdentityCertificate(data)) except SecurityException as e: print("Error when addCertificateAsIdentityDefault for root: " + data.getName().toUri()) print(str(e)) self._rootCertificate = data try: # use the default configuration where possible # TODO: use environment variable for this, fall back to default fileName = os.path.expanduser('~/.ndn/.iot.root.cert') rootCertFile = open(fileName, "w") rootCertFile.write(Blob(b64encode(self._rootCertificate.wireEncode().toBytes()), False).toRawStr()) rootCertFile.close() except IOError as e: self.log.error("Cannot write to root certificate file: " + rootCertFile) print "Cannot write to root certificate file: " + rootCertFile except SecurityException as e: print(str(e)) # already exists, or got certificate in wrong format pass self._keyChain.verifyData(newCert, self._finalizeCertificateDownload, self._certificateValidationFailed) def onRootCertificateTimeout(interest): # TODO: limit number of tries, then revert trust root + network prefix # reset salt, create new Hmac key self.face.expressInterest(rootCertName, onRootCertificateDownload, onRootCertificateTimeout) self.face.expressInterest(rootCertName, onRootCertificateDownload, onRootCertificateTimeout) except Exception as e: self.log.exception("Could not import new certificate", exc_info=True)
def test_refresh_10s(self): with open('policy_config/testData', 'r') as dataFile: encodedData = dataFile.read() data = Data() dataBlob = Blob(b64decode(encodedData)) data.wireDecode(dataBlob) # needed, since the KeyChain will express interests in unknown # certificates vr = doVerify(self.policyManager, data) self.assertTrue(vr.hasFurtherSteps, "ConfigPolicyManager did not create ValidationRequest for unknown certificate") self.assertEqual(vr.successCount, 0, "ConfigPolicyManager called success callback with pending ValidationRequest") self.assertEqual(vr.failureCount, 0, "ConfigPolicyManager called failure callback with pending ValidationRequest") # now save the cert data to our anchor directory, and wait # we have to sign it with the current identity or the # policy manager will create an interest for the signing certificate with open(self.testCertFile, 'w') as certFile: cert = IdentityCertificate() certData = b64decode(CERT_DUMP) cert.wireDecode(Blob(certData, False)) self.keyChain.signByIdentity(cert, self.identityName) encodedCert = b64encode(cert.wireEncode().toBuffer()) certFile.write(Blob(encodedCert, False).toRawStr()) # still too early for refresh to pick it up vr = doVerify(self.policyManager, data) self.assertTrue(vr.hasFurtherSteps, "ConfigPolicyManager refresh occured sooner than specified") self.assertEqual(vr.successCount, 0, "ConfigPolicyManager called success callback with pending ValidationRequest") self.assertEqual(vr.failureCount, 0, "ConfigPolicyManager called failure callback with pending ValidationRequest") time.sleep(6) # now we should find it vr = doVerify(self.policyManager, data) self.assertFalse(vr.hasFurtherSteps, "ConfigPolicyManager did not refresh certificate store") self.assertEqual(vr.successCount, 1, "Verification success called {} times instead of 1".format( vr.successCount)) self.assertEqual(vr.failureCount, 0, "ConfigPolicyManager did not verify valid signed data")
def test_refresh_10s(self): with open('policy_config/testData', 'r') as dataFile: encodedData = dataFile.read() data = Data() dataBlob = Blob(b64decode(encodedData)) data.wireDecode(dataBlob) # needed, since the KeyChain will express interests in unknown # certificates vr = doVerify(self.policyManager, data) self.assertTrue(vr.hasFurtherSteps, "ConfigPolicyManager did not create ValidationRequest for unknown certificate") self.assertEqual(vr.successCount, 0, "ConfigPolicyManager called success callback with pending ValidationRequest") self.assertEqual(vr.failureCount, 0, "ConfigPolicyManager called failure callback with pending ValidationRequest") # now save the cert data to our anchor directory, and wait # we have to sign it with the current identity or the # policy manager will create an interest for the signing certificate with open(self.testCertFile, 'w') as certFile: cert = IdentityCertificate() certData = b64decode(CERT_DUMP) cert.wireDecode(Blob(certData, False)) self.keyChain.signByIdentity(cert, self.identityName) encodedCert = b64encode(cert.wireEncode().toBytes()) certFile.write(Blob(encodedCert, False).toRawStr()) # still too early for refresh to pick it up vr = doVerify(self.policyManager, data) self.assertTrue(vr.hasFurtherSteps, "ConfigPolicyManager refresh occured sooner than specified") self.assertEqual(vr.successCount, 0, "ConfigPolicyManager called success callback with pending ValidationRequest") self.assertEqual(vr.failureCount, 0, "ConfigPolicyManager called failure callback with pending ValidationRequest") time.sleep(6) # now we should find it vr = doVerify(self.policyManager, data) self.assertFalse(vr.hasFurtherSteps, "ConfigPolicyManager did not refresh certificate store") self.assertEqual(vr.successCount, 1, "Verification success called {} times instead of 1".format( vr.successCount)) self.assertEqual(vr.failureCount, 0, "ConfigPolicyManager did not verify valid signed data")
def test_create_d_key_data(self): # Create the group manager. manager = GroupManager( Name("Alice"), Name("data_type"), Sqlite3GroupManagerDb(self.dKeyDatabaseFilePath), 2048, 1, self.keyChain) newCertificateBlob = self.certificate.wireEncode() newCertificate = IdentityCertificate() newCertificate.wireDecode(newCertificateBlob) # Encrypt the D-KEY. data = manager._createDKeyData( "20150825T000000", "20150827T000000", Name("/ndn/memberA/KEY"), self.decryptKeyBlob, newCertificate.getPublicKeyInfo().getKeyDer()) # Verify the encrypted D-KEY. dataContent = data.getContent() # Get the nonce key. # dataContent is a sequence of the two EncryptedContent. encryptedNonce = EncryptedContent() encryptedNonce.wireDecode(dataContent) self.assertEqual(0, encryptedNonce.getInitialVector().size()) self.assertEqual(EncryptAlgorithmType.RsaOaep, encryptedNonce.getAlgorithmType()) blobNonce = encryptedNonce.getPayload() decryptParams = EncryptParams(EncryptAlgorithmType.RsaOaep) nonce = RsaAlgorithm.decrypt(self.decryptKeyBlob, blobNonce, decryptParams) # Get the D-KEY. # Use the size of encryptedNonce to find the start of encryptedPayload. payloadContent = dataContent.buf()[encryptedNonce.wireEncode().size():] encryptedPayload = EncryptedContent() encryptedPayload.wireDecode(payloadContent) self.assertEqual(16, encryptedPayload.getInitialVector().size()) self.assertEqual(EncryptAlgorithmType.AesCbc, encryptedPayload.getAlgorithmType()) decryptParams.setAlgorithmType(EncryptAlgorithmType.AesCbc) decryptParams.setInitialVector(encryptedPayload.getInitialVector()) blobPayload = encryptedPayload.getPayload() largePayload = AesAlgorithm.decrypt(nonce, blobPayload, decryptParams) self.assertTrue(largePayload.equals(self.decryptKeyBlob))
def test_create_d_key_data(self): # Create the group manager. manager = GroupManager( Name("Alice"), Name("data_type"), Sqlite3GroupManagerDb(self.dKeyDatabaseFilePath), 2048, 1, self.keyChain) newCertificateBlob = self.certificate.wireEncode() newCertificate = IdentityCertificate() newCertificate.wireDecode(newCertificateBlob) # Encrypt the D-KEY. data = manager._createDKeyData( "20150825T000000", "20150827T000000", Name("/ndn/memberA/KEY"), self.decryptKeyBlob, newCertificate.getPublicKeyInfo().getKeyDer()) # Verify the encrypted D-KEY. dataContent = data.getContent() # Get the nonce key. # dataContent is a sequence of the two EncryptedContent. encryptedNonce = EncryptedContent() encryptedNonce.wireDecode(dataContent) self.assertEqual(0, encryptedNonce.getInitialVector().size()) self.assertEqual(EncryptAlgorithmType.RsaOaep, encryptedNonce.getAlgorithmType()) blobNonce = encryptedNonce.getPayload() decryptParams = EncryptParams(EncryptAlgorithmType.RsaOaep) nonce = RsaAlgorithm.decrypt(self.decryptKeyBlob, blobNonce, decryptParams) # Get the D-KEY. # Use the size of encryptedNonce to find the start of encryptedPayload. payloadContent = dataContent.buf()[encryptedNonce.wireEncode().size():] encryptedPayload = EncryptedContent() encryptedPayload.wireDecode(payloadContent) self.assertEqual(16, encryptedPayload.getInitialVector().size()) self.assertEqual(EncryptAlgorithmType.AesCbc, encryptedPayload.getAlgorithmType()) decryptParams.setAlgorithmType(EncryptAlgorithmType.AesCbc) decryptParams.setInitialVector(encryptedPayload.getInitialVector()) blobPayload = encryptedPayload.getPayload() largePayload = AesAlgorithm.decrypt(nonce, blobPayload, decryptParams) self.assertTrue(largePayload.equals(self.decryptKeyBlob))
def getCertificate(self, certificateName, allowAny=False): """ Get a certificate from the identity storage. :param Name certificateName: The name of the requested certificate. :param bool allowAny: (optional) If False, only a valid certificate will be returned, otherwise validity is disregarded. If omitted, allowAny is False. :return: The requested certificate. If not found, return None. :rtype: IdentityCertificate """ certificateNameUri = certificateName.toUri() if not (certificateNameUri in self._certificateStore): # Not found. Silently return None. return None certificate = IdentityCertificate() certificate.wireDecode(self._certificateStore[certificateNameUri]) return certificate
def getCertificate(self, certificateName, allowAny = False): """ Get a certificate from the identity storage. :param Name certificateName: The name of the requested certificate. :param bool allowAny: (optional) If False, only a valid certificate will be returned, otherwise validity is disregarded. If omitted, allowAny is False. :return: The requested certificate. If not found, return None. :rtype: IdentityCertificate """ certificateNameUri = certificateName.toUri() if not (certificateNameUri in self._certificateStore): # Not found. Silently return None. return None certificate = IdentityCertificate() certificate.wireDecode(self._certificateStore[certificateNameUri]) return certificate
def _processValidCertificate(self, data): # unpack the cert from the HMAC signed packet and verify try: newCert = IdentityCertificate() newCert.wireDecode(data.getContent()) self.log.info("Received certificate from controller") self.log.debug(str(newCert)) # NOTE: we download and install the root certificate without verifying it (!) # otherwise our policy manager will reject it. # we may need a static method on KeyChain to allow verifying before adding rootCertName = newCert.getSignature().getKeyLocator().getKeyName() # update trust rules so we trust the controller self._policyManager.setDeviceIdentity(self._configureIdentity) self._policyManager.updateTrustRules() def onRootCertificateDownload(interest, data): try: self._identityStorage.addCertificate(data) except SecurityException: # already exists pass self._keyChain.verifyData(newCert, self._finalizeCertificateDownload, self._certificateValidationFailed) def onRootCertificateTimeout(interest): # TODO: limit number of tries, then revert trust root + network prefix # reset salt, create new Hmac key self.face.expressInterest(rootCertName, onRootCertificateDownload, onRootCertificateTimeout) self.face.expressInterest(rootCertName, onRootCertificateDownload, onRootCertificateTimeout) except Exception as e: self.log.exception("Could not import new certificate", exc_info=True)
def getCertificate(self, certificateName): """ Get a certificate from the identity storage. :param Name certificateName: The name of the requested certificate. :return: The requested certificate. :rtype: IdentityCertificate :raises SecurityException: if the certificate doesn't exist. """ certificateNameUri = certificateName.toUri() if not (certificateNameUri in self._certificateStore): raise SecurityException( "MemoryIdentityStorage::getCertificate: The certificate does not exist") certificate = IdentityCertificate() try: certificate.wireDecode(self._certificateStore[certificateNameUri]) except ValueError: raise SecurityException( "MemoryIdentityStorage::getCertificate: The certificate cannot be decoded") return certificate
def getCertificate(self, certificateName): """ Get a certificate from the identity storage. :param Name certificateName: The name of the requested certificate. :return: The requested certificate. :rtype: IdentityCertificate :raises SecurityException: if the certificate doesn't exist. """ certificateNameUri = certificateName.toUri() if not (certificateNameUri in self._certificateStore): raise SecurityException( "MemoryIdentityStorage.getCertificate: The certificate does not exist" ) certificate = IdentityCertificate() try: certificate.wireDecode(self._certificateStore[certificateNameUri]) except ValueError: raise SecurityException( "MemoryIdentityStorage.getCertificate: The certificate cannot be decoded" ) return certificate
def _processValidCertificate(self, data): # unpack the cert from the HMAC signed packet and verify try: newCert = IdentityCertificate() newCert.wireDecode(data.getContent()) self.log.info("Received certificate from controller") # NOTE: we download and install the root certificate without verifying it (!) # otherwise our policy manager will reject it. # we may need a static method on KeyChain to allow verifying before adding rootCertName = newCert.getSignature().getKeyLocator().getKeyName() # update trust rules so we trust the controller self._policyManager.setDeviceIdentity(self._configureIdentity) self._policyManager.updateTrustRules() def onRootCertificateDownload(interest, data): try: # zhehao: the root cert is downloaded and installed without verifying; should the root cert be preconfigured? # Insert root certificate so that we can verify newCert self._policyManager._certificateCache.insertCertificate( data) # Set the root cert as default for root identity try: self._identityManager.addCertificateAsIdentityDefault( IdentityCertificate(data)) except SecurityException as e: print( "Error when addCertificateAsIdentityDefault for root: " + data.getName().toUri()) print(str(e)) self._rootCertificate = data try: # use the default configuration where possible # TODO: use environment variable for this, fall back to default fileName = os.path.expanduser('~/.ndn/.iot.root.cert') rootCertFile = open(fileName, "w") rootCertFile.write( Blob( b64encode(self._rootCertificate.wireEncode(). toBytes()), False).toRawStr()) rootCertFile.close() except IOError as e: self.log.error( "Cannot write to root certificate file: " + rootCertFile) print "Cannot write to root certificate file: " + rootCertFile except SecurityException as e: print(str(e)) # already exists, or got certificate in wrong format pass self._keyChain.verifyData(newCert, self._finalizeCertificateDownload, self._certificateValidationFailed) def onRootCertificateTimeout(interest): # TODO: limit number of tries, then revert trust root + network prefix # reset salt, create new Hmac key self.face.expressInterest(rootCertName, onRootCertificateDownload, onRootCertificateTimeout) self.face.expressInterest(rootCertName, onRootCertificateDownload, onRootCertificateTimeout) except Exception as e: self.log.exception("Could not import new certificate", exc_info=True)