russdeep 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +1 -0
- data/{spec/spec.opts → .rspec} +0 -0
- data/History.txt +9 -0
- data/Rakefile +13 -5
- data/VERSION +1 -1
- data/ext/ssdeep_native/ssdeep_native.c +44 -0
- data/lib/ffi/ssdeep.rb +32 -0
- data/lib/russdeep.rb +45 -0
- data/lib/ssdeep.rb +51 -0
- data/spec/fuzzy_comparable_spec.rb +21 -0
- data/spec/spec_helper.rb +1 -2
- metadata +13 -5
data/.document
CHANGED
data/{spec/spec.opts → .rspec}
RENAMED
File without changes
|
data/History.txt
ADDED
data/Rakefile
CHANGED
@@ -16,6 +16,7 @@ begin
|
|
16
16
|
|
17
17
|
if RUBY_PLATFORM !~ /java/
|
18
18
|
gem.extensions = FileList['ext/**/extconf.rb']
|
19
|
+
gem.extra_rdoc_files += FileList['ext/**/*.c']
|
19
20
|
end
|
20
21
|
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
21
22
|
end
|
@@ -24,18 +25,20 @@ rescue LoadError
|
|
24
25
|
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
25
26
|
end
|
26
27
|
|
27
|
-
require '
|
28
|
-
|
29
|
-
spec.
|
30
|
-
spec.spec_files = FileList['spec/ssdeep_spec.rb', 'spec/**/*_spec.rb'].uniq
|
28
|
+
require 'rspec/core/rake_task'
|
29
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
30
|
+
spec.pattern = FileList['spec/ssdeep_spec.rb', 'spec/**/*_spec.rb'].uniq
|
31
31
|
end
|
32
32
|
|
33
33
|
if RUBY_PLATFORM !~ /java/
|
34
34
|
Rake::ExtensionTask.new("ssdeep_native")
|
35
35
|
|
36
|
+
CLEAN.include("doc")
|
37
|
+
CLEAN.include("rdoc")
|
38
|
+
CLEAN.include("coverage")
|
39
|
+
CLEAN.include("tmp")
|
36
40
|
CLEAN.include("lib/*.bundle")
|
37
41
|
CLEAN.include("lib/*.so")
|
38
|
-
CLEAN.include("tmp")
|
39
42
|
|
40
43
|
task :spec => :compile
|
41
44
|
end
|
@@ -53,4 +56,9 @@ Rake::RDocTask.new do |rdoc|
|
|
53
56
|
rdoc.title = "russdeep #{version}"
|
54
57
|
rdoc.rdoc_files.include('README*')
|
55
58
|
rdoc.rdoc_files.include('lib/**/*.rb')
|
59
|
+
rdoc.rdoc_files.include('ext/**/*.c')
|
56
60
|
end
|
61
|
+
|
62
|
+
require 'yard'
|
63
|
+
YARD::Rake::YardocTask.new
|
64
|
+
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.
|
1
|
+
1.1.0
|
@@ -5,6 +5,17 @@
|
|
5
5
|
static VALUE module_Ssdeep = Qnil;
|
6
6
|
static VALUE error_HashError = Qnil;
|
7
7
|
|
8
|
+
/* call-seq: from_string(buf)
|
9
|
+
*
|
10
|
+
* Create a fuzzy hash from a ruby string
|
11
|
+
*
|
12
|
+
* @param String buf The string to hash
|
13
|
+
*
|
14
|
+
* @return String The fuzzy hash of the string
|
15
|
+
*
|
16
|
+
* @raise HashError
|
17
|
+
* An exception is raised if the libfuzzy library encounters an error.
|
18
|
+
*/
|
8
19
|
VALUE ssdeep_from_string(VALUE klass, VALUE buf) {
|
9
20
|
char hash[FUZZY_MAX_RESULT];
|
10
21
|
int ret;
|
@@ -17,6 +28,17 @@ VALUE ssdeep_from_string(VALUE klass, VALUE buf) {
|
|
17
28
|
rb_raise(error_HashError, "An error occurred hashing a string: ret=%i", ret);
|
18
29
|
}
|
19
30
|
|
31
|
+
/* call-seq: from_file(filename)
|
32
|
+
*
|
33
|
+
* Create a fuzzy hash from a file
|
34
|
+
*
|
35
|
+
* @param String fielname The file to read and hash
|
36
|
+
*
|
37
|
+
* @return String The fuzzy hash of the file input
|
38
|
+
*
|
39
|
+
* @raise HashError
|
40
|
+
* An exception is raised if the libfuzzy library encounters an error.
|
41
|
+
*/
|
20
42
|
VALUE ssdeep_from_filename(VALUE klass, VALUE filename) {
|
21
43
|
char hash[FUZZY_MAX_RESULT];
|
22
44
|
int ret;
|
@@ -29,6 +51,17 @@ VALUE ssdeep_from_filename(VALUE klass, VALUE filename) {
|
|
29
51
|
rb_raise(error_HashError, "An error occurred the file: %s -- ret=%i", RSTRING_PTR(filename), ret);
|
30
52
|
}
|
31
53
|
|
54
|
+
/* call-seq: from_fileno(fileno)
|
55
|
+
*
|
56
|
+
* Create a fuzzy hash from a file descriptor fileno
|
57
|
+
*
|
58
|
+
* @param Integer fileno The file descriptor to read and hash
|
59
|
+
*
|
60
|
+
* @return String The fuzzy hash of the file descriptor input
|
61
|
+
*
|
62
|
+
* @raise HashError
|
63
|
+
* An exception is raised if the libfuzzy library encounters an error.
|
64
|
+
*/
|
32
65
|
VALUE ssdeep_from_fileno(VALUE klass, VALUE fileno) {
|
33
66
|
char hash[FUZZY_MAX_RESULT];
|
34
67
|
int ret, fd;
|
@@ -50,6 +83,17 @@ VALUE ssdeep_from_fileno(VALUE klass, VALUE fileno) {
|
|
50
83
|
rb_raise(error_HashError, "An error occurred the fileno: %i -- ret=%i", fd, ret);
|
51
84
|
}
|
52
85
|
|
86
|
+
/* call-seq: compare(sig1, sig2)
|
87
|
+
*
|
88
|
+
* Compare two hashes
|
89
|
+
*
|
90
|
+
* @param String sig1 A fuzzy hash which will be compared to sig2
|
91
|
+
*
|
92
|
+
* @param String sig2 A fuzzy hash which will be compared to sig1
|
93
|
+
*
|
94
|
+
* @return Integer
|
95
|
+
* A value between 0 and 100 indicating the percentage of similarity.
|
96
|
+
*/
|
53
97
|
VALUE ssdeep_compare(VALUE klass, VALUE sig1, VALUE sig2) {
|
54
98
|
int ret;
|
55
99
|
|
data/lib/ffi/ssdeep.rb
CHANGED
@@ -27,6 +27,14 @@ module Ssdeep
|
|
27
27
|
attach_function :fdopen, [:int, :string], :pointer
|
28
28
|
|
29
29
|
|
30
|
+
# Create a fuzzy hash from a ruby string
|
31
|
+
#
|
32
|
+
# @param String buf The string to hash
|
33
|
+
#
|
34
|
+
# @return String The fuzzy hash of the string
|
35
|
+
#
|
36
|
+
# @raise HashError
|
37
|
+
# An exception is raised if the libfuzzy library encounters an error.
|
30
38
|
def self.from_string(buf)
|
31
39
|
bufp = FFI::MemoryPointer.new(buf.size)
|
32
40
|
bufp.write_string(buf)
|
@@ -40,6 +48,14 @@ module Ssdeep
|
|
40
48
|
end
|
41
49
|
end
|
42
50
|
|
51
|
+
# Create a fuzzy hash from a file descriptor fileno
|
52
|
+
#
|
53
|
+
# @param Integer fileno The file descriptor to read and hash
|
54
|
+
#
|
55
|
+
# @return String The fuzzy hash of the file descriptor input
|
56
|
+
#
|
57
|
+
# @raise HashError
|
58
|
+
# An exception is raised if the libfuzzy library encounters an error.
|
43
59
|
def self.from_fileno(fileno)
|
44
60
|
if (not fileno.kind_of?(Integer)) or (file=fdopen(fileno, "r")).null?
|
45
61
|
raise(HashError, "Unable to open file descriptor: #{fileno}")
|
@@ -54,6 +70,14 @@ module Ssdeep
|
|
54
70
|
end
|
55
71
|
end
|
56
72
|
|
73
|
+
# Create a fuzzy hash from a file
|
74
|
+
#
|
75
|
+
# @param String fielname The file to read and hash
|
76
|
+
#
|
77
|
+
# @return String The fuzzy hash of the file input
|
78
|
+
#
|
79
|
+
# @raise HashError
|
80
|
+
# An exception is raised if the libfuzzy library encounters an error.
|
57
81
|
def self.from_file(filename)
|
58
82
|
File.stat(filename)
|
59
83
|
out = FFI::MemoryPointer.new(FUZZY_MAX_RESULT)
|
@@ -65,6 +89,14 @@ module Ssdeep
|
|
65
89
|
end
|
66
90
|
end
|
67
91
|
|
92
|
+
# Compare two hashes
|
93
|
+
#
|
94
|
+
# @param String sig1 A fuzzy hash which will be compared to sig2
|
95
|
+
#
|
96
|
+
# @param String sig2 A fuzzy hash which will be compared to sig1
|
97
|
+
#
|
98
|
+
# @return Integer
|
99
|
+
# A value between 0 and 100 indicating the percentage of similarity.
|
68
100
|
def self.compare(sig1, sig2)
|
69
101
|
psig1 = FFI::MemoryPointer.from_string(sig1)
|
70
102
|
psig2 = FFI::MemoryPointer.from_string(sig2)
|
data/lib/russdeep.rb
CHANGED
@@ -1,3 +1,48 @@
|
|
1
1
|
require 'ssdeep'
|
2
2
|
|
3
|
+
|
4
|
+
module Ssdeep
|
5
|
+
# The FuzzyComparable module adds mixins for doing fuzzy hash comparisons.
|
6
|
+
# The object extending must simply implement the 'ssdeep' method, which
|
7
|
+
# should return a string containing a fuzzy CTPH hash.
|
8
|
+
module FuzzyComparable
|
9
|
+
# Returns a CTPH comparison score between this object and another's
|
10
|
+
# fuzzy hash.
|
11
|
+
#
|
12
|
+
# @param String,Object other
|
13
|
+
# The hash string or other object to compare to. If other is not
|
14
|
+
# a string, it just needs to implement the 'ssdeep' method.
|
15
|
+
#
|
16
|
+
def fuzzy_score(other)
|
17
|
+
other_hash=
|
18
|
+
if other.is_a? String
|
19
|
+
other
|
20
|
+
elsif other.respond_to? :ssdeep
|
21
|
+
other.ssdeep
|
22
|
+
else
|
23
|
+
raise(TypeError, "can't handle type for other: #{other.class}")
|
24
|
+
end
|
25
|
+
|
26
|
+
Ssdeep.compare(self.ssdeep, other_hash)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Returns true/false whether the sample matches a CTPH (fuzzy hash)
|
30
|
+
# with a score above a specified threshold
|
31
|
+
#
|
32
|
+
# @param String,Object other
|
33
|
+
# The hash string or other object to compare to. If other is not
|
34
|
+
# a string, it just needs to implement the 'ssdeep' method.
|
35
|
+
#
|
36
|
+
# @param Integer threshold
|
37
|
+
# The theshold above-which a match is considered true. If a threshold
|
38
|
+
# is supplied above 100, it is treated as 100.
|
39
|
+
#
|
40
|
+
# @return true,false
|
41
|
+
# Whether a match occurred.
|
42
|
+
def fuzzy_match(other, threshold=25)
|
43
|
+
return (fuzzy_score(other) >= [threshold, 100].min)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
3
48
|
RuSsdeep = Ssdeep
|
data/lib/ssdeep.rb
CHANGED
@@ -5,3 +5,54 @@ else
|
|
5
5
|
require 'ssdeep_native'
|
6
6
|
end
|
7
7
|
|
8
|
+
module Ssdeep
|
9
|
+
# The FuzzyComparable module adds mixins for doing fuzzy hash comparisons.
|
10
|
+
# To mix in the module your object must simply implement the 'ssdeep'
|
11
|
+
# method, which should return a string containing a fuzzy CTPH hash.
|
12
|
+
module FuzzyComparable
|
13
|
+
# Returns a CTPH comparison score between this object and another's
|
14
|
+
# fuzzy hash.
|
15
|
+
#
|
16
|
+
# @param String,Object other
|
17
|
+
# The hash string or other object to compare to. If other is not
|
18
|
+
# a string, it just needs to implement the 'ssdeep' method.
|
19
|
+
#
|
20
|
+
def fuzzy_score(other)
|
21
|
+
other_hash=
|
22
|
+
if other.is_a? String
|
23
|
+
other
|
24
|
+
elsif other.respond_to? :ssdeep
|
25
|
+
other.ssdeep
|
26
|
+
else
|
27
|
+
raise(TypeError, "can't handle type for other: #{other.class}")
|
28
|
+
end
|
29
|
+
|
30
|
+
Ssdeep.compare(self.ssdeep, other_hash)
|
31
|
+
end
|
32
|
+
|
33
|
+
# Returns true/false whether the sample matches a CTPH (fuzzy hash)
|
34
|
+
# with a score above a specified threshold
|
35
|
+
#
|
36
|
+
# @param String,Object other
|
37
|
+
# The hash string or other object to compare to. If other is not
|
38
|
+
# a string, it just needs to implement the 'ssdeep' method.
|
39
|
+
#
|
40
|
+
# @param Integer threshold
|
41
|
+
# The theshold above-which a match is considered true. If a threshold
|
42
|
+
# is supplied above 100, it is treated as 100.
|
43
|
+
#
|
44
|
+
# @return true,false
|
45
|
+
# Whether a match occurred.
|
46
|
+
def fuzzy_match(other, threshold=25)
|
47
|
+
return (fuzzy_score(other) >= [threshold, 100].min)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
class << self
|
52
|
+
alias :hash_string :from_string
|
53
|
+
alias :hash_file :from_file
|
54
|
+
alias :hash_fileno :from_fileno
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
require 'ssdeep'
|
3
|
+
|
4
|
+
class TestFuzzyComparable
|
5
|
+
include Ssdeep::FuzzyComparable
|
6
|
+
|
7
|
+
def ssdeep
|
8
|
+
'96:tQWAFF4IMtG6z4FEmYqGPUyukJM4kbqkTKL+LGw6b8f/EZMhJvybtSryfubB:tO4a68FZYqyG4w2+Bbzhpybg6u9'
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
describe Ssdeep::FuzzyComparable do
|
13
|
+
before :all do
|
14
|
+
@obj = TestFuzzyComparable.new
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should compare itself to another fuzzy hash string" do
|
18
|
+
@obj.fuzzy_score(Ssdeep.from_file sample_file("sample1.txt")).should == 100
|
19
|
+
@obj.fuzzy_match(Ssdeep.from_file sample_file("sample1.txt")).should be_true
|
20
|
+
end
|
21
|
+
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 1
|
7
|
+
- 1
|
7
8
|
- 0
|
8
|
-
|
9
|
-
version: 1.0.0
|
9
|
+
version: 1.1.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Eric Monti
|
@@ -14,13 +14,14 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2011-
|
17
|
+
date: 2011-03-22 00:00:00 -05:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: rspec
|
22
22
|
prerelease: false
|
23
23
|
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
24
25
|
requirements:
|
25
26
|
- - ">="
|
26
27
|
- !ruby/object:Gem::Version
|
@@ -35,6 +36,7 @@ dependencies:
|
|
35
36
|
name: ffi
|
36
37
|
prerelease: false
|
37
38
|
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
38
40
|
requirements:
|
39
41
|
- - ">="
|
40
42
|
- !ruby/object:Gem::Version
|
@@ -52,8 +54,11 @@ extensions:
|
|
52
54
|
extra_rdoc_files:
|
53
55
|
- LICENSE
|
54
56
|
- README.rdoc
|
57
|
+
- ext/ssdeep_native/ssdeep_native.c
|
55
58
|
files:
|
56
59
|
- .document
|
60
|
+
- .rspec
|
61
|
+
- History.txt
|
57
62
|
- LICENSE
|
58
63
|
- README.rdoc
|
59
64
|
- Rakefile
|
@@ -65,9 +70,9 @@ files:
|
|
65
70
|
- lib/ssdeep.rb
|
66
71
|
- lib/ssdeep_ffi.rb
|
67
72
|
- spec/ffi_ssdeep_spec.rb
|
73
|
+
- spec/fuzzy_comparable_spec.rb
|
68
74
|
- spec/samples/sample1.txt
|
69
75
|
- spec/samples/sample2.txt
|
70
|
-
- spec/spec.opts
|
71
76
|
- spec/spec_helper.rb
|
72
77
|
- spec/ssdeep_behaviors.rb
|
73
78
|
- spec/ssdeep_spec.rb
|
@@ -81,6 +86,7 @@ rdoc_options: []
|
|
81
86
|
require_paths:
|
82
87
|
- lib
|
83
88
|
required_ruby_version: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
84
90
|
requirements:
|
85
91
|
- - ">="
|
86
92
|
- !ruby/object:Gem::Version
|
@@ -88,6 +94,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
88
94
|
- 0
|
89
95
|
version: "0"
|
90
96
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
91
98
|
requirements:
|
92
99
|
- - ">="
|
93
100
|
- !ruby/object:Gem::Version
|
@@ -97,12 +104,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
97
104
|
requirements: []
|
98
105
|
|
99
106
|
rubyforge_project:
|
100
|
-
rubygems_version: 1.3.
|
107
|
+
rubygems_version: 1.3.7
|
101
108
|
signing_key:
|
102
109
|
specification_version: 3
|
103
110
|
summary: Ruby bindings for libfuzzy (from ssdeep)
|
104
111
|
test_files:
|
105
112
|
- spec/ffi_ssdeep_spec.rb
|
113
|
+
- spec/fuzzy_comparable_spec.rb
|
106
114
|
- spec/spec_helper.rb
|
107
115
|
- spec/ssdeep_behaviors.rb
|
108
116
|
- spec/ssdeep_spec.rb
|