def setUp(self): # Reuse the policy_config subdirectory for the temporary SQLite files. self.dKeyDatabaseFilePath = "policy_config/manager-d-key-test.db" try: os.remove(self.dKeyDatabaseFilePath) except OSError: # no such file pass self.eKeyDatabaseFilePath = "policy_config/manager-e-key-test.db" try: os.remove(self.eKeyDatabaseFilePath) except OSError: # no such file pass self.intervalDatabaseFilePath = "policy_config/manager-interval-test.db" try: os.remove(self.intervalDatabaseFilePath) except OSError: # no such file pass self.groupKeyDatabaseFilePath = "policy_config/manager-group-key-test.db" try: os.remove(self.groupKeyDatabaseFilePath) except OSError: # no such file pass params = RsaKeyParams() memberDecryptKey = RsaAlgorithm.generateKey(params) self.decryptKeyBlob = memberDecryptKey.getKeyBits() memberEncryptKey = RsaAlgorithm.deriveEncryptKey(self.decryptKeyBlob) self.encryptKeyBlob = memberEncryptKey.getKeyBits() # Generate the certificate. self.certificate = IdentityCertificate() self.certificate.setName(Name("/ndn/memberA/KEY/ksk-123/ID-CERT/123")) contentPublicKey = PublicKey(self.encryptKeyBlob) self.certificate.setPublicKeyInfo(contentPublicKey) self.certificate.setNotBefore(0) self.certificate.setNotAfter(0) self.certificate.encode() signatureInfoBlob = Blob(SIG_INFO, False) signatureValueBlob = Blob(SIG_VALUE, False) signature = TlvWireFormat.get().decodeSignatureInfoAndValue( signatureInfoBlob.buf(), signatureValueBlob.buf()) self.certificate.setSignature(signature) self.certificate.wireEncode() # Set up the keyChain. identityStorage = MemoryIdentityStorage() privateKeyStorage = MemoryPrivateKeyStorage() self.keyChain = KeyChain( IdentityManager(identityStorage, privateKeyStorage), NoVerifyPolicyManager()) identityName = Name("TestGroupManager") self.keyChain.createIdentityAndCertificate(identityName) self.keyChain.getIdentityManager().setDefaultIdentity(identityName)
def test_import_export(self): privateKeyPkcs1Base64 = ( "MIIEpAIBAAKCAQEAw0WM1/WhAxyLtEqsiAJgWDZWuzkYpeYVdeeZcqRZzzfRgBQT\n" + "sNozS5t4HnwTZhwwXbH7k3QN0kRTV826Xobws3iigohnM9yTK+KKiayPhIAm/+5H\n" + "GT6SgFJhYhqo1/upWdueojil6RP4/AgavHhopxlAVbk6G9VdVnlQcQ5Zv0OcGi73\n" + "c+EnYD/YgURYGSngUi/Ynsh779p2U69/te9gZwIL5PuE9BiO6I39cL9z7EK1SfZh\n" + "OWvDe/qH7YhD/BHwcWit8FjRww1glwRVTJsA9rH58ynaAix0tcR/nBMRLUX+e3rU\n" + "RHg6UbSjJbdb9qmKM1fTGHKUzL/5pMG6uBU0ywIDAQABAoIBADQkckOIl4IZMUTn\n" + "W8LFv6xOdkJwMKC8G6bsPRFbyY+HvC2TLt7epSvfS+f4AcYWaOPcDu2E49vt2sNr\n" + "cASly8hgwiRRAB3dHH9vcsboiTo8bi2RFvMqvjv9w3tK2yMxVDtmZamzrrnaV3YV\n" + "Q+5nyKo2F/PMDjQ4eUAKDOzjhBuKHsZBTFnA1MFNI+UKj5X4Yp64DFmKlxTX/U2b\n" + "wzVywo5hzx2Uhw51jmoLls4YUvMJXD0wW5ZtYRuPogXvXb/of9ef/20/wU11WFKg\n" + "Xb4gfR8zUXaXS1sXcnVm3+24vIs9dApUwykuoyjOqxWqcHRec2QT2FxVGkFEraze\n" + "CPa4rMECgYEA5Y8CywomIcTgerFGFCeMHJr8nQGqY2V/owFb3k9maczPnC9p4a9R\n" + "c5szLxA9FMYFxurQZMBWSEG2JS1HR2mnjigx8UKjYML/A+rvvjZOMe4M6Sy2ggh4\n" + "SkLZKpWTzjTe07ByM/j5v/SjNZhWAG7sw4/LmPGRQkwJv+KZhGojuOkCgYEA2cOF\n" + "T6cJRv6kvzTz9S0COZOVm+euJh/BXp7oAsAmbNfOpckPMzqHXy8/wpdKl6AAcB57\n" + "OuztlNfV1D7qvbz7JuRlYwQ0cEfBgbZPcz1p18HHDXhwn57ZPb8G33Yh9Omg0HNA\n" + "Imb4LsVuSqxA6NwSj7cpRekgTedrhLFPJ+Ydb5MCgYEAsM3Q7OjILcIg0t6uht9e\n" + "vrlwTsz1mtCV2co2I6crzdj9HeI2vqf1KAElDt6G7PUHhglcr/yjd8uEqmWRPKNX\n" + "ddnnfVZB10jYeP/93pac6z/Zmc3iU4yKeUe7U10ZFf0KkiiYDQd59CpLef/2XScS\n" + "HB0oRofnxRQjfjLc4muNT+ECgYEAlcDk06MOOTly+F8lCc1bA1dgAmgwFd2usDBd\n" + "Y07a3e0HGnGLN3Kfl7C5i0tZq64HvxLnMd2vgLVxQlXGPpdQrC1TH+XLXg+qnlZO\n" + "ivSH7i0/gx75bHvj75eH1XK65V8pDVDEoSPottllAIs21CxLw3N1ObOZWJm2EfmR\n" + "cuHICmsCgYAtFJ1idqMoHxES3mlRpf2JxyQudP3SCm2WpGmqVzhRYInqeatY5sUd\n" + "lPLHm/p77RT7EyxQHTlwn8FJPuM/4ZH1rQd/vB+Y8qAtYJCexDMsbvLW+Js+VOvk\n" + "jweEC0nrcL31j9mF0vz5E6tfRu4hhJ6L4yfWs0gSejskeVB/w8QY4g==\n") for tpm in self.backEndList: if tpm is self.backEndOsx: # TODO: Implement TpmBackEndOsx import/export. continue keyName = Name("/Test/KeyName/KEY/1") tpm.deleteKey(keyName) self.assertEquals(False, tpm.hasKey(keyName)) privateKey = TpmPrivateKey() privateKeyPkcs1Encoding = Blob(base64.b64decode(privateKeyPkcs1Base64)) privateKey.loadPkcs1(privateKeyPkcs1Encoding.buf()) password = Blob("password").toBytes() encryptedPkcs8 = privateKey.toEncryptedPkcs8(password) tpm.importKey(keyName, encryptedPkcs8.buf(), password) self.assertEquals(True, tpm.hasKey(keyName)) try: # Can't import the same keyName again. tpm.importKey(keyName, encryptedPkcs8.buf(), password) self.fail("Did not throw the expected exception") except TpmBackEnd.Error: pass else: self.fail("Did not throw the expected exception") exportedKey = tpm.exportKey(keyName, password) self.assertEquals(True, tpm.hasKey(keyName)) privateKey2 = TpmPrivateKey() privateKey2.loadEncryptedPkcs8(exportedKey.buf(), password) privateKey2Pkcs1Encoding = privateKey2.toPkcs1() self.assertTrue(privateKeyPkcs1Encoding.equals(privateKey2Pkcs1Encoding)) tpm.deleteKey(keyName) self.assertEquals(False, tpm.hasKey(keyName)) try: tpm.exportKey(keyName, password) self.fail("Did not throw the expected exception") except TpmBackEnd.Error: pass else: self.fail("Did not throw the expected exception")
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 test_import_export(self): privateKeyPkcs1Base64 = ( "MIIEpAIBAAKCAQEAw0WM1/WhAxyLtEqsiAJgWDZWuzkYpeYVdeeZcqRZzzfRgBQT\n" + "sNozS5t4HnwTZhwwXbH7k3QN0kRTV826Xobws3iigohnM9yTK+KKiayPhIAm/+5H\n" + "GT6SgFJhYhqo1/upWdueojil6RP4/AgavHhopxlAVbk6G9VdVnlQcQ5Zv0OcGi73\n" + "c+EnYD/YgURYGSngUi/Ynsh779p2U69/te9gZwIL5PuE9BiO6I39cL9z7EK1SfZh\n" + "OWvDe/qH7YhD/BHwcWit8FjRww1glwRVTJsA9rH58ynaAix0tcR/nBMRLUX+e3rU\n" + "RHg6UbSjJbdb9qmKM1fTGHKUzL/5pMG6uBU0ywIDAQABAoIBADQkckOIl4IZMUTn\n" + "W8LFv6xOdkJwMKC8G6bsPRFbyY+HvC2TLt7epSvfS+f4AcYWaOPcDu2E49vt2sNr\n" + "cASly8hgwiRRAB3dHH9vcsboiTo8bi2RFvMqvjv9w3tK2yMxVDtmZamzrrnaV3YV\n" + "Q+5nyKo2F/PMDjQ4eUAKDOzjhBuKHsZBTFnA1MFNI+UKj5X4Yp64DFmKlxTX/U2b\n" + "wzVywo5hzx2Uhw51jmoLls4YUvMJXD0wW5ZtYRuPogXvXb/of9ef/20/wU11WFKg\n" + "Xb4gfR8zUXaXS1sXcnVm3+24vIs9dApUwykuoyjOqxWqcHRec2QT2FxVGkFEraze\n" + "CPa4rMECgYEA5Y8CywomIcTgerFGFCeMHJr8nQGqY2V/owFb3k9maczPnC9p4a9R\n" + "c5szLxA9FMYFxurQZMBWSEG2JS1HR2mnjigx8UKjYML/A+rvvjZOMe4M6Sy2ggh4\n" + "SkLZKpWTzjTe07ByM/j5v/SjNZhWAG7sw4/LmPGRQkwJv+KZhGojuOkCgYEA2cOF\n" + "T6cJRv6kvzTz9S0COZOVm+euJh/BXp7oAsAmbNfOpckPMzqHXy8/wpdKl6AAcB57\n" + "OuztlNfV1D7qvbz7JuRlYwQ0cEfBgbZPcz1p18HHDXhwn57ZPb8G33Yh9Omg0HNA\n" + "Imb4LsVuSqxA6NwSj7cpRekgTedrhLFPJ+Ydb5MCgYEAsM3Q7OjILcIg0t6uht9e\n" + "vrlwTsz1mtCV2co2I6crzdj9HeI2vqf1KAElDt6G7PUHhglcr/yjd8uEqmWRPKNX\n" + "ddnnfVZB10jYeP/93pac6z/Zmc3iU4yKeUe7U10ZFf0KkiiYDQd59CpLef/2XScS\n" + "HB0oRofnxRQjfjLc4muNT+ECgYEAlcDk06MOOTly+F8lCc1bA1dgAmgwFd2usDBd\n" + "Y07a3e0HGnGLN3Kfl7C5i0tZq64HvxLnMd2vgLVxQlXGPpdQrC1TH+XLXg+qnlZO\n" + "ivSH7i0/gx75bHvj75eH1XK65V8pDVDEoSPottllAIs21CxLw3N1ObOZWJm2EfmR\n" + "cuHICmsCgYAtFJ1idqMoHxES3mlRpf2JxyQudP3SCm2WpGmqVzhRYInqeatY5sUd\n" + "lPLHm/p77RT7EyxQHTlwn8FJPuM/4ZH1rQd/vB+Y8qAtYJCexDMsbvLW+Js+VOvk\n" + "jweEC0nrcL31j9mF0vz5E6tfRu4hhJ6L4yfWs0gSejskeVB/w8QY4g==\n") for tpm in self.backEndList: if tpm is self.backEndOsx: # TODO: Implement TpmBackEndOsx import/export. continue keyName = Name("/Test/KeyName/KEY/1") tpm.deleteKey(keyName) self.assertEqual(False, tpm.hasKey(keyName)) privateKey = TpmPrivateKey() privateKeyPkcs1Encoding = Blob(base64.b64decode(privateKeyPkcs1Base64)) privateKey.loadPkcs1(privateKeyPkcs1Encoding.buf()) password = Blob("password").toBytes() encryptedPkcs8 = privateKey.toEncryptedPkcs8(password) tpm.importKey(keyName, encryptedPkcs8.buf(), password) self.assertEqual(True, tpm.hasKey(keyName)) try: # Can't import the same keyName again. tpm.importKey(keyName, encryptedPkcs8.buf(), password) self.fail("Did not throw the expected exception") except TpmBackEnd.Error: pass else: self.fail("Did not throw the expected exception") exportedKey = tpm.exportKey(keyName, password) self.assertEqual(True, tpm.hasKey(keyName)) privateKey2 = TpmPrivateKey() privateKey2.loadEncryptedPkcs8(exportedKey.buf(), password) privateKey2Pkcs1Encoding = privateKey2.toPkcs1() self.assertTrue(privateKeyPkcs1Encoding.equals(privateKey2Pkcs1Encoding)) tpm.deleteKey(keyName) self.assertEqual(False, tpm.hasKey(keyName)) try: tpm.exportKey(keyName, password) self.fail("Did not throw the expected exception") except TpmBackEnd.Error: pass else: self.fail("Did not throw the expected exception")
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 name conventions (a network-ordered number where the first byte is the marker 0x00). :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 toVersion(self): """ Interpret this name component as a version number according to NDN name conventions (a network-ordered number where the first byte is the marker 0xFD). Note that this returns the exact number from the component without converting it to a time representation. :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 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 network-ordered encoding of the number. Note: if the number is zero, the result is empty. :param int number: The number to be encoded. :return: The component value. :rtype: Name.Component """ value = [] # First encode in little endian. while number != 0: value.append(number & 0xff) number >>= 8 # Make it big endian. value.reverse() return Name.Component(Blob(value, False)) @staticmethod def fromNumberWithMarker(number, marker): """ Create a component whose value is the marker appended with the network-ordered encoding of the number. Note: if the number is zero, no bytes are used for the number - the result will have only the marker. :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 """ value = [] # First encode in little endian. while number != 0: value.append(number & 0xff) number >>= 8 # Make it big endian. value.reverse() # Prepend the leading marker. value.insert(0, marker) return Name.Component(Blob(value, 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