def test_load_keyfile_corrupt_public(self):
     """Test :py:meth:`.KeyManager.load_keyfile` raises :class:`.InvalidFormat` with corrupted public key"""
 
     with TemporaryDirectory() as d:
         keyfile = join(d, 'corrupt_key')
         with open(keyfile, 'w') as fp:
             fp.write('ssh-rsa AAAAThisIsNotARealKey')
         with self.assertRaises(InvalidFormat):
             KeyManager.load_keyfile(keyfile)
 def _sign_verify(priv, pub):
     """Helper method to avoid duplicating sign+verify code for every algorithm"""
     km = KeyManager(priv)  # KeyManager with private key (public key interpolated from private key)
     km_pub = KeyManager(pub)  # KeyManager with only public key
     sig = km.sign('hello world')  # Sign 'hello world' with the private key
     # Verify the signature, these methods will raise InvalidSignature if it doesn't verify.
     km_pub.verify(signature=sig, message='hello world')  # Verify with pubkey-only instance
     km.verify(signature=sig, message='hello world')  # Verify with privkey-only instance
 def test_load_keyfile_corrupt_public_2(self):
     """
     Test :py:meth:`.KeyManager.load_keyfile` raises :class:`.InvalidFormat` with corrupted public key
     (but with valid b64)
     """
 
     with TemporaryDirectory() as d:
         keyfile = join(d, 'corrupt_key')
         with open(keyfile, 'w') as fp:
             fp.write(f'ssh-rsa {self.fake_b64_key}')
         with self.assertRaises(InvalidFormat):
             KeyManager.load_keyfile(keyfile)
 def test_load_keyfile_corrupt_private(self):
     """Test :py:meth:`.KeyManager.load_keyfile` raises :class:`.InvalidFormat` with corrupted PEM private key"""
 
     with TemporaryDirectory() as d:
         keydata = "-----BEGIN PRIVATE KEY-----\n"
         keydata += self.fake_b64_key
         keydata += "\n-----END PRIVATE KEY-----\n"
         
         keyfile = join(d, 'corrupt_key')
         with open(keyfile, 'w') as fp:
             fp.write(keydata)
         with self.assertRaises(InvalidFormat):
             KeyManager.load_keyfile(keyfile)
 def test_rsa_gen(self):
     """Generate an RSA 2048 + 4096-bit key, check the pub/priv lengths, and confirm they're formatted correctly"""
     priv, pub = KeyManager.generate_keypair()
     self.assertAlmostEqual(len(priv), 1704, delta=64)
     self.assertAlmostEqual(len(pub), 380, delta=32)
     self.assertIn('---BEGIN PRIVATE', priv.decode('utf-8'))
     self.assertIn('ssh-rsa', pub.decode('utf-8'))
     
     priv, pub = KeyManager.generate_keypair(key_size=4096)
     self.assertAlmostEqual(len(priv), 3272, delta=64)
     self.assertAlmostEqual(len(pub), 724, delta=32)
     self.assertIn('---BEGIN PRIVATE', priv.decode('utf-8'))
     self.assertIn('ssh-rsa', pub.decode('utf-8'))
 def test_ed25519_gen(self):
     """Generate an Ed25519 keypair, check the pub/priv lengths, and confirm they're formatted correctly"""
     priv, pub = KeyManager.generate_keypair('ed25519')
     self.assertAlmostEqual(len(priv), 119, delta=16)
     self.assertAlmostEqual(len(pub), 80, delta=16)
     self.assertIn('---BEGIN PRIVATE', priv.decode('utf-8'))
     self.assertEqual('ssh-ed25519', pub.decode('utf-8')[0:11])
 def test_ecdsa_gen(self):
     """Generate an ECDSA keypair, check the pub/priv lengths, and confirm they're formatted correctly"""
     priv, pub = KeyManager.generate_keypair('ecdsa')
     self.assertAlmostEqual(len(priv), 306, delta=16)
     self.assertAlmostEqual(len(pub), 204, delta=16)
     self.assertIn('---BEGIN PRIVATE', priv.decode('utf-8'))
     self.assertEqual('ecdsa-', pub.decode('utf-8')[0:6])
 def test_rsa_encrypt_decrypt(self):
     priv, pub = KeyManager.generate_keypair()
     km, km_pub = KeyManager(priv), KeyManager(pub)
     msg = 'hello world'
     enc = km.encrypt(msg)          # Encrypt `msg` using private key KeyManager instance
     enc_pub = km_pub.encrypt(msg)  # Encrypt `msg` using public key KeyManager instance
     # Confirm that the encrypted data is actually different from the original message
     self.assertNotEqual(enc, msg)
     self.assertNotEqual(enc_pub, msg)
     # Confirm decrypting the two encrypted `bytes` vars (and decoding to str) matches the original message
     self.assertEqual(km.decrypt(enc).decode('utf-8'), msg)
     self.assertEqual(km.decrypt(enc_pub).decode('utf-8'), msg)
 def test_output_keypair(self):
     """Test outputting a keypair to files creates files, and file contents match the returned priv/pub"""
     with TemporaryDirectory() as d:
         priv_file, pub_file = join(d, 'id_rsa'), join(d, 'id_rsa.pub')
         priv, pub = KeyManager.output_keypair(priv=priv_file, pub=pub_file)
         self.assertTrue(path.exists(priv_file), msg=f"Test file exists: {priv_file}")
         self.assertTrue(path.exists(pub_file), msg=f"Test file exists: {pub_file}")
         
         with open(priv_file) as fp:
             data = fp.read().strip()
             key = priv.decode().strip()
             self.assertEqual(key, data, msg='Test private key file contents match returned priv key')
         with open(pub_file) as fp:
             data = fp.read().strip()
             key = pub.decode().strip()
             self.assertEqual(key, data, msg='Test public key file contents match returned pub key')
Example #10
0
 def test_ed25519_sign_verify(self):
     """Attempt to sign and verify a message using an Ed25519 keypair using :py:meth:`._sign_verify` test helper"""
     priv, pub = KeyManager.generate_keypair('ed25519')
     self._sign_verify(priv, pub)
Example #11
0
 def test_rsa_sign_verify(self):
     """Attempt to sign and verify a message using an RSA keypair using :py:meth:`._sign_verify` test helper"""
     priv, pub = KeyManager.generate_keypair()
     self._sign_verify(priv, pub)
Example #12
0
 def test_load_keyfile_noexist(self):
     """Test :py:meth:`.KeyManager.load_keyfile` raises :class:`FileNotFoundError` with non-existent path"""
     with TemporaryDirectory() as d:
         with self.assertRaises(FileNotFoundError):
             KeyManager.load_keyfile(join(d, 'non_existent'))
Example #13
0
 def test_load_keyfile_sign_verify_rsa(self):
     """
     Generate a key pair + save to disk, then load the keypair from disk. Confirm that the keys on disk definitely
     match the returned tuple by running signature verification.
     
     Uses KeyManager with both the public/private keys from disk, and the output_keypair returned public/private keys
     """
     with TemporaryDirectory() as d:
         # Generate and output an RSA key to id_rsa and id_rsa.pub
         priv_file, pub_file = join(d, 'id_rsa'), join(d, 'id_rsa.pub')
         priv, pub = KeyManager.output_keypair(priv=priv_file, pub=pub_file)
         # Load the returned private + public key bytes
         km_ret, km_ret_pub = KeyManager(priv), KeyManager(pub)
         
         # Load the private/public keys from the files
         km = KeyManager.load_keyfile(priv_file)
         self.assertTrue(isinstance(km, KeyManager))
         
         km_pub = KeyManager.load_keyfile(pub_file)
         self.assertTrue(isinstance(km_pub, KeyManager))
         
         # Sign 'hello world' with both the returned private key, and the id_rsa file loaded from disk
         sig = km.sign('hello world')
         sig_ret = km_ret.sign('hello world')
         
         # Make sure the keys are the same by verifying the signature (signed by the keys from disk) with
         # KeyManager instances using the public/private keys loaded from disk + returned public/private keys
         km.verify(sig, 'hello world')
         km_pub.verify(sig, 'hello world')
         km_ret.verify(sig, 'hello world')
         km_ret_pub.verify(sig, 'hello world')
         
         # Same as above, but verifying the signature made by the KeyManager using the returned private key
         km.verify(sig_ret, 'hello world')
         km_ret.verify(sig_ret, 'hello world')
         km_pub.verify(sig_ret, 'hello world')
         km_ret_pub.verify(sig_ret, 'hello world')
Example #14
0
 def test_ed25519_load(self):
     """Generate and attempt to load an Ed25519 keypair"""
     priv, pub = KeyManager.generate_keypair('ed25519')
     # If the keys were invalid, KeyManager should raise InvalidFormat and fail the test
     KeyManager(priv)
     KeyManager(pub)
Example #15
0
 def test_load_invalid(self):
     """Initialise KeyManager with an invalid key to confirm it raises InvalidFormat"""
     with self.assertRaises(InvalidFormat):
         KeyManager('-----THIS IS NOT --- A ___ KEY')