shredder 1.0.0 → 2.0.200126
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README.md +113 -0
- data/bin/shredder +47 -35
- data/lib/shredder.rb +6 -5
- data/lib/shredder/files.rb +22 -36
- data/lib/shredder/shredder.rb +33 -39
- data/lib/shredder/stdio.rb +31 -0
- data/lib/shredder/streams.rb +4 -17
- metadata +16 -72
- data/History.txt +0 -0
- data/README.rdoc +0 -58
- data/TODO.txt +0 -7
- data/features/main.feature +0 -72
- data/features/step_definitions/main_steps.rb +0 -77
- data/lib/shredder/functions.rb +0 -36
- data/lib/shredder/version.rb +0 -5
- data/shredder.gemspec +0 -55
- data/test/test_shredder.rb +0 -140
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 498eeb86b0aea1ba926ec9c2dd168d41ef4467dd64ff79e7e712f3141aec4e02
|
4
|
+
data.tar.gz: 654802da4b46624cc48f87ca2d6aa949ba451fade334c6ce77a5c7836465938d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 52830fd82dd9711003bd78e039df4467e66b95b013ca622c28103e65265dbe8b02841f886008db00b66508e2e34a47eb8f586c398b11fecf41e2ed5bcc6274c2
|
7
|
+
data.tar.gz: 766b712345d5efa6783a730d4f9afb4a00fe48e40a7f805a65252c7075edf1bad5f6cb750ab388f842e4accd2e58bb26612d6ed1b6d43eb85f57dbcdb9f5d929
|
data/README.md
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
# shredder
|
2
|
+
|
3
|
+
* [VERSION 2.0.200126](https://github.com/carlosjhr64/shredder/releases)
|
4
|
+
* [github](https://github.com/carlosjhr64/shredder)
|
5
|
+
* [rubygems](https://rubygems.org/gems/shredder)
|
6
|
+
|
7
|
+
## DESCRIPTION:
|
8
|
+
|
9
|
+
Shred a file into file fragments, and join fragments back into a restored file.
|
10
|
+
|
11
|
+
## HELP:
|
12
|
+
|
13
|
+
$ Usage:
|
14
|
+
$ shredder shred [:options+] <shreds=FILENAME>+
|
15
|
+
$ shredder sew [:options+] <shreds=FILENAME>+
|
16
|
+
$ Options:
|
17
|
+
$ --n=INTEGER Number of shreds
|
18
|
+
$ --passphrase Relay passphrase from stding to stdout
|
19
|
+
$ Types:
|
20
|
+
$ FILENAME /^[[:print:]]+$/
|
21
|
+
$ INTEGER /^[2-9]d*$/
|
22
|
+
$ # Examples:
|
23
|
+
$ # shredder shred file.1 file.2 < file.txt
|
24
|
+
$ # shredder shred --n=2 file < file.txt
|
25
|
+
$ # shredder sew file.1 file.2 > file.txt
|
26
|
+
$ # shredder shred --n=2 file > file.txt
|
27
|
+
|
28
|
+
## SYNOPSIS
|
29
|
+
|
30
|
+
### Library:
|
31
|
+
|
32
|
+
require 'shredder'
|
33
|
+
|
34
|
+
#### Shredder::Streams
|
35
|
+
|
36
|
+
require 'stringio'
|
37
|
+
|
38
|
+
sewn = StringIO.new("This is a test String: 1, 2, 3.")
|
39
|
+
sewn.string.length #=> 31
|
40
|
+
shreds = [StringIO.new, StringIO.new]
|
41
|
+
|
42
|
+
shredder = Shredder::Streams.new(sewn, shreds)
|
43
|
+
shredder.shred #=> 31
|
44
|
+
|
45
|
+
shreds[0].string
|
46
|
+
#=> "T\u0001S\u001AAT\u0016T'\e\t\u001A\u001D\u0012\f\u001D"
|
47
|
+
shreds[0].string.length #=> 16
|
48
|
+
|
49
|
+
shreds[1].string
|
50
|
+
#=> "<\u001AISA\u0011\as\u0006\a]\u0011\f\u001E\u0013"
|
51
|
+
shreds[1].string.length #=> 15
|
52
|
+
|
53
|
+
restored = StringIO.new
|
54
|
+
shreds.each{|_|_.rewind}
|
55
|
+
|
56
|
+
shredder = Shredder::Streams.new(restored, shreds)
|
57
|
+
shredder.sew #=> 31
|
58
|
+
|
59
|
+
restored.string #=> "This is a test String: 1, 2, 3."
|
60
|
+
|
61
|
+
#### Shredder::Files
|
62
|
+
|
63
|
+
sewn = './tmp/sewn.txt'
|
64
|
+
shreds = './tmp/shreds'
|
65
|
+
restored = './tmp/restored.txt'
|
66
|
+
|
67
|
+
File.read(sewn).chomp #=> "This is a test file: 1, 2, 3."
|
68
|
+
File.size(sewn) #=> 30
|
69
|
+
|
70
|
+
shredder = Shredder::Files.new(sewn, shreds, 3)
|
71
|
+
shredder.shreds
|
72
|
+
#=> ["./tmp/shreds.1", "./tmp/shreds.2", "./tmp/shreds.3"]
|
73
|
+
shredder.shred #=> 30
|
74
|
+
|
75
|
+
File.read(shreds+'.1') #=> "T\u001A\u001AA\u0016F\t\u0011\u0012\u0013"
|
76
|
+
File.read(shreds+'.2') #=> "<SST\a\u000F_\u001D\u001E\u001D"
|
77
|
+
File.read(shreds+'.3') #=> "\u0001IA\u0011T\u0005\u001A\f\f$"
|
78
|
+
File.size(shreds+'.3') #=> 10
|
79
|
+
|
80
|
+
shredder = Shredder::Files.new(restored, shreds, 3)
|
81
|
+
shredder.sewn #=> "./tmp/restored.txt"
|
82
|
+
shredder.sew #=> 30
|
83
|
+
File.read(restored).chomp #=> "This is a test file: 1, 2, 3."
|
84
|
+
|
85
|
+
## INSTALL:
|
86
|
+
|
87
|
+
$ gem install shredder
|
88
|
+
|
89
|
+
## LICENSE:
|
90
|
+
|
91
|
+
(The MIT License)
|
92
|
+
|
93
|
+
Copyright (c) 2020 CarlosJHR64
|
94
|
+
|
95
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
96
|
+
a copy of this software and associated documentation files (the
|
97
|
+
'Software'), to deal in the Software without restriction, including
|
98
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
99
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
100
|
+
permit persons to whom the Software is furnished to do so, subject to
|
101
|
+
the following conditions:
|
102
|
+
|
103
|
+
The above copyright notice and this permission notice shall be
|
104
|
+
included in all copies or substantial portions of the Software.
|
105
|
+
|
106
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
107
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
108
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
109
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
110
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
111
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
112
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
113
|
+
|
data/bin/shredder
CHANGED
@@ -1,43 +1,55 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
# Gems:
|
4
2
|
require 'help_parser'
|
5
3
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
NAME = File.basename $0 # Program Name
|
11
|
-
HELP = <<HELP
|
12
|
-
Usage: #{NAME} [options] [file] shred1 shred2...
|
4
|
+
OPTIONS = HelpParser['2.0.200126', <<HELP]
|
5
|
+
Usage:
|
6
|
+
shredder shred [:options+] <shreds=FILENAME>+
|
7
|
+
shredder sew [:options+] <shreds=FILENAME>+
|
13
8
|
Options:
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
--no a symmetry with commands like gpg.
|
25
|
-
Note:
|
26
|
-
Typical use of relay is for passphrase.
|
27
|
-
Version: #{VERSION}
|
9
|
+
--n=INTEGER \tNumber of shreds
|
10
|
+
--passphrase\tRelay passphrase from stding to stdout
|
11
|
+
Types:
|
12
|
+
FILENAME /^[[:print:]]+$/
|
13
|
+
INTEGER /^[2-9]\d*$/
|
14
|
+
# Examples:
|
15
|
+
# shredder shred file.1 file.2 < file.txt
|
16
|
+
# shredder shred --n=2 file < file.txt
|
17
|
+
# shredder sew file.1 file.2 > file.txt
|
18
|
+
# shredder shred --n=2 file > file.txt
|
28
19
|
HELP
|
20
|
+
HelpParser.int?(:n)
|
29
21
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
22
|
+
shreds = OPTIONS.shreds
|
23
|
+
count = shreds.length
|
24
|
+
if n = OPTIONS.n?
|
25
|
+
if count == 1
|
26
|
+
count = n
|
27
|
+
shreds = shreds.first
|
28
|
+
elsif count != n
|
29
|
+
$stderr.puts "shred count(#{count}) not equal to n(#{n})."
|
30
|
+
exit 64
|
31
|
+
end
|
32
|
+
end
|
33
|
+
unless count > 1
|
34
|
+
$stderr.puts "shred count must be at least 2"
|
42
35
|
exit 64
|
43
36
|
end
|
37
|
+
|
38
|
+
require 'shredder/shredder'
|
39
|
+
require 'shredder/streams'
|
40
|
+
require 'shredder/stdio'
|
41
|
+
|
42
|
+
shredder = Shredder::StdIO.new(shreds, count)
|
43
|
+
case OPTIONS[1]
|
44
|
+
when 'shred'
|
45
|
+
shredder.shred
|
46
|
+
when 'sew'
|
47
|
+
begin
|
48
|
+
shredder.sew
|
49
|
+
rescue Errno::ENOENT
|
50
|
+
# Common expected type of error,
|
51
|
+
# user tries to sew non-existing shreds.
|
52
|
+
$stderr.puts $!.message
|
53
|
+
exit 65
|
54
|
+
end
|
55
|
+
end
|
data/lib/shredder.rb
CHANGED
@@ -1,8 +1,9 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
require 'shredder/streams'
|
1
|
+
module Shredder
|
2
|
+
VERSION = '2.0.200126'
|
3
|
+
end
|
5
4
|
require 'shredder/shredder'
|
6
|
-
|
5
|
+
require 'shredder/streams'
|
6
|
+
require 'shredder/stdio'
|
7
|
+
require 'shredder/files'
|
7
8
|
# Requires:
|
8
9
|
#`ruby`
|
data/lib/shredder/files.rb
CHANGED
@@ -1,51 +1,37 @@
|
|
1
|
-
module
|
2
|
-
|
1
|
+
module Shredder
|
3
2
|
class Files
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
@
|
9
|
-
@shreds
|
10
|
-
@limit = limit
|
3
|
+
include Shredder
|
4
|
+
# this one takes filenames
|
5
|
+
def initialize(sewn, shreds=sewn, m=2, n: m)
|
6
|
+
@sewn = sewn
|
7
|
+
@shreds = shred_files(shreds, n)
|
8
|
+
raise "Need at least 2 shreds" unless @shreds.length > 1
|
11
9
|
end
|
12
10
|
|
13
|
-
def shred(limit
|
14
|
-
reader
|
15
|
-
writers = []
|
16
|
-
@shreds.each{|shred| writers.push(File.open(shred, 'wb'))}
|
17
|
-
|
18
|
-
count = nil
|
11
|
+
def shred(limit=0)
|
12
|
+
reader = writers = count = nil
|
19
13
|
begin
|
20
|
-
|
21
|
-
|
22
|
-
|
14
|
+
reader = File.open(@sewn, 'r')
|
15
|
+
writers = @shreds.map{|shred| File.open(shred, 'wb')}
|
16
|
+
count = Streams.new(reader, writers).shred(limit: limit)
|
23
17
|
ensure
|
24
|
-
writers.each{|writer| writer.close}
|
25
|
-
reader.close
|
26
|
-
|
27
|
-
|
18
|
+
writers.each{|writer| writer.close} if writers
|
19
|
+
reader.close if reader
|
20
|
+
end
|
28
21
|
return count
|
29
22
|
end
|
30
23
|
|
31
|
-
def sew(limit
|
32
|
-
writer
|
33
|
-
readers = []
|
34
|
-
@shreds.each{|shred| readers.push(File.open(shred, 'r'))}
|
35
|
-
|
36
|
-
count = nil
|
24
|
+
def sew(limit=0)
|
25
|
+
writer = readers = count = nil
|
37
26
|
begin
|
38
|
-
|
39
|
-
|
40
|
-
|
27
|
+
writer = File.open(@sewn, 'wb')
|
28
|
+
readers = @shreds.map{|shred| File.open(shred, 'r')}
|
29
|
+
count = Streams.new(writer, readers).sew(limit: limit)
|
41
30
|
ensure
|
42
|
-
writer.close
|
43
|
-
readers.each{|reader| reader.close}
|
31
|
+
writer.close if writer
|
32
|
+
readers.each{|reader| reader.close} if readers
|
44
33
|
end
|
45
|
-
|
46
34
|
return count
|
47
35
|
end
|
48
|
-
|
49
36
|
end
|
50
|
-
|
51
37
|
end
|
data/lib/shredder/shredder.rb
CHANGED
@@ -1,46 +1,40 @@
|
|
1
|
-
module
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
@sewed = (@shred)? STDIN : STDOUT
|
13
|
-
else
|
14
|
-
@sewed = @shreds.shift
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
def execute(sewed=@sewed, shreds=@shreds, shred=@shred)
|
20
|
-
stream = false
|
21
|
-
if sewed.kind_of?(IO)
|
22
|
-
stream = true
|
23
|
-
rw = (shred)? 'w' : 'r'
|
24
|
-
shreds = shreds.map{|filename| File.open(filename, rw)}
|
25
|
-
end
|
26
|
-
|
27
|
-
shredder = (stream)? Shredder::Streams.new(sewed, shreds) : Shredder::Files.new(sewed, shreds)
|
28
|
-
STDOUT.puts STDIN.gets if @relay
|
29
|
-
begin
|
30
|
-
(shred)? shredder.shred : shredder.sew
|
31
|
-
ensure
|
32
|
-
shreds.each{|filehandle| filehandle.close} if stream
|
33
|
-
end
|
1
|
+
module Shredder
|
2
|
+
attr_accessor :sewn, :shreds
|
3
|
+
|
4
|
+
# note that these are streams
|
5
|
+
def shred(sewn=(@sewn or $stdin), shreds=@shreds,
|
6
|
+
writers: shreds, reader: sewn, limit: 0)
|
7
|
+
shreds,xor,count = writers.length,0,0
|
8
|
+
while byte = reader.getbyte do
|
9
|
+
writers[count%shreds].putc(xor^(xor=byte))
|
10
|
+
count += 1 # not that 0 is skipped
|
11
|
+
break if count == limit
|
34
12
|
end
|
13
|
+
return count
|
14
|
+
end
|
35
15
|
|
36
|
-
|
37
|
-
|
16
|
+
# note that these are streams
|
17
|
+
def sew(shreds=@shreds, sewn=(@sewn or $stdout),
|
18
|
+
readers: shreds, writer: sewn, limit: 0)
|
19
|
+
shreds,xor,count = readers.length,0,0
|
20
|
+
while byte = readers[count%shreds].getbyte do
|
21
|
+
writer.putc(xor=(byte^xor))
|
22
|
+
count += 1 # note that 0 is skipped
|
23
|
+
break if count == limit
|
38
24
|
end
|
25
|
+
return count
|
26
|
+
end
|
39
27
|
|
40
|
-
|
41
|
-
|
28
|
+
def shred_files(b, m=2, basename: b, n: m)
|
29
|
+
case basename
|
30
|
+
when Array
|
31
|
+
basename
|
32
|
+
when String
|
33
|
+
(1..n).map{|i| "#{basename}.#{i}"}
|
34
|
+
when Integer
|
35
|
+
(1..basename).map{|i| "#{@sewn or 'shred'}.#{i}"}
|
36
|
+
else
|
37
|
+
raise "Expected basename Array|String|Integer"
|
42
38
|
end
|
43
|
-
|
44
39
|
end
|
45
|
-
|
46
40
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Shredder
|
2
|
+
class StdIO
|
3
|
+
include Shredder
|
4
|
+
# this one takes shred filenames and uses $stdin or $stdout appropriately.
|
5
|
+
def initialize(*args)
|
6
|
+
@shreds = shred_files(*args)
|
7
|
+
end
|
8
|
+
|
9
|
+
def shred(limit=0)
|
10
|
+
writers = count = nil
|
11
|
+
begin
|
12
|
+
writers = @shreds.map{|shred| File.open(shred, 'wb')}
|
13
|
+
count = Streams.new($stdin, writers).shred(limit: limit)
|
14
|
+
ensure
|
15
|
+
writers.each{|writer| writer.close} if writers
|
16
|
+
end
|
17
|
+
return count
|
18
|
+
end
|
19
|
+
|
20
|
+
def sew(limit=0)
|
21
|
+
readers = count = nil
|
22
|
+
begin
|
23
|
+
readers = @shreds.map{|shred| File.open(shred, 'r')}
|
24
|
+
count = Streams.new($stdout, readers).sew(limit: limit)
|
25
|
+
ensure
|
26
|
+
readers.each{|reader| reader.close} if readers
|
27
|
+
end
|
28
|
+
return count
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/shredder/streams.rb
CHANGED
@@ -1,23 +1,10 @@
|
|
1
|
-
module
|
2
|
-
|
1
|
+
module Shredder
|
3
2
|
class Streams
|
4
|
-
|
5
|
-
|
3
|
+
include Shredder
|
6
4
|
# this one takes streams
|
7
|
-
def initialize(
|
8
|
-
@
|
5
|
+
def initialize(sewn, shreds)
|
6
|
+
@sewn = sewn
|
9
7
|
@shreds = shreds
|
10
|
-
@limit = limit
|
11
8
|
end
|
12
|
-
|
13
|
-
def shred(limit=@limit)
|
14
|
-
Streams.shred(@sew,@shreds,limit)
|
15
|
-
end
|
16
|
-
|
17
|
-
def sew(limit=@limit)
|
18
|
-
Streams.sew(@sew,@shreds,limit)
|
19
|
-
end
|
20
|
-
|
21
9
|
end
|
22
|
-
|
23
10
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: shredder
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.200126
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
-
|
7
|
+
- carlosjhr64
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-01-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: help_parser
|
@@ -16,94 +16,43 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '6.5'
|
20
20
|
- - ">="
|
21
21
|
- !ruby/object:Gem::Version
|
22
|
-
version:
|
22
|
+
version: 6.5.0
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
26
26
|
requirements:
|
27
27
|
- - "~>"
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version: '
|
29
|
+
version: '6.5'
|
30
30
|
- - ">="
|
31
31
|
- !ruby/object:Gem::Version
|
32
|
-
version:
|
33
|
-
|
34
|
-
|
35
|
-
requirement: !ruby/object:Gem::Requirement
|
36
|
-
requirements:
|
37
|
-
- - "~>"
|
38
|
-
- !ruby/object:Gem::Version
|
39
|
-
version: '2.5'
|
40
|
-
- - ">="
|
41
|
-
- !ruby/object:Gem::Version
|
42
|
-
version: 2.5.5
|
43
|
-
type: :development
|
44
|
-
prerelease: false
|
45
|
-
version_requirements: !ruby/object:Gem::Requirement
|
46
|
-
requirements:
|
47
|
-
- - "~>"
|
48
|
-
- !ruby/object:Gem::Version
|
49
|
-
version: '2.5'
|
50
|
-
- - ">="
|
51
|
-
- !ruby/object:Gem::Version
|
52
|
-
version: 2.5.5
|
53
|
-
- !ruby/object:Gem::Dependency
|
54
|
-
name: symmetric_gpg
|
55
|
-
requirement: !ruby/object:Gem::Requirement
|
56
|
-
requirements:
|
57
|
-
- - "~>"
|
58
|
-
- !ruby/object:Gem::Version
|
59
|
-
version: '2.0'
|
60
|
-
- - ">="
|
61
|
-
- !ruby/object:Gem::Version
|
62
|
-
version: 2.0.1
|
63
|
-
type: :development
|
64
|
-
prerelease: false
|
65
|
-
version_requirements: !ruby/object:Gem::Requirement
|
66
|
-
requirements:
|
67
|
-
- - "~>"
|
68
|
-
- !ruby/object:Gem::Version
|
69
|
-
version: '2.0'
|
70
|
-
- - ">="
|
71
|
-
- !ruby/object:Gem::Version
|
72
|
-
version: 2.0.1
|
73
|
-
description: |
|
74
|
-
Shred a file into file fragments, and join fragments back into a restored file.
|
32
|
+
version: 6.5.0
|
33
|
+
description: 'Shred a file into file fragments, and join fragments back into a restored
|
34
|
+
file.
|
75
35
|
|
76
|
-
|
77
|
-
so that no one depository has the entire file.
|
36
|
+
'
|
78
37
|
email: carlosjhr64@gmail.com
|
79
38
|
executables:
|
80
39
|
- shredder
|
81
40
|
extensions: []
|
82
|
-
extra_rdoc_files:
|
83
|
-
- README.rdoc
|
41
|
+
extra_rdoc_files: []
|
84
42
|
files:
|
85
|
-
-
|
86
|
-
- README.rdoc
|
87
|
-
- TODO.txt
|
43
|
+
- README.md
|
88
44
|
- bin/shredder
|
89
|
-
- features/main.feature
|
90
|
-
- features/step_definitions/main_steps.rb
|
91
45
|
- lib/shredder.rb
|
92
46
|
- lib/shredder/files.rb
|
93
|
-
- lib/shredder/functions.rb
|
94
47
|
- lib/shredder/shredder.rb
|
48
|
+
- lib/shredder/stdio.rb
|
95
49
|
- lib/shredder/streams.rb
|
96
|
-
- lib/shredder/version.rb
|
97
|
-
- shredder.gemspec
|
98
|
-
- test/test_shredder.rb
|
99
50
|
homepage: https://github.com/carlosjhr64/shredder
|
100
51
|
licenses:
|
101
52
|
- MIT
|
102
53
|
metadata: {}
|
103
54
|
post_install_message:
|
104
|
-
rdoc_options:
|
105
|
-
- "--main"
|
106
|
-
- README.rdoc
|
55
|
+
rdoc_options: []
|
107
56
|
require_paths:
|
108
57
|
- lib
|
109
58
|
required_ruby_version: !ruby/object:Gem::Requirement
|
@@ -117,13 +66,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
117
66
|
- !ruby/object:Gem::Version
|
118
67
|
version: '0'
|
119
68
|
requirements:
|
120
|
-
- 'ruby: ruby 2.
|
121
|
-
|
122
|
-
- 'system in development: linux/bash'
|
123
|
-
- 'rm in development: rm (GNU coreutils) 8.13'
|
124
|
-
- 'diff in development: diff (GNU diffutils) 3.2'
|
125
|
-
rubyforge_project:
|
126
|
-
rubygems_version: 2.2.0
|
69
|
+
- 'ruby: ruby 2.7.0p0 (2019-12-25 revision 647ee6f091) [x86_64-linux]'
|
70
|
+
rubygems_version: 3.1.2
|
127
71
|
signing_key:
|
128
72
|
specification_version: 4
|
129
73
|
summary: Shred a file into file fragments, and join fragments back into a restored
|
data/History.txt
DELETED
File without changes
|
data/README.rdoc
DELETED
@@ -1,58 +0,0 @@
|
|
1
|
-
= shredder
|
2
|
-
|
3
|
-
github :: https://www.github.com/carlosjhr64/shredder
|
4
|
-
rubygems :: https://rubygems.org/gems/shredder
|
5
|
-
|
6
|
-
== DESCRIPTION:
|
7
|
-
|
8
|
-
Shred a file into file fragments, and join fragments back into a restored file.
|
9
|
-
|
10
|
-
Disperse file shreds in separate depositories
|
11
|
-
so that no one depository has the entire file.
|
12
|
-
|
13
|
-
== SYNOPSIS
|
14
|
-
|
15
|
-
Command line:
|
16
|
-
|
17
|
-
$ shredder --help
|
18
|
-
$ shredder --shred file.orig file.1 file.2
|
19
|
-
$ shredder --sew file.sewed file.1 file.2
|
20
|
-
$ cat file.orig | shredder --shred --io file.1 file.2
|
21
|
-
$ shredder --sew --io file.1 file.2 > file.sewed
|
22
|
-
|
23
|
-
Library:
|
24
|
-
|
25
|
-
require 'shredder'
|
26
|
-
# ...
|
27
|
-
shredder = SHREDDER:Shredder.new
|
28
|
-
shredder.shred('orinal.txt', 'shred.1', 'shred.2')
|
29
|
-
shredder.sew( 'sewed.txt', 'shred.1', 'shred.2')
|
30
|
-
|
31
|
-
== INSTALL:
|
32
|
-
|
33
|
-
$ sudo gem install shredder
|
34
|
-
|
35
|
-
== LICENSE:
|
36
|
-
|
37
|
-
(The MIT License)
|
38
|
-
|
39
|
-
Copyright (c) 2014 CarlosJHR64
|
40
|
-
|
41
|
-
Permission is hereby granted, free of charge, to any person obtaining
|
42
|
-
a copy of this software and associated documentation files (the
|
43
|
-
'Software'), to deal in the Software without restriction, including
|
44
|
-
without limitation the rights to use, copy, modify, merge, publish,
|
45
|
-
distribute, sublicense, and/or sell copies of the Software, and to
|
46
|
-
permit persons to whom the Software is furnished to do so, subject to
|
47
|
-
the following conditions:
|
48
|
-
|
49
|
-
The above copyright notice and this permission notice shall be
|
50
|
-
included in all copies or substantial portions of the Software.
|
51
|
-
|
52
|
-
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
53
|
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
54
|
-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
55
|
-
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
56
|
-
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
57
|
-
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
58
|
-
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/TODO.txt
DELETED
data/features/main.feature
DELETED
@@ -1,72 +0,0 @@
|
|
1
|
-
@main
|
2
|
-
Feature: Main Features
|
3
|
-
|
4
|
-
Background:
|
5
|
-
* Given command "ruby -I ./lib ./bin/shredder"
|
6
|
-
|
7
|
-
Scenario: Long opt version.
|
8
|
-
* Given arguments "--version"
|
9
|
-
* When run
|
10
|
-
* Then status is "0"
|
11
|
-
* Then stderr is ""
|
12
|
-
* Then stdout is "1.0.0"
|
13
|
-
|
14
|
-
Scenario: Long opt help.
|
15
|
-
* Given arguments "--help"
|
16
|
-
* When run
|
17
|
-
* Then status is "0"
|
18
|
-
* Then stderr is ""
|
19
|
-
* Then stdout matches "^Usage: shredder"
|
20
|
-
|
21
|
-
Scenario: Can't be both sew and shred.
|
22
|
-
* Given system(rm ./temp.* 2> /dev/null)
|
23
|
-
* Given system(openssl rand -base64 32 > ./temp.txt)
|
24
|
-
* Given arguments "--sew --shred ./temp.txt ./temp.1 ./temp.2"
|
25
|
-
* When run
|
26
|
-
* Then status is "64"
|
27
|
-
* Then stderr is not ""
|
28
|
-
* Then stdout is ""
|
29
|
-
* Then stderr is "Need choice: sew or shred?"
|
30
|
-
|
31
|
-
Scenario: Needs to be either sew or shred.
|
32
|
-
* Given system(rm ./temp.* 2> /dev/null)
|
33
|
-
* Given system(openssl rand -base64 32 > ./temp.txt)
|
34
|
-
* Given arguments "./temp.txt ./temp.1 ./temp.2"
|
35
|
-
* When run
|
36
|
-
* Then status is "64"
|
37
|
-
* Then stderr is not ""
|
38
|
-
* Then stdout is ""
|
39
|
-
* Then stderr is "Need choice: sew or shred?"
|
40
|
-
|
41
|
-
Scenario: What we shred, we can sew.
|
42
|
-
* Given system(rm ./temp.* 2> /dev/null)
|
43
|
-
* Given system(openssl rand -base64 32 > ./temp.txt)
|
44
|
-
* Given arguments "--shred ./temp.txt ./temp.1 ./temp.2"
|
45
|
-
* When run
|
46
|
-
* Then status is "0"
|
47
|
-
* Then stderr is ""
|
48
|
-
* Then stdout is ""
|
49
|
-
* Then system(test -e ./temp.1)
|
50
|
-
* Then system(test -e ./temp.2)
|
51
|
-
* Given arguments "--sew ./temp.sewed ./temp.1 ./temp.2"
|
52
|
-
* When run
|
53
|
-
* Then status is "0"
|
54
|
-
* Then stderr is ""
|
55
|
-
* Then stdout is ""
|
56
|
-
* Then system(test -e ./temp.sewed)
|
57
|
-
# temp.txt and temp.sewed are equal
|
58
|
-
* Then system(diff temp.txt temp.sewed > /dev/null)
|
59
|
-
# Just a sanity check temp.1 and temp.2 are not equal
|
60
|
-
* Then not system(diff temp.1 temp.2 > /dev/null)
|
61
|
-
|
62
|
-
Scenario: What we shred from stdin, we can sew to stdout. And using 3 shreds to boot!
|
63
|
-
* Given system(rm ./temp.* 2> /dev/null)
|
64
|
-
* Given system(openssl rand -base64 32 > ./temp.txt)
|
65
|
-
* Given system(cat ./temp.txt | ruby -I ./lib ./bin/shredder --shred --io ./temp.1 ./temp.2 ./temp.3)
|
66
|
-
* Then system(test -e ./temp.3)
|
67
|
-
* Given system(ruby -I ./lib ./bin/shredder --sew --io ./temp.1 ./temp.2 ./temp.3 > ./temp.sewed)
|
68
|
-
* Then system(test -e ./temp.sewed)
|
69
|
-
* Then system(diff temp.txt temp.sewed > /dev/null)
|
70
|
-
|
71
|
-
# Let's clean up after ourselves...
|
72
|
-
* Given system(rm ./temp.* 2> /dev/null)
|
@@ -1,77 +0,0 @@
|
|
1
|
-
require 'open3'
|
2
|
-
|
3
|
-
# Requires:
|
4
|
-
#`bash`
|
5
|
-
|
6
|
-
H = {}
|
7
|
-
|
8
|
-
def _capture3(command)
|
9
|
-
stdout, stderr, status = Open3.capture3(command)
|
10
|
-
H['status'] = status.exitstatus
|
11
|
-
H['stdout'] = stdout.chomp
|
12
|
-
H['stderr'] = stderr.chomp
|
13
|
-
end
|
14
|
-
|
15
|
-
def _given(condition)
|
16
|
-
case condition
|
17
|
-
when /^(\w+) "([^"]*)"$/
|
18
|
-
H[$1] = $2
|
19
|
-
when /^system\(([^\(\)]*)\)$/
|
20
|
-
system($1)
|
21
|
-
else
|
22
|
-
raise "Unrecognized Given-Statement"
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
def _when(condition)
|
27
|
-
case condition
|
28
|
-
when 'run'
|
29
|
-
command, arguments = H['command'], H['arguments']
|
30
|
-
raise 'Need command and argurments to run' unless command and arguments
|
31
|
-
_capture3("#{command} #{arguments}")
|
32
|
-
when /^run\(([^\(\)]*)\)$/
|
33
|
-
_capture3($1)
|
34
|
-
else
|
35
|
-
raise "Unrecognized When-Statement"
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
def _then(condition)
|
40
|
-
case condition
|
41
|
-
when /^(not )?system\(([^\(\)]*)\)$/
|
42
|
-
neg, cmd = $1, $2
|
43
|
-
ok = system(cmd)
|
44
|
-
ok = !ok if neg
|
45
|
-
raise "System Call Error" unless ok
|
46
|
-
when /^(\w+) (\w+)( not)? "([^"]*)"$/
|
47
|
-
key, cmp, negate, expected = $1, $2, $3, $4
|
48
|
-
actual = H[key].to_s
|
49
|
-
ok = case cmp
|
50
|
-
when 'is'
|
51
|
-
actual == expected
|
52
|
-
when 'matches'
|
53
|
-
expected = Regexp.new(expected)
|
54
|
-
actual =~ expected
|
55
|
-
else
|
56
|
-
raise "Unrecognized Comparison Operator"
|
57
|
-
end
|
58
|
-
ok = !ok if negate
|
59
|
-
raise "Got #{actual} for #{key}" unless ok
|
60
|
-
else
|
61
|
-
raise "Unrecognized Then-Statement"
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
Given /^(\w+) (.*)$/ do |given, condition|
|
66
|
-
condition.strip!
|
67
|
-
case given
|
68
|
-
when 'Given'
|
69
|
-
_given(condition)
|
70
|
-
when 'When'
|
71
|
-
_when(condition)
|
72
|
-
when 'Then'
|
73
|
-
_then(condition)
|
74
|
-
else
|
75
|
-
raise "'#{given}' form not defined."
|
76
|
-
end
|
77
|
-
end
|
data/lib/shredder/functions.rb
DELETED
@@ -1,36 +0,0 @@
|
|
1
|
-
module SHREDDER
|
2
|
-
|
3
|
-
module Functions
|
4
|
-
|
5
|
-
# note that these are streams
|
6
|
-
def shred(reader, writers, limit=0)
|
7
|
-
shreds = writers.length
|
8
|
-
xor = count = 0
|
9
|
-
while byte = reader.getbyte do
|
10
|
-
writers[ count % shreds ].putc byte^xor
|
11
|
-
xor = byte
|
12
|
-
count += 1
|
13
|
-
# note: will not break if limit is zero
|
14
|
-
break if count == limit
|
15
|
-
end
|
16
|
-
return count
|
17
|
-
end
|
18
|
-
|
19
|
-
# note that these are streams
|
20
|
-
def sew(writer, readers, limit=0)
|
21
|
-
shreds = readers.length
|
22
|
-
xor = count = 0
|
23
|
-
while byte = readers[ count % shreds ].getbyte do
|
24
|
-
chr = byte^xor
|
25
|
-
xor = chr
|
26
|
-
writer.putc chr
|
27
|
-
count += 1
|
28
|
-
# note: will not break if limit is zero
|
29
|
-
break if count == limit
|
30
|
-
end
|
31
|
-
return count
|
32
|
-
end
|
33
|
-
|
34
|
-
end
|
35
|
-
|
36
|
-
end
|
data/lib/shredder/version.rb
DELETED
data/shredder.gemspec
DELETED
@@ -1,55 +0,0 @@
|
|
1
|
-
Gem::Specification.new do |s|
|
2
|
-
|
3
|
-
s.name = 'shredder'
|
4
|
-
s.version = '1.0.0'
|
5
|
-
|
6
|
-
s.homepage = 'https://github.com/carlosjhr64/shredder'
|
7
|
-
|
8
|
-
s.author = 'CarlosJHR64'
|
9
|
-
s.email = 'carlosjhr64@gmail.com'
|
10
|
-
|
11
|
-
s.date = '2014-01-11'
|
12
|
-
s.licenses = ['MIT']
|
13
|
-
|
14
|
-
s.description = <<DESCRIPTION
|
15
|
-
Shred a file into file fragments, and join fragments back into a restored file.
|
16
|
-
|
17
|
-
Disperse file shreds in separate depositories
|
18
|
-
so that no one depository has the entire file.
|
19
|
-
DESCRIPTION
|
20
|
-
|
21
|
-
s.summary = <<SUMMARY
|
22
|
-
Shred a file into file fragments, and join fragments back into a restored file.
|
23
|
-
SUMMARY
|
24
|
-
|
25
|
-
s.extra_rdoc_files = ['README.rdoc']
|
26
|
-
s.rdoc_options = ["--main", "README.rdoc"]
|
27
|
-
|
28
|
-
s.require_paths = ["lib"]
|
29
|
-
s.files = %w(
|
30
|
-
History.txt
|
31
|
-
README.rdoc
|
32
|
-
TODO.txt
|
33
|
-
bin/shredder
|
34
|
-
features/main.feature
|
35
|
-
features/step_definitions/main_steps.rb
|
36
|
-
lib/shredder.rb
|
37
|
-
lib/shredder/files.rb
|
38
|
-
lib/shredder/functions.rb
|
39
|
-
lib/shredder/shredder.rb
|
40
|
-
lib/shredder/streams.rb
|
41
|
-
lib/shredder/version.rb
|
42
|
-
shredder.gemspec
|
43
|
-
test/test_shredder.rb
|
44
|
-
)
|
45
|
-
s.executables << 'shredder'
|
46
|
-
s.add_runtime_dependency 'help_parser', '~> 1.1', '>= 1.1.0'
|
47
|
-
s.add_development_dependency 'test-unit', '~> 2.5', '>= 2.5.5'
|
48
|
-
s.add_development_dependency 'symmetric_gpg', '~> 2.0', '>= 2.0.1'
|
49
|
-
s.requirements << 'ruby: ruby 2.1.0p0 (2013-12-25 revision 44422) [x86_64-linux]'
|
50
|
-
s.requirements << 'bash in development: GNU bash, version 4.2.25(1)-release (x86_64-pc-linux-gnu)'
|
51
|
-
s.requirements << 'system in development: linux/bash'
|
52
|
-
s.requirements << 'rm in development: rm (GNU coreutils) 8.13'
|
53
|
-
s.requirements << 'diff in development: diff (GNU diffutils) 3.2'
|
54
|
-
|
55
|
-
end
|
data/test/test_shredder.rb
DELETED
@@ -1,140 +0,0 @@
|
|
1
|
-
# Standard Libraries
|
2
|
-
require 'stringio'
|
3
|
-
|
4
|
-
# Gems
|
5
|
-
require 'test/unit'
|
6
|
-
begin
|
7
|
-
require 'symmetric_gpg'
|
8
|
-
GPG = true
|
9
|
-
rescue
|
10
|
-
STDERR.puts "Warning: symmetric_gpg not available for testing"
|
11
|
-
GPG = false
|
12
|
-
end
|
13
|
-
|
14
|
-
# This Gem
|
15
|
-
require 'shredder'
|
16
|
-
include SHREDDER
|
17
|
-
|
18
|
-
module TestFunction
|
19
|
-
extend Functions
|
20
|
-
end
|
21
|
-
|
22
|
-
class TestShredder < Test::Unit::TestCase
|
23
|
-
|
24
|
-
def test_version
|
25
|
-
assert_equal '1.0.0', VERSION
|
26
|
-
assert_equal '1.0.0', SHREDDER::VERSION
|
27
|
-
end
|
28
|
-
|
29
|
-
def test_functions_even
|
30
|
-
abc = "abcdefghijklmnopqrstuvwxyz"
|
31
|
-
string = StringIO.new(abc)
|
32
|
-
shred1 = StringIO.new
|
33
|
-
shred2 = StringIO.new
|
34
|
-
TestFunction.shred(string, [shred1, shred2])
|
35
|
-
string.rewind
|
36
|
-
shred1.rewind
|
37
|
-
shred2.rewind
|
38
|
-
l0, l1, l2 = string.length, shred1.length, shred2.length
|
39
|
-
assert_equal(l0, l1 + l2)
|
40
|
-
assert_equal(l1, l2)
|
41
|
-
sewed = StringIO.new
|
42
|
-
TestFunction.sew(sewed, [shred1, shred2])
|
43
|
-
sewed.rewind
|
44
|
-
assert_equal(sewed.read, abc)
|
45
|
-
|
46
|
-
# Note that the xor starts it's seed with the first letter,
|
47
|
-
# so that 'a' in the abc string remains unchanged.
|
48
|
-
# Anyways, the point of the following is to show that the shreds
|
49
|
-
# are no longer easily recognizable as part of the original string.
|
50
|
-
|
51
|
-
shred1.rewind
|
52
|
-
shred = shred1.read
|
53
|
-
assert_nil(shred=~/[b-z]/)
|
54
|
-
|
55
|
-
shred2.rewind
|
56
|
-
shred = shred2.read
|
57
|
-
assert_nil(shred=~/[b-z]/)
|
58
|
-
end
|
59
|
-
|
60
|
-
def test_functions_odd
|
61
|
-
abc = "abcdefghijklmnopqrstuvwxyz+"
|
62
|
-
string = StringIO.new(abc)
|
63
|
-
shred1 = StringIO.new
|
64
|
-
shred2 = StringIO.new
|
65
|
-
TestFunction.shred(string, [shred1, shred2])
|
66
|
-
string.rewind
|
67
|
-
shred1.rewind
|
68
|
-
shred2.rewind
|
69
|
-
l0, l1, l2 = string.length, shred1.length, shred2.length
|
70
|
-
assert_equal(l0, l1 + l2)
|
71
|
-
assert_equal(l1, l2+1)
|
72
|
-
sewed = StringIO.new
|
73
|
-
TestFunction.sew(sewed, [shred1, shred2])
|
74
|
-
sewed.rewind
|
75
|
-
assert_equal(sewed.read, abc)
|
76
|
-
end
|
77
|
-
|
78
|
-
def test_functions_three
|
79
|
-
abc = "abcdefghijklmnopqrstuvwxyz"
|
80
|
-
string = StringIO.new(abc)
|
81
|
-
shred1 = StringIO.new
|
82
|
-
shred2 = StringIO.new
|
83
|
-
shred3 = StringIO.new
|
84
|
-
TestFunction.shred(string, [shred1, shred2, shred3])
|
85
|
-
string.rewind
|
86
|
-
shred1.rewind
|
87
|
-
shred2.rewind
|
88
|
-
shred3.rewind
|
89
|
-
l0, l1, l2, l3 = string.length, shred1.length, shred2.length, shred3.length
|
90
|
-
assert_equal(l0, l1 + l2 + l3)
|
91
|
-
assert(l1>7)
|
92
|
-
assert(l2>7)
|
93
|
-
assert(l3>7)
|
94
|
-
sewed = StringIO.new
|
95
|
-
TestFunction.sew(sewed, [shred1, shred2, shred3])
|
96
|
-
sewed.rewind
|
97
|
-
assert_equal(sewed.read, abc)
|
98
|
-
end
|
99
|
-
|
100
|
-
# Most of the code is tested under cucumber.
|
101
|
-
# Just going to test an untested path.
|
102
|
-
# Shredder.new(...).execute is well tested.
|
103
|
-
# Now test Shredder.new.shred and #sew
|
104
|
-
def test_shredder
|
105
|
-
system('rm ./temp.* 2> /dev/null')
|
106
|
-
refute File.exist? './temp.sewed' # just a quick sanity check
|
107
|
-
system('openssl rand -base64 32 > ./temp.txt')
|
108
|
-
shredder = Shredder.new
|
109
|
-
# ...and just for something a bit different, 4 shreds.
|
110
|
-
shredder.shred('./temp.txt', './temp.1', './temp.2', './temp.3', './temp.4')
|
111
|
-
assert File.exist? './temp.1'
|
112
|
-
assert File.exist? './temp.2'
|
113
|
-
assert File.exist? './temp.3'
|
114
|
-
assert File.exist? './temp.4'
|
115
|
-
shredder.sew('./temp.sewed', './temp.1', './temp.2', './temp.3', './temp.4')
|
116
|
-
assert File.exist? './temp.sewed'
|
117
|
-
# The following will show the two files to be equal
|
118
|
-
assert system 'diff ./temp.txt ./temp.sewed 2> /dev/null'
|
119
|
-
|
120
|
-
system('rm ./temp.*') # cleanup after ourselves
|
121
|
-
end
|
122
|
-
|
123
|
-
def test_symmetric_gpg
|
124
|
-
if GPG
|
125
|
-
system('rm ./temp.* 2> /dev/null')
|
126
|
-
string = "A is for Apple."
|
127
|
-
shreds = SymmetricGPG::Shreds.new("Shreddelicious!", string, ['./temp.1','./temp.2'])
|
128
|
-
shreds.shredder = '/usr/local/bin/ruby -I ./lib ./bin/shredder'
|
129
|
-
shreds.shred # Should encrypt and then shred the string into shred.1 and shred.2.
|
130
|
-
assert File.exist? './temp.1'
|
131
|
-
assert File.exist? './temp.2'
|
132
|
-
shreds.plain = nil # no cheat!
|
133
|
-
plain = shreds.sew # should get the shredded string back.
|
134
|
-
assert_equal string, plain
|
135
|
-
# Cleanup after ourselves
|
136
|
-
system('rm ./temp.* 2> /dev/null')
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
|
-
end
|