@@ -84,14 +84,19 @@ def _cmd(self, command, shell=False, check=True, verbose=None):
8484 shell = shell , check = check )
8585
8686 def _config_args (self ):
87- arg_templates = [
88- "-c" , self . config [ 'cipher' ] ,
89- "-p" , self . config [ 'password' ] ,
90- " -md" , self . config [ 'digest' ] ,
91- " --kdf" , self . config [ 'kdf' ] ,
92- " -bs" , self . config [ 'base_salt' ] ,
87+ flags_and_keys = [
88+ ( '-c' , 'cipher' ) ,
89+ ( '-p' , 'password' ) ,
90+ ( ' -md' , 'digest' ) ,
91+ ( ' --kdf' , 'kdf' ) ,
92+ ( ' -bs' , 'base_salt' ) ,
9393 ]
94- args = [template .format (** self .config ) for template in arg_templates ]
94+ args = []
95+ for flag , key in flags_and_keys :
96+ value = self .config [key ]
97+ if value is not None :
98+ args .append (flag )
99+ args .append (value )
95100 return args
96101
97102 def is_configured (self ):
@@ -144,7 +149,8 @@ def version(self):
144149 return self ._cmd (f'{ self .transcript_exe } --version' )['out' ].rstrip ()
145150
146151 def _crypt_dir (self ):
147- info = self ._cmd ('git config --local transcrypt.crypt-dir' , check = 0 )
152+ info = self ._cmd ('git config --local transcrypt.crypt-dir' , check = 0 ,
153+ verbose = 0 )
148154 if info ['err' ] == 0 :
149155 crypt_dpath = ub .Path (info ['out' ].strip ())
150156 else :
@@ -198,13 +204,15 @@ def upgrade(self):
198204 return self ._cmd (f'{ self .transcript_exe } --upgrade -y' )
199205
200206 def _load_unversioned_config (self ):
207+ if self .verbose > 0 :
208+ print ('Loading unversioned config' )
201209 local_config = {
202- 'cipher' : self ._cmd ('git config --get --local transcrypt.cipher' )['out' ].strip (),
203- 'digest' : self ._cmd ('git config --get --local transcrypt.digest' )['out' ].strip (),
204- 'kdf' : self ._cmd ('git config --get --local transcrypt.kdf' )['out' ].strip (),
205- 'base_salt' : self ._cmd ('git config --get --local transcrypt.base-salt' )['out' ].strip (),
206- 'password' : self ._cmd ('git config --get --local transcrypt.password' )['out' ].strip (),
207- 'openssl_path' : self ._cmd ('git config --get --local transcrypt.openssl-path' )['out' ].strip (),
210+ 'cipher' : self ._cmd ('git config --get --local transcrypt.cipher' , verbose = 0 )['out' ].strip (),
211+ 'digest' : self ._cmd ('git config --get --local transcrypt.digest' , verbose = 0 )['out' ].strip (),
212+ 'kdf' : self ._cmd ('git config --get --local transcrypt.kdf' , verbose = 0 )['out' ].strip (),
213+ 'base_salt' : self ._cmd ('git config --get --local transcrypt.base-salt' , verbose = 0 )['out' ].strip (),
214+ 'password' : self ._cmd ('git config --get --local transcrypt.password' , verbose = 0 )['out' ].strip (),
215+ 'openssl_path' : self ._cmd ('git config --get --local transcrypt.openssl-path' , verbose = 0 )['out' ].strip (),
208216 }
209217 return local_config
210218
@@ -237,7 +245,7 @@ def setup(self):
237245 self ._setup_gpghome ()
238246 self ._setup_gitrepo ()
239247 self ._setup_contents ()
240- if self .verbose > 2 :
248+ if self .verbose > 1 :
241249 self ._show_manual_env_setup ()
242250 return self
243251
@@ -314,6 +322,16 @@ def _show_manual_env_setup(self):
314322class TestCases :
315323 """
316324 Unit tests to be applied to different transcrypt configurations
325+
326+ xdoctest -m tests/test_transcrypt.py TestCases
327+
328+ Example:
329+ >>> from test_transcrypt import * # NOQA
330+ >>> self = TestCases(verbose=2)
331+ >>> self.setup()
332+ >>> self.sandbox._show_manual_env_setup()
333+ >>> self.test_round_trip()
334+ >>> self.test_export_gpg()
317335 """
318336
319337 def __init__ (self , config = None , dpath = None , verbose = 0 ):
@@ -412,7 +430,7 @@ def test_legacy_defaults():
412430 'password' : 'correct horse battery staple' ,
413431 'digest' : 'md5' ,
414432 'kdf' : 'none' ,
415- 'base_salt' : 'password ' ,
433+ 'base_salt' : '' ,
416434 }
417435 verbose = 1
418436 self = TestCases (config = config , verbose = verbose )
@@ -437,68 +455,148 @@ def test_secure_defaults():
437455
438456
439457def test_configured_salt_changes_on_rekey ():
458+ """
459+ CommandLine:
460+ xdoctest -m tests/test_transcrypt.py test_configured_salt_changes_on_rekey
461+ """
440462 config = {
441463 'cipher' : 'aes-256-cbc' ,
442464 'password' : 'correct horse battery staple' ,
443465 'digest' : 'sha512' ,
444466 'kdf' : 'pbkdf2' ,
445467 'base_salt' : 'random' ,
446468 }
447- verbose = 1
469+ verbose = 2
448470 self = TestCases (config = config , verbose = verbose )
449471 self .setup ()
450472 before_config = self .tc ._load_unversioned_config ()
451473 self .tc .rekey ({'password' : '12345' , 'base_salt' : '' })
452474 self .sandbox .git .commit ('-am commit rekey' )
453475 after_config = self .tc ._load_unversioned_config ()
454- assert before_config ['password' ] != after_config ['password' ]
476+ assert before_config ['password' ] != after_config ['password' ], 'password should have changed!'
477+ assert before_config ['base_salt' ] != after_config ['base_salt' ], 'salt should have changed!'
455478 assert before_config ['cipher' ] == after_config ['cipher' ]
456479 assert before_config ['kdf' ] == after_config ['kdf' ]
457- assert before_config ['base_salt' ] == after_config ['base_salt' ]
458480 assert before_config ['openssl_path' ] == after_config ['openssl_path' ]
459481
460482
483+ def test_unspecified_salt_without_kdf ():
484+ """
485+ In this case the salt should default to the password method
486+ """
487+ config = {
488+ 'cipher' : 'aes-256-cbc' ,
489+ 'password' : 'correct horse battery staple' ,
490+ 'digest' : 'sha512' ,
491+ 'kdf' : '' ,
492+ 'base_salt' : None ,
493+ }
494+ verbose = 2
495+ self = TestCases (config = config , verbose = verbose )
496+ self .setup ()
497+ config1 = self .tc ._load_unversioned_config ()
498+ assert config1 ['base_salt' ] == 'password'
499+
500+
501+ def test_unspecified_salt_with_kdf ():
502+ config = {
503+ 'cipher' : 'aes-256-cbc' ,
504+ 'password' : 'correct horse battery staple' ,
505+ 'digest' : 'sha512' ,
506+ 'kdf' : 'pbkdf2' ,
507+ 'base_salt' : None ,
508+ }
509+ verbose = 1
510+ self = TestCases (config = config , verbose = verbose )
511+ self .setup ()
512+ config1 = self .tc ._load_unversioned_config ()
513+ assert len (config1 ['base_salt' ]) == 64
514+
515+
516+ def test_salt_changes_when_kdf_changes ():
517+ config = {
518+ 'cipher' : 'aes-256-cbc' ,
519+ 'password' : 'correct horse battery staple' ,
520+ 'digest' : 'sha512' ,
521+ 'kdf' : '' ,
522+ 'base_salt' : None ,
523+ }
524+ verbose = 2
525+ self = TestCases (config = config , verbose = verbose )
526+ self .setup ()
527+ config1 = self .tc ._load_unversioned_config ()
528+ assert config1 ['base_salt' ] == 'password'
529+ # Test rekey, base-salt should still be password
530+ self .tc .rekey ({'password' : '12345' })
531+ config2 = self .tc ._load_unversioned_config ()
532+ assert config2 ['base_salt' ] == 'password'
533+ self .sandbox .git .commit ('-am commit rekey' )
534+
535+ # Test rekey with kdf=pbkdf2 base-salt should now randomize
536+ self .tc .rekey ({'password' : '12345' , 'kdf' : 'pbkdf2' , 'base_salt' : None })
537+ config3 = self .tc ._load_unversioned_config ()
538+ assert len (config3 ['base_salt' ]) == 64 , 'should have had new random salt'
539+ self .sandbox .git .commit ('-am commit rekey' )
540+
541+ # Test rekey going back to no kdf
542+ self .tc .rekey ({'password' : '12345' , 'kdf' : 'none' , 'base_salt' : None })
543+ config4 = self .tc ._load_unversioned_config ()
544+ assert config4 ['base_salt' ] == 'password'
545+
546+
461547def test_configuration_grid ():
462548 """
463549 CommandLine:
464550 xdoctest -m tests/test_transcrypt.py test_configuration_grid
465-
466- Example:
467- >>> from test_transcrypt import * # NOQA
468- >>> self = TestCases()
469- >>> self.setup()
470- >>> self.sandbox._show_manual_env_setup()
471- >>> self.test_round_trip()
472- >>> self.test_export_gpg()
473551 """
474552 # Test that transcrypt works under a variety of config conditions
475553 basis = {
476554 'cipher' : ['aes-256-cbc' , 'aes-128-ecb' ],
477555 'password' : ['correct horse battery staple' ],
478556 'digest' : ['md5' , 'sha256' ],
479557 'kdf' : ['none' , 'pbkdf2' ],
480- 'base_salt' : ['password' , 'random' , 'mylittlecustomsalt' ],
558+ 'base_salt' : ['password' , 'random' , 'mylittlecustomsalt' , None ],
481559 }
560+
482561 test_grid = list (ub .named_product (basis ))
483- verbose = 3
562+
563+ def validate_test_grid (params ):
564+ if params ['kdf' ] == 'none' and params ['base_salt' ] != 'password' :
565+ return False
566+ if params ['kdf' ] != 'none' and params ['base_salt' ] == 'password' :
567+ return False
568+ return True
569+
570+ # Remove invalid configs
571+ valid_test_grid = list (filter (validate_test_grid , test_grid ))
572+ print ('valid_test_grid = {}' .format (ub .repr2 (valid_test_grid , sort = 0 , nl = 1 )))
573+
574+ verbose = 2
484575 dpath = 'special:temp'
485576 dpath = 'special:cache'
486- for params in ub .ProgIter (test_grid , desc = 'test configs' , freq = 1 ):
577+ for params in ub .ProgIter (valid_test_grid , desc = 'test configs' , freq = 1 ,
578+ verbose = verbose + 1 ):
579+ if verbose :
580+ print ('\n \n ' )
581+ print ('=================' )
582+ print ('params = {}' .format (ub .repr2 (params , nl = 1 )))
583+ print ('=================' )
584+
487585 config = params .copy ()
488586 self = TestCases (config = config , dpath = dpath , verbose = verbose )
489587 self .setup ()
490- if 1 :
491- # Manual debug
492- self .sandbox ._show_manual_env_setup ()
493-
494588 self .test_round_trip ()
495589 self .test_export_gpg ()
496590 self .test_rekey ()
497-
591+ if verbose :
592+ print ('=================' )
498593
499594if __name__ == '__main__' :
500595 """
501596 CommandLine:
502597 python tests/test_transcrypt.py
598+
599+ # Runs everything
600+ pytest tests/test_transcrypt.py -v
503601 """
504602 test_configuration_grid ()
0 commit comments