Back to index

obnam  1.1
encryption_tests.py
Go to the documentation of this file.
00001 # Copyright 2011  Lars Wirzenius
00002 # 
00003 # This program is free software: you can redistribute it and/or modify
00004 # it under the terms of the GNU General Public License as published by
00005 # the Free Software Foundation, either version 3 of the License, or
00006 # (at your option) any later version.
00007 # 
00008 # This program is distributed in the hope that it will be useful,
00009 # but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00011 # GNU General Public License for more details.
00012 # 
00013 # You should have received a copy of the GNU General Public License
00014 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
00015 
00016 
00017 import os
00018 import shutil
00019 import subprocess
00020 import tempfile
00021 import unittest
00022 
00023 import obnamlib
00024 
00025 
00026 def cat(filename):
00027     f = open(filename, 'rb')
00028     data = f.read()
00029     f.close()
00030     return data
00031 
00032 
00033 class SymmetricEncryptionTests(unittest.TestCase):
00034 
00035     # We don't test the quality of keys or encryption here. Doing that is
00036     # hard to do well, and we'll just assume that reading /dev/random
00037     # for keys, and using gpg for encryption, is going to work well.
00038     # In these tests, we care about making sure we use the tools right,
00039     # not that the tools themselves work right.
00040 
00041     def test_generates_key_of_correct_length(self):
00042         numbits = 16
00043         key = obnamlib.generate_symmetric_key(numbits, filename='/dev/zero')
00044         self.assertEqual(len(key) * 8 / 2, numbits) # /2 for hex encoding
00045 
00046     def test_generates_key_with_size_rounded_up(self):
00047         numbits = 15
00048         key = obnamlib.generate_symmetric_key(numbits, filename='/dev/zero')
00049         self.assertEqual(len(key)/2, 2) # /2 for hex encoding
00050 
00051     def test_encrypts_into_different_string_than_cleartext(self):
00052         cleartext = 'hello world'
00053         key = 'sekr1t'
00054         encrypted = obnamlib.encrypt_symmetric(cleartext, key)
00055         self.assertNotEqual(cleartext, encrypted)
00056 
00057     def test_encrypt_decrypt_round_trip(self):
00058         cleartext = 'hello, world'
00059         key = 'sekr1t'
00060         encrypted = obnamlib.encrypt_symmetric(cleartext, key)
00061         decrypted = obnamlib.decrypt_symmetric(encrypted, key)
00062         self.assertEqual(decrypted, cleartext)
00063 
00064 
00065 class SymmetricKeyCacheTests(unittest.TestCase):
00066 
00067     def setUp(self):
00068         self.cache = obnamlib.SymmetricKeyCache()
00069         self.repo = 'repo'
00070         self.repo2 = 'repo2'
00071         self.toplevel = 'toplevel'
00072         self.key = 'key'
00073         self.key2 = 'key2'
00074         
00075     def test_does_not_have_key_initially(self):
00076         self.assertEqual(self.cache.get(self.repo, self.toplevel), None)
00077         
00078     def test_remembers_key(self):
00079         self.cache.put(self.repo, self.toplevel, self.key)
00080         self.assertEqual(self.cache.get(self.repo, self.toplevel), self.key)
00081 
00082     def test_does_not_remember_key_for_different_repo(self):
00083         self.cache.put(self.repo, self.toplevel, self.key)
00084         self.assertEqual(self.cache.get(self.repo2, self.toplevel), None)
00085         
00086     def test_remembers_keys_for_both_repos(self):
00087         self.cache.put(self.repo, self.toplevel, self.key)
00088         self.cache.put(self.repo2, self.toplevel, self.key2)
00089         self.assertEqual(self.cache.get(self.repo, self.toplevel), self.key)
00090         self.assertEqual(self.cache.get(self.repo2, self.toplevel), self.key2)
00091 
00092     def test_clears_cache(self):
00093         self.cache.put(self.repo, self.toplevel, self.key)
00094         self.cache.clear()
00095         self.assertEqual(self.cache.get(self.repo, self.toplevel), None)
00096 
00097 
00098 class GetPublicKeyTests(unittest.TestCase):
00099 
00100     def setUp(self):
00101         self.dirname = tempfile.mkdtemp()
00102         self.gpghome = os.path.join(self.dirname, 'gpghome')
00103         shutil.copytree('test-gpghome', self.gpghome)
00104         self.keyid = '1B321347'
00105         
00106     def tearDown(self):
00107         shutil.rmtree(self.dirname)
00108         
00109     def test_exports_key(self):
00110         key = obnamlib.get_public_key(self.keyid, gpghome=self.gpghome)
00111         self.assert_('-----BEGIN PGP PUBLIC KEY BLOCK-----' in key)
00112 
00113 
00114 class KeyringTests(unittest.TestCase):
00115 
00116     def setUp(self):
00117         self.keyring = obnamlib.Keyring()
00118         self.keyid = '3B1802F81B321347'
00119         self.key = '''
00120 -----BEGIN PGP PUBLIC KEY BLOCK-----
00121 Version: GnuPG v1.4.10 (GNU/Linux)
00122 
00123 mI0ETY8gwwEEAMrSXBIJseIv9miuwnYlCd7CQCzNb8nHYkpo4o1nEQD3k/h7xj9m
00124 /0Gd5kLfF+WLwAxSJYb41JjaKs0FeUexSGNePdNFxn2CCZ4moHH19tTlWGfqCNz7
00125 vcYQpSbPix+zhR7uNqilxtsIrx1iyYwh7L2VKf/KMJ7yXbT+jbAj7fqBABEBAAG0
00126 CFRlc3QgS2V5iLgEEwECACIFAk2PIMMCGwMGCwkIBwMCBhUIAgkKCwQWAgMBAh4B
00127 AheAAAoJEDsYAvgbMhNHlEED/1UkiLJ8R3phMRnjLtn+5JobYvOi7WEubnRv1rnN
00128 MC4MyhFiLux7Z8p3xwt1Pf2GqL7q1dD91NOx+6KS3d1PFmiM/i1fYalZPbzm1gNr
00129 8sFK2Gxsnd7mmYf2wKIo335Bk21SCmGcNKvmKW2M6ckzPT0q/RZ2hhY9JhHUiLG4
00130 Lu3muI0ETY8gwwEEAMQoiBCQYky52pDamnH5c7FngCM72AkNq/z0+DHqY202gksd
00131 Vy63TF7UGIsiCLvY787vPm62sOqYO0uI6PV5xVDGyJh4oI/g2zgNkhXRZrIB1Q+T
00132 THp7qSmwQUZv8T+HfgxLiaXDq6oV/HWLElcMQ9ClZ3Sxzlu3ZQHrtmY5XridABEB
00133 AAGInwQYAQIACQUCTY8gwwIbDAAKCRA7GAL4GzITR4hgBAClEurTj5n0/21pWZH0
00134 Ljmokwa3FM++OZxO7shc1LIVNiAKfLiPigU+XbvSeVWTeajKkvj5LCVxKQiRSiYB
00135 Z85TYTo06kHvDCYQmFOSGrLsZxMyJCfHML5spF9+bej5cepmuNVIdJK5vlgDiVr3
00136 uWUO7gMi+AlnxbfXVCTEgw3xhg==
00137 =j+6W
00138 -----END PGP PUBLIC KEY BLOCK-----
00139 '''
00140 
00141     def test_has_no_keys_initially(self):
00142         self.assertEqual(self.keyring.keyids(), [])
00143         self.assertEqual(str(self.keyring), '')
00144 
00145     def test_gets_no_keys_from_empty_encoded(self):
00146         keyring = obnamlib.Keyring(encoded='')
00147         self.assertEqual(keyring.keyids(), [])
00148         
00149     def test_adds_key(self):
00150         self.keyring.add(self.key)
00151         self.assertEqual(self.keyring.keyids(), [self.keyid])
00152         self.assert_(self.keyid in self.keyring)
00153         
00154     def test_removes_key(self):
00155         self.keyring.add(self.key)
00156         self.keyring.remove(self.keyid)
00157         self.assertEqual(self.keyring.keyids(), [])
00158         
00159     def test_export_import_roundtrip_works(self):
00160         self.keyring.add(self.key)
00161         exported = str(self.keyring)
00162         keyring2 = obnamlib.Keyring(exported)
00163         self.assertEqual(keyring2.keyids(), [self.keyid])
00164 
00165 
00166 class SecretKeyringTests(unittest.TestCase):
00167 
00168     def test_lists_correct_key(self):
00169         keyid1 = '3B1802F81B321347'
00170         keyid2 = 'DF3D13AA11E69900'
00171         seckeys = obnamlib.SecretKeyring(cat('test-gpghome/secring.gpg'))
00172         self.assertEqual(sorted(seckeys.keyids()), sorted([keyid1, keyid2]))
00173 
00174 
00175 class PublicKeyEncryptionTests(unittest.TestCase):
00176 
00177     def test_roundtrip_works(self):
00178         cleartext = 'hello, world'
00179         passphrase = 'password1'
00180         keyring = obnamlib.Keyring(cat('test-gpghome/pubring.gpg'))
00181         seckeys = obnamlib.SecretKeyring(cat('test-gpghome/secring.gpg'))
00182         
00183         encrypted = obnamlib.encrypt_with_keyring(cleartext, keyring)
00184         decrypted = obnamlib.decrypt_with_secret_keys(encrypted,
00185                                                       gpghome='test-gpghome')
00186     
00187         self.assertEqual(decrypted, cleartext)
00188