lenc 1.1.0 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fbdf59fe864cde5c6b5d6ab0029ed7b3086b6abb
4
- data.tar.gz: 935307daa431368ca0f0d86a8b9eca068d1d1b58
3
+ metadata.gz: 4f09c6e3e0d5b6ce0ebb95fe5a2b7f24a672601d
4
+ data.tar.gz: a5e5dd2ac1ea3c34f2a96fb5568381d4a1368803
5
5
  SHA512:
6
- metadata.gz: 1377690289e75b202bf0a6ee0cffc28c469688ccde9a8dcba36051eed8433b2f32010f5db40b6d648a4d214e0a74ead2c2f4555c2caef5aa5875d21fd17cb90e
7
- data.tar.gz: 46b0cc17fc7254f5a87abe27099d0f3ee21e92fc133bd87de2e20c1df052bc385def1bcda8a1e64f7fd280656a8e46c6664143c1020a91bfc989fb694cbc71a0
6
+ metadata.gz: a54fe2806c2703d53770abfcf3eedfd66ef0c7d714683de2e15644c6053ead25a83da08ea272a84c059de5208bccd65161aa0618e68e605326e5fe449992b389
7
+ data.tar.gz: eb0aec9260ed9fd7d5f771cc11cb48845746dc58ec9d68399d2912f1e428fdef1a8e2c94e1a80c50a6285237891083114127a103951867e568a682eeda13611e
data/CHANGELOG.txt CHANGED
@@ -2,6 +2,15 @@
2
2
  * Version 1.0.0 released
3
3
 
4
4
  2013-03-22
5
+ * 1.1.0 released
5
6
  * For added safety, unless the --storekey option is given when the repository is
6
7
  initialized, the key is no longer stored in repository configuration file, and
7
8
  the user is prompted at every update to enter the password.
9
+
10
+ 2013-04-08
11
+ * 1.1.1 released
12
+ * Fixed problem with README that was omitting a word
13
+ * Now allows passwords as short as 8 characters, to agree with documentation
14
+ * Now omitting symlink'd files (it used to fail upon encountering these)
15
+ * Added ability to provide update password as command line argument (i.e. lencrypt <pwd>)
16
+
data/README.txt CHANGED
@@ -33,7 +33,7 @@ Running the program
33
33
 
34
34
  The program can be asked to perform one of the following tasks:
35
35
 
36
- 1) Setting up a repository. Select a directory you wish to be the <source>
36
+ 1) Setting up a repository. Select a directory you wish to be the \<source\>
37
37
  directory, and make it the current directory. Type:
38
38
 
39
39
  lencrypt -i KEY ENCDIR
@@ -50,7 +50,8 @@ it cannot lie within the current directory's tree).
50
50
  You will be prompted for the encryption key, and then the program will examine
51
51
  which files within the \<source\> directory have been changed (since the repository
52
52
  was created or last updated), and re-encrypt these into the \<encrypted\> directory.
53
-
53
+
54
+
54
55
  3) Recovering encrypted files. Type:
55
56
 
56
57
  lencrypt -r KEY ENCDIR RECDIR
@@ -97,4 +98,7 @@ The format of ignore files is similar to that of .gitignore files. Details:
97
98
  * If the pattern contains any path separators, then the wildcards '*', '?' will not
98
99
  match the path separator.
99
100
 
101
+ Miscellaneous Issues
102
+ -------
103
+ At present, the program will ignore any files (or directories) that are symbolic links.
100
104
 
data/lib/lenc/aes.rb CHANGED
@@ -2,10 +2,6 @@ require_relative 'tools'
2
2
 
3
3
  require 'openssl'
4
4
 
5
- module LEnc
6
- class DecryptionError < Exception
7
- end
8
- end
9
5
 
10
6
  module RepoInternal
11
7
 
data/lib/lenc/lencrypt.rb CHANGED
@@ -13,7 +13,8 @@ class LEncApp
13
13
  opt :orignames, "(with --init) leave filenames unencrypted"
14
14
  opt :storekey, "(with --init) store the key within the repository configuration file so it" \
15
15
  " need not be entered with every update"
16
- opt :update, "update encrypted repository (default operation)"
16
+ opt :update, "update encrypted repository (default operation): KEY", :default => ""
17
+ #opt :updatepwd, "specify key for update: KEY", :type => :string
17
18
  opt :recover, "recover files from an encrypted repository: KEY ENCDIR RECDIR", :type => :strings
18
19
  opt :where, "specify source directory (default = current directory)", :type => :string
19
20
  opt :verbose,"verbose operation"
@@ -25,16 +26,25 @@ class LEncApp
25
26
  p.parse argv
26
27
  end
27
28
 
29
+ # Not sure how to determine if there were leftover arguments;
30
+ # trollop seems to include path information ('.')
31
+ #p.die("Unrecognized argument: #{p.leftovers[0]}",nil) if p.leftovers.size
32
+
28
33
  v = 0
29
34
  v = -1 if options[:quiet]
30
35
  v = 1 if options[:verbose]
31
36
 
37
+ update_pwd = options[:update]
38
+ update_pwd = nil if update_pwd.size == 0
39
+
32
40
  nOpt = 0
33
41
  nOpt += 1 if options[:init]
34
- nOpt += 1 if options[:update]
42
+ nOpt += 1 if update_pwd
35
43
  nOpt += 1 if options[:recover]
36
-
37
- Trollop::die("Only one operation can be performed at a time." ) if nOpt > 1
44
+
45
+ #pr("trollop opts = %s\n",d2(options))
46
+
47
+ p.die("Only one operation can be performed at a time.",nil) if nOpt > 1
38
48
 
39
49
  r = Repo.new(:dryrun => options[:dryrun],
40
50
  :verbosity => v)
@@ -42,14 +52,14 @@ class LEncApp
42
52
  begin
43
53
 
44
54
  if (a = options[:init])
45
- Trollop::die("Expecting: KEY ENCDIR") if a.size != 2
55
+ p.die("Expecting: KEY ENCDIR",nil) if a.size != 2
46
56
  pwd,encDir = a
47
57
  r.create(options[:where], pwd, encDir, options[:orignames], options[:storekey])
48
58
  elsif (a = options[:recover])
49
- Trollop::die("Expecting: KEY ENCDIR RECDIR") if a.size != 3
59
+ p.Trollop::die("Expecting: KEY ENCDIR RECDIR",nil) if a.size != 3
50
60
  r.perform_recovery(a[0],a[1],a[2])
51
61
  else
52
- r.open(options[:where])
62
+ r.open(options[:where],update_pwd)
53
63
  r.perform_update(options[:verifyenc])
54
64
  end
55
65
 
@@ -64,19 +74,6 @@ end
64
74
  if __FILE__ == $0
65
75
  args = ARGV
66
76
 
67
- # if true && Dir.home.end_with?("/jeff")
68
- # warn("trying special")
69
- # bs = File.join(Dir.home,"Desktop/_testdirs_")
70
- #
71
- # if !File.file? "#{bs}/src/.lenc"
72
- # s = "-w #{bs}/src -i onefishtwofishredfishbluefish #{bs}/encr"
73
- # else
74
- # s = "-w #{bs}/src"
75
- # end
76
- ## s = "-h"
77
- # args = s.split
78
- # # args = "-h".split
79
- # end
80
77
 
81
78
  LEncApp.new().run(args)
82
79
  end
data/lib/lenc/repo.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require 'base64'
2
2
  require 'pathname'
3
3
  require 'fileutils'
4
+ require 'tempfile'
4
5
 
5
6
  require_relative 'tools'
6
7
  req('aes config_file')
@@ -28,6 +29,9 @@ end
28
29
 
29
30
  module LEnc
30
31
 
32
+ class DecryptionError < Exception
33
+ end
34
+
31
35
  class RepoNotFoundException < Exception
32
36
  end
33
37
 
@@ -66,16 +70,14 @@ module LEnc
66
70
 
67
71
  if windows?
68
72
  IGNOREFILENAME = "__lencignore__.txt"
69
- TEMPFILENAME = "__tmp_file__.bin"
70
73
  else
71
74
  IGNOREFILENAME = ".lencignore"
72
- TEMPFILENAME = ".lenc__temp__file"
73
75
  end
74
76
 
75
77
 
76
78
  DEFAULTIGNORE = \
77
- "#{LENC_REPO_FILENAME}\n #{TEMPFILENAME}\n" + \
78
- ".DS_Store\n" + \
79
+ "#{LENC_REPO_FILENAME}\n " \
80
+ ".DS_Store\n" + \
79
81
  ".recoverdefaults\n"
80
82
 
81
83
  STATE_CLOSED = 0
@@ -115,7 +117,7 @@ module LEnc
115
117
  # Create a new encryption repository, and open it.
116
118
  #
117
119
  # @param repo_dir directory of new repository (nil for current directory)
118
- # @param key encryption key, a string from 20 to 56 characters in length
120
+ # @param key encryption key, a string from 8 to 56 characters in length
119
121
  # @param enc_dir directory to store encrypted files; must not yet exist, and must
120
122
  # not represent a directory lying within the repo_dir tree
121
123
  # @param original_names if true, the filenames are not encrypted, only the file contents
@@ -161,7 +163,7 @@ module LEnc
161
163
  " is a subdirectory of " + pp[1]
162
164
  end
163
165
 
164
- if (key.size < 20 || key.size > 56)
166
+ if (key.size < 8 || key.size > 56)
165
167
  raise ArgumentError, "Password length " + key.size.to_s \
166
168
  + " is illegal"
167
169
  end
@@ -272,7 +274,6 @@ module LEnc
272
274
 
273
275
  raise IllegalStateException if @state != STATE_OPEN
274
276
 
275
- removeTempFile()
276
277
  reset_state()
277
278
  end
278
279
 
@@ -363,13 +364,6 @@ module LEnc
363
364
  nil
364
365
  end
365
366
 
366
- def renameTempFile(newFilename)
367
- if !File.exists?(TEMPFILENAME)
368
- raise IOError, "Temporary file missing or of wrong type"
369
- end
370
-
371
- File.rename(TEMPFILENAME, newFilename)
372
- end
373
367
 
374
368
  # Starting in a particular directory, attempt to find the nearest
375
369
  # parent repository.
@@ -451,7 +445,6 @@ module LEnc
451
445
  # [...] => [...]
452
446
  # [!..] => [^...]
453
447
 
454
-
455
448
  pat = ''
456
449
 
457
450
  inBrace = false
@@ -557,12 +550,6 @@ module LEnc
557
550
  @ignoreStack.pop()
558
551
  end
559
552
 
560
- def removeTempFile()
561
- if not @dryrun and File.file?(TEMPFILENAME)
562
- remove_file_or_dir(TEMPFILENAME)
563
- end
564
- end
565
-
566
553
  # Determine the secondary key, which is used for the filenames (not their contents)
567
554
  # This is found by encrypting the primary key.
568
555
  def prepareKeys()
@@ -642,8 +629,7 @@ module LEnc
642
629
  !db || hex_dump(s,"after cvt to string (#{s})")
643
630
 
644
631
  rescue ArgumentError => e
645
- pr("caught exception during decrypt: %s\n",dt(e))
646
- raise DecryptionError(e)
632
+ raise DecryptionError.new(e)
647
633
  end
648
634
 
649
635
  set_recovery_pwd_verified()
@@ -688,7 +674,7 @@ module LEnc
688
674
 
689
675
 
690
676
  # Update a single source file if necessary (not a directory)
691
- def encryptFile(sourceFile, encryptFile)
677
+ def encrypt_file(sourceFile, encryptFile)
692
678
 
693
679
  # If encrypted file is a directory, delete it
694
680
  if File.directory?(encryptFile)
@@ -716,19 +702,25 @@ module LEnc
716
702
  pr("%s", srcDisp)
717
703
  end
718
704
 
719
- convertFile(sourceFile, encryptFile, true, showProgress, false)
705
+ encPath = convertFile(sourceFile, true, showProgress, false)
706
+ FileUtils.mv(encPath, encryptFile)
707
+
720
708
 
721
709
  if @verifyEncryption
722
710
  # Verify that the original and decoded files are identical
723
- convertFile(encryptFile, TEMPFILENAME, false, showProgress, true)
724
- if !FileUtils.compare_file(sourceFile, TEMPFILENAME)
711
+ decoded_file = convertFile(encryptFile, false, showProgress, true)
712
+ files_match = FileUtils.compare_file(sourceFile, decoded_file.path)
713
+ decoded_file.unlink
714
+
715
+ if !files_match
716
+ delete_file_or_dir(encryptFile)
725
717
  raise EncryptionVerificationException, \
726
718
  "File '#{srcDisp}' did not encrypt/decrypt correctly"
719
+
727
720
  end
728
721
  if @verbosity >= 0
729
722
  pr(" (file #{srcDisp} encrypted correctly)\n")
730
723
  end
731
- removeTempFile()
732
724
  end
733
725
  end
734
726
  end
@@ -736,13 +728,16 @@ module LEnc
736
728
  # Determine if a file matches one of the expressions in the ignore stack.
737
729
  # Searches the stack from top to bottom (i.e., the outermost elements are examined last)
738
730
  def shouldFileBeIgnored(f)
731
+ db = false
732
+ !db || pr("shouldFileBeIgnored? #{f}\n")
739
733
  f2 = f
740
734
  @ignoreStack.reverse.each do |dir,ients|
741
735
  ients.each do |ient|
742
736
  fArg = ient.pathMode ? f2 : f
743
737
 
744
738
  matches = ient.rexp.match(fArg)
745
-
739
+ !db || pr(" ent path=#{ient.pathMode} rexp=#{ient.rexp} neg=#{ient.negated} matches=#{matches}\n")
740
+
746
741
  if matches
747
742
  return !ient.negated
748
743
  end
@@ -810,10 +805,18 @@ module LEnc
810
805
  # Convert string to ASCII-8BIT encoding.
811
806
  f = to_ascii8(f2)
812
807
 
808
+ !db || pr(" testing if file should be ignored: #{f}\n")
813
809
  ignore = shouldFileBeIgnored(f)
814
810
 
815
811
  filePath = File.join(sourceDir,f)
816
812
 
813
+ if File.symlink?(filePath)
814
+ if @verbosity >= 0
815
+ pr("Omitting symlink file '#{rel_path(filePath,@inputDir)}'\n")
816
+ end
817
+ next
818
+ end
819
+
817
820
  if ignore
818
821
  !db || pr("(ignoring %s)\n", rel_path(filePath, @inputDir)) if @verbosity >= 1
819
822
  next
@@ -821,8 +824,7 @@ module LEnc
821
824
 
822
825
  if f.start_with?(ENCRFILENAMEPREFIX)
823
826
  if @verbosity >= 0
824
- msg = "Source file/dir found with name that looks encrypted: " + d(f)
825
- pr("(%s)\n", f)
827
+ pr("(Omitting source file / dir with name that looks encrypted: #{d(f)})\n")
826
828
  end
827
829
  end
828
830
 
@@ -848,7 +850,8 @@ module LEnc
848
850
  if File.directory?(filePath)
849
851
  encryptDir(filePath, encrPath)
850
852
  else
851
- encryptFile(filePath, encrPath)
853
+ !db || pr("...attempting to encrypt file #{filePath} to #{encrPath}...\n")
854
+ encrypt_file(filePath, encrPath)
852
855
  end
853
856
  end
854
857
 
@@ -859,6 +862,7 @@ module LEnc
859
862
 
860
863
  # (if doing dry run, encrypt dir may not exist)
861
864
 
865
+ !db || pr("examining files in encrypted dir #{encryptDir} to delete ones that don't belong\n")
862
866
  if File.directory?(encryptDir)
863
867
  dire = dir_entries(encryptDir)
864
868
  else
@@ -872,10 +876,10 @@ module LEnc
872
876
  begin
873
877
  orphanOrigName = decryptFilename(f)
874
878
  next if !orphanOrigName
875
- orphanPath = os.path.join(encryptDir, f)
879
+ orphanPath = File.join(encryptDir, f)
876
880
  if @verbosity >= 1
877
881
  printf("Removing encrypted version of missing (or ignored) file " \
878
- + rel_path(os.path.join(sourceDir, orphanOrigName), @inputDir) + ": " + orphanPath)
882
+ + rel_path(File.join(sourceDir, orphanOrigName), @inputDir) + ": " + orphanPath)
879
883
  end
880
884
  if !@dryrun
881
885
  remove_file_or_dir(orphanPath)
@@ -962,14 +966,19 @@ module LEnc
962
966
  pr("%s", pth)
963
967
  end
964
968
  begin
965
- convertFile(encrFullPath, TEMPFILENAME, false, showProgress)
969
+ tmp_file = convertFile(encrFullPath,false, showProgress)
970
+
966
971
  set_recovery_pwd_verified()
972
+
967
973
  if not @dryrun
968
974
  if File.file?(origPath)
969
975
  remove_file_or_dir(origPath)
970
976
  end
971
- renameTempFile(origPath)
977
+ FileUtils.mv(tmp_file.path, origPath)
978
+ else
979
+ tmp_file.unlink
972
980
  end
981
+
973
982
  rescue DecryptionError => e
974
983
 
975
984
  if !@recovery_pwd_verified
@@ -986,18 +995,23 @@ module LEnc
986
995
  end
987
996
 
988
997
  # Encrypt or decrypt a file (not a directory)
989
- def convertFile(srcPath, destPath, encrypt, showProgress=false, verifying=false)
998
+ # @param srcPath source path
999
+ # @param encrypt true if encrypting
1000
+ # @return temporary file containing modified file
1001
+ #
1002
+ def convertFile(srcPath,encrypt, showProgress=false, verifying=false)
990
1003
 
991
1004
  db = warndb 0
992
- !db||pr("\n\n\n\nconvertFile\n %s =>\n %s;\n %s\n",d(srcPath),d(destPath),df(encrypt,"encrypt"))
1005
+ !db||pr("\n\n\n\nconvertFile\n %s\n",d(srcPath))
993
1006
 
1007
+ fw = nil
994
1008
  showDots = false
995
1009
  if not @dryrun
996
1010
 
997
1011
  fSize = File.size(srcPath)
998
1012
 
999
1013
  fr = File.open(srcPath, 'rb')
1000
- fw = File.open(TEMPFILENAME, 'wb')
1014
+ fw = Tempfile.new("repo")
1001
1015
 
1002
1016
  cSize = 100000
1003
1017
 
@@ -1054,8 +1068,6 @@ module LEnc
1054
1068
  fr.close()
1055
1069
  fw.close()
1056
1070
 
1057
- renameTempFile(destPath)
1058
-
1059
1071
  pr("]") if showDots
1060
1072
 
1061
1073
  end
@@ -1063,6 +1075,8 @@ module LEnc
1063
1075
  if showProgress and (showDots or not verifying)
1064
1076
  pr("\n")
1065
1077
  end
1078
+
1079
+ fw
1066
1080
  end
1067
1081
 
1068
1082
  end # class Repo
data/lib/lenc/tools.rb CHANGED
@@ -506,7 +506,7 @@ end
506
506
  # Convenience method to detect if a script is being run
507
507
  # e.g. as a 'main' method (for debug purposes only).
508
508
  # If so, it changes the current directory to the
509
- # directory containing the script.
509
+ # directory containing the script (if such a directory exists).
510
510
  #
511
511
  # @param file pass __FILE__ in here
512
512
  # @return true if so
@@ -523,7 +523,10 @@ def main?(file)
523
523
  end
524
524
 
525
525
  if (ret = (file == scr))
526
- Dir.chdir(File.dirname(file))
526
+ dr = File.dirname(file)
527
+ if File.directory?(dr)
528
+ Dir.chdir(dr)
529
+ end
527
530
  end
528
531
  ret
529
532
  end
data/test/test.rb CHANGED
@@ -4,7 +4,7 @@ require_relative '../lib/lenc/tools.rb'
4
4
  req('repo lencrypt')
5
5
 
6
6
 
7
- #SINGLETEST = "test_200_recover_with_incorrect_password"
7
+ #SINGLETEST = "test_101_update_repo_with_verify"
8
8
  if defined? SINGLETEST
9
9
  if main?(__FILE__)
10
10
  ARGV.concat("-n #{SINGLETEST}".split)
@@ -350,6 +350,7 @@ end
350
350
  end
351
351
  end
352
352
 
353
+
353
354
  def test_200_recover_with_incorrect_password
354
355
  create_repo
355
356
  ex("") # updates repo
@@ -361,17 +362,4 @@ end
361
362
  end
362
363
  end
363
364
 
364
- # def test_300_source_contains_encrypted_filename
365
- # create_repo
366
- # update_repo
367
- #
368
- # makeFile(bogusSourceFile())
369
- # assert_raise(UpdateException) do
370
- # update_repo
371
- # end
372
- # remove_file_or_dir(bogusSourceFile())
373
- # end
374
-
375
-
376
-
377
365
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lenc
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeff Sember
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-03-19 00:00:00.000000000 Z
11
+ date: 2013-04-08 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: "Encrypts a set of local files, and copies the encrypted versions to
14
14
  a repository, \nwhich may be located within a free cloud service (Dropbox, Google