stribog 0.1.3 → 0.2.0
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 +4 -4
- data/.rubocop.yml +2 -2
- data/README.rdoc +6 -2
- data/lib/stribog.rb +14 -2
- data/lib/stribog/byte_vector.rb +96 -0
- data/lib/stribog/{compression.rb → compression_func.rb} +17 -20
- data/lib/stribog/create_hash.rb +14 -115
- data/lib/stribog/digest.rb +20 -5
- data/lib/stribog/hash_params.rb +12 -12
- data/lib/stribog/stage/base.rb +62 -0
- data/lib/stribog/stage/compression.rb +53 -0
- data/lib/stribog/stage/final.rb +37 -0
- data/lib/stribog/stage/initial.rb +47 -0
- data/lib/stribog/version.rb +1 -1
- data/stribog.gemspec +1 -1
- metadata +11 -7
- data/lib/stribog/binary_vector.rb +0 -105
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 81cda8678e16f6f25d1cc99e89c31cae61c7e389
|
4
|
+
data.tar.gz: 414fe5e18f7909b12649582b18d4b0af7bb2cfcc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cdb8f9ff439e21593f0cc918e37141c0f2d31cca11123f61a257c313be5e86fb0d609bb6154334d2273f191eb14c3dac500c3192dd672b0c5d40f879b1e0145c
|
7
|
+
data.tar.gz: a53ade4b91a890313fedc0f0682f9a9888a0c181fe860effb3b7d854d1c5116234f2b79773d48293b26f8f5602183c27632863601aea4bdec603c5923d6f9f63
|
data/.rubocop.yml
CHANGED
data/README.rdoc
CHANGED
@@ -28,10 +28,14 @@ Or install it yourself as:
|
|
28
28
|
hash = Stribog::CreateHash.new('ruby')
|
29
29
|
|
30
30
|
# for 256 bit
|
31
|
-
hash.(256).
|
31
|
+
hash.(256).hex #=> "cde7864b760a690f4ec24ffe5c66bd2c00db843e9cf1b82b6c467dba5a7846a7"
|
32
|
+
hash.(256).base64
|
33
|
+
hash.(256).pack
|
32
34
|
|
33
35
|
# for 512 bit
|
34
|
-
hash.(512).
|
36
|
+
hash.(512).hex #=> "f0dafc0703f801d1ecbe7ff246808d07507f67879eaacf887ba041336fd51e0a964f00470ed0eedb0378a39e019eb308876ea8c84bb89e2c35159fb6dbbdc598"
|
37
|
+
hash.(512).base64
|
38
|
+
hash.(512).pack
|
35
39
|
|
36
40
|
=== Contributing
|
37
41
|
|
data/lib/stribog.rb
CHANGED
@@ -1,11 +1,23 @@
|
|
1
1
|
require 'stribog/version'
|
2
|
+
# require 'pry'
|
3
|
+
# require 'pry-byebug'
|
2
4
|
# Stribog gost
|
3
5
|
#
|
4
6
|
# @author WildDima
|
5
7
|
module Stribog
|
6
8
|
require_relative './stribog/create_hash'
|
7
9
|
require_relative './stribog/hash_params'
|
8
|
-
require_relative './stribog/
|
9
|
-
require_relative './stribog/binary_vector'
|
10
|
+
require_relative './stribog/compression_func'
|
10
11
|
require_relative './stribog/digest'
|
12
|
+
require_relative './stribog/byte_vector'
|
13
|
+
require_relative './stribog/stage/base'
|
14
|
+
require_relative './stribog/stage/initial'
|
15
|
+
require_relative './stribog/stage/compression'
|
16
|
+
require_relative './stribog/stage/final'
|
17
|
+
|
18
|
+
HASH_LENGTH = 512
|
19
|
+
|
20
|
+
def self.vector
|
21
|
+
ByteVector
|
22
|
+
end
|
11
23
|
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
module Stribog
|
2
|
+
# byte_array
|
3
|
+
#
|
4
|
+
# @author WildDima
|
5
|
+
class ByteVector
|
6
|
+
include Enumerable
|
7
|
+
|
8
|
+
attr_reader :vector
|
9
|
+
|
10
|
+
def self.convert(vector)
|
11
|
+
case vector
|
12
|
+
when String
|
13
|
+
new(vector.unpack('C*'))
|
14
|
+
when Numeric
|
15
|
+
# TODO: REFACTOR
|
16
|
+
bin = vector.to_s(2)
|
17
|
+
size = 2**Math.log2(vector.size * 8).ceil
|
18
|
+
new(['0' * (size - bin.size) + bin].pack('B*').unpack('C*'))
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def initialize(vector)
|
23
|
+
@vector = vector
|
24
|
+
end
|
25
|
+
|
26
|
+
def ^(other)
|
27
|
+
vec = [other, self].sort_by(&:size).reverse.map(&:reverse)
|
28
|
+
self.class.new vec[0].map
|
29
|
+
.with_index { |bit, index| bit ^ (vec[1][index] || 0) }.reverse
|
30
|
+
end
|
31
|
+
|
32
|
+
def +(other)
|
33
|
+
self.class.new vector + other.to_a
|
34
|
+
end
|
35
|
+
|
36
|
+
def addition(size: 64)
|
37
|
+
return self if vector.size >= size
|
38
|
+
self.class.new(Array.new(size - vector.size, 0) + vector)
|
39
|
+
end
|
40
|
+
|
41
|
+
def padding(size: 64)
|
42
|
+
return self if vector.size >= size
|
43
|
+
# (self.class.new([1]) + vector).addition_by_zeros(size: 512)
|
44
|
+
self.class.new([1] + vector).addition(size: size)
|
45
|
+
end
|
46
|
+
|
47
|
+
def byte8
|
48
|
+
@byte8 ||= vector.pack('C*').unpack('Q*')
|
49
|
+
end
|
50
|
+
|
51
|
+
def bit64
|
52
|
+
@bit64 ||= byte8.map { |b| [b].pack('Q*').unpack('B*') }.flatten
|
53
|
+
end
|
54
|
+
|
55
|
+
def to_dec
|
56
|
+
# to_s.to_i(2)
|
57
|
+
vector.pack('C*').unpack('B*').first.to_i(2)
|
58
|
+
end
|
59
|
+
|
60
|
+
def to_hex
|
61
|
+
to_s.to_i(2).to_s(16)
|
62
|
+
end
|
63
|
+
|
64
|
+
def to_s
|
65
|
+
# vector.pack('C*')
|
66
|
+
vector
|
67
|
+
end
|
68
|
+
|
69
|
+
def size
|
70
|
+
@size ||= vector.size
|
71
|
+
end
|
72
|
+
|
73
|
+
def [](index)
|
74
|
+
vector[index]
|
75
|
+
end
|
76
|
+
|
77
|
+
def each
|
78
|
+
return vector.each unless block_given?
|
79
|
+
vector.each do |v|
|
80
|
+
yield(v)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def to_a
|
85
|
+
vector
|
86
|
+
end
|
87
|
+
|
88
|
+
def zero?
|
89
|
+
vector.any?(&:zero?)
|
90
|
+
end
|
91
|
+
|
92
|
+
def reverse
|
93
|
+
self.class.new vector.reverse
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -3,7 +3,7 @@ module Stribog
|
|
3
3
|
#
|
4
4
|
# Class implements compression function of GOST R 34.11-2012 algorithm.
|
5
5
|
# @author WildDima
|
6
|
-
class
|
6
|
+
class CompressionFunc
|
7
7
|
include HashParams
|
8
8
|
|
9
9
|
def initialize(n, message, hash_vector)
|
@@ -32,36 +32,34 @@ module Stribog
|
|
32
32
|
end
|
33
33
|
|
34
34
|
def replacement_pi(vector)
|
35
|
-
|
36
|
-
.map { |byte| PI[byte] }
|
35
|
+
ByteVector.new vector.map { |byte| PI[byte] }
|
37
36
|
end
|
38
37
|
|
39
38
|
# rubocop:disable Style/EachWithObject
|
40
39
|
def permutation_t(vector)
|
41
|
-
|
42
|
-
vector.
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
end
|
40
|
+
ByteVector.new(
|
41
|
+
vector.each.with_index.inject([]) do |b_arr, (byte, index)|
|
42
|
+
b_arr[T[index]] = byte
|
43
|
+
b_arr
|
44
|
+
end.map(&:to_i)
|
47
45
|
)
|
48
46
|
end
|
49
47
|
# rubocop:enable Style/EachWithObject
|
50
48
|
|
51
49
|
def linear_transformation(vector)
|
52
|
-
|
53
|
-
vector.
|
54
|
-
small_linear_transformation(
|
55
|
-
end
|
56
|
-
size: 64
|
50
|
+
ByteVector.new(
|
51
|
+
vector.bit64.map do |byte8|
|
52
|
+
small_linear_transformation(byte8)
|
53
|
+
end.flatten
|
57
54
|
)
|
58
55
|
end
|
59
56
|
|
60
57
|
def small_linear_transformation(vector)
|
61
|
-
|
58
|
+
# REFACTOR
|
59
|
+
ByteVector.convert(
|
62
60
|
not_zeros_indexes(vector)
|
63
61
|
.inject(0) { |acc, elem| acc ^ MATRIX_A[elem] }
|
64
|
-
).
|
62
|
+
).to_a
|
65
63
|
end
|
66
64
|
|
67
65
|
# rubocop:disable Style/EachWithObject
|
@@ -70,8 +68,7 @@ module Stribog
|
|
70
68
|
.inject(v1: first_vector.dup,
|
71
69
|
v2: second_vector.dup) do |vs, const|
|
72
70
|
vs[:v2] = lpsx_func(vs[:v1], vs[:v2])
|
73
|
-
vs[:v1] = lpsx_func(vs[:v1],
|
74
|
-
size: 512))
|
71
|
+
vs[:v1] = lpsx_func(vs[:v1], ByteVector.convert(const))
|
75
72
|
vs
|
76
73
|
end
|
77
74
|
vectors[:v1] ^ vectors[:v2]
|
@@ -79,8 +76,8 @@ module Stribog
|
|
79
76
|
# rubocop:enable Style/EachWithObject
|
80
77
|
|
81
78
|
def not_zeros_indexes(vector)
|
82
|
-
vector.map.with_index do |bit, index|
|
83
|
-
next if bit
|
79
|
+
vector.chars.map.with_index do |bit, index|
|
80
|
+
next if bit == '0'
|
84
81
|
index
|
85
82
|
end.compact
|
86
83
|
end
|
data/lib/stribog/create_hash.rb
CHANGED
@@ -27,11 +27,12 @@ module Stribog
|
|
27
27
|
# digest.message_vector
|
28
28
|
# @return [BinaryVector] binary representation of message
|
29
29
|
attr_reader :message_vector
|
30
|
+
attr_reader :vector
|
30
31
|
|
31
|
-
|
32
|
-
|
33
|
-
def initialize(message)
|
32
|
+
def initialize(message, transformation = :from_hex, vector = Stribog.vector)
|
34
33
|
@message = message
|
34
|
+
@transformation = transformation
|
35
|
+
@vector = vector
|
35
36
|
end
|
36
37
|
|
37
38
|
# Create digest of {#message}. Default equal to 512.
|
@@ -41,140 +42,38 @@ module Stribog
|
|
41
42
|
# Stribog::CreateHash.new('ruby').call(512)
|
42
43
|
# @author WildDima
|
43
44
|
def call(digest_length = HASH_LENGTH)
|
44
|
-
|
45
|
-
|
45
|
+
@digest_length = digest_length
|
46
46
|
return_hash(
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
sum: @sum,
|
51
|
-
n: @n,
|
52
|
-
message_vector: message_vector,
|
53
|
-
hash_vector: @hash_vector
|
54
|
-
)
|
47
|
+
Stage::Final.new(
|
48
|
+
Stage::Compression.new(
|
49
|
+
Stage::Initial.new(self)
|
55
50
|
)
|
56
|
-
)
|
51
|
+
).call
|
57
52
|
)
|
58
53
|
end
|
59
54
|
|
60
55
|
private
|
61
56
|
|
62
|
-
# Create instance vars for hashing
|
63
|
-
def prepare_hash_params!(digest_length:)
|
64
|
-
@n = binary_vector_field_by
|
65
|
-
@sum = binary_vector_field_by
|
66
|
-
@digest_length = digest_length
|
67
|
-
@hash_vector = create_hash_vector
|
68
|
-
@message_vector = binary_vector.from_hex(message)
|
69
|
-
end
|
70
|
-
|
71
|
-
# Create hash_vector for hashing
|
72
|
-
def create_hash_vector
|
73
|
-
case digest_length
|
74
|
-
when 512
|
75
|
-
binary_vector_field_by(size: 512)
|
76
|
-
when 256
|
77
|
-
binary_vector_from_array(Array.new(64, '00000001').join.chars.map(&:to_i))
|
78
|
-
else
|
79
|
-
raise ArgumentError,
|
80
|
-
"digest length must be equal to 256 or 512, not #{digest_length}"
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
# Method, which slices longer messages, and hashings them by parts.
|
85
|
-
def compact_message(sum:, n:, message_vector:, hash_vector:, message_head: nil)
|
86
|
-
current_vector = message_head || message_vector
|
87
|
-
if current_vector.size < HASH_LENGTH
|
88
|
-
return { sum: sum, n: n, message_vector: current_vector,
|
89
|
-
hash_vector: hash_vector }
|
90
|
-
end
|
91
|
-
|
92
|
-
compact_message(
|
93
|
-
sum: addition_in_ring_to_binary(sum.to_dec, current_vector.to_dec),
|
94
|
-
n: addition_in_ring_to_binary(n.to_dec, slice_message_tail(current_vector).size),
|
95
|
-
message_vector: message_vector,
|
96
|
-
hash_vector: compress(n: n, message: slice_message_tail(current_vector),
|
97
|
-
hash_vector: hash_vector),
|
98
|
-
message_head: slice_message_head(current_vector)
|
99
|
-
)
|
100
|
-
end
|
101
|
-
|
102
|
-
# Method, which slices head of message
|
103
|
-
def slice_message_head(message_vector)
|
104
|
-
binary_vector_from_array(message_vector.vector[0...-HASH_LENGTH])
|
105
|
-
end
|
106
|
-
|
107
|
-
# Method, which slices head of tail
|
108
|
-
def slice_message_tail(message_vector)
|
109
|
-
binary_vector_from_array(message_vector.vector[-HASH_LENGTH..-1])
|
110
|
-
end
|
111
|
-
|
112
|
-
# Method, which implements main hashing
|
113
|
-
def core_hashing(sum:, n:, message_vector:, hash_vector:)
|
114
|
-
new_sum = addition_in_ring_to_binary(sum.to_dec,
|
115
|
-
message_vector
|
116
|
-
.addition_bit_padding(size: HASH_LENGTH)
|
117
|
-
.to_dec)
|
118
|
-
|
119
|
-
new_n = addition_in_ring_to_binary(n.to_dec, message_vector.size)
|
120
|
-
|
121
|
-
new_hash_vector = compress(n: n.addition_by_zeros(size: HASH_LENGTH),
|
122
|
-
message: message_vector.addition_bit_padding(size: HASH_LENGTH),
|
123
|
-
hash_vector: hash_vector)
|
124
|
-
|
125
|
-
{ sum: new_sum, n: new_n, hash_vector: new_hash_vector }
|
126
|
-
end
|
127
|
-
|
128
|
-
# Method, which implements final compression
|
129
|
-
def final_compression(sum:, n:, hash_vector:)
|
130
|
-
compress(message: sum, hash_vector: compress(message: n, hash_vector: hash_vector))
|
131
|
-
end
|
132
|
-
|
133
57
|
# Method, which return digest, dependent on them length
|
134
58
|
def return_hash(final_vector)
|
135
59
|
case digest_length
|
136
60
|
when 512
|
137
61
|
create_digest(final_vector)
|
138
62
|
when 256
|
139
|
-
create_digest(
|
63
|
+
create_digest(vector_from_array(final_vector[0..31]))
|
140
64
|
else
|
141
65
|
raise ArgumentError,
|
142
66
|
"digest length must be equal to 256 or 512, not #{digest_length}"
|
143
67
|
end
|
144
68
|
end
|
145
69
|
|
146
|
-
|
147
|
-
|
148
|
-
(first + second) % ring
|
149
|
-
end
|
150
|
-
|
151
|
-
# Method implements addition in ring and creates binary vector
|
152
|
-
def addition_in_ring_to_binary(first, second, ring = 2**HASH_LENGTH, size: HASH_LENGTH)
|
153
|
-
binary_vector.from_byte(addition_in_ring(first, second, ring), size: size)
|
154
|
-
end
|
155
|
-
|
156
|
-
# Compression method
|
157
|
-
def compress(message:, hash_vector:, n: binary_vector_field_by)
|
158
|
-
Compression.new(n, message, hash_vector).call
|
159
|
-
end
|
160
|
-
|
161
|
-
# Method creates binary vector from array
|
162
|
-
def binary_vector_from_array(vector)
|
163
|
-
binary_vector.new(vector)
|
164
|
-
end
|
165
|
-
|
166
|
-
# Method creates binary vector and fields it by passed values
|
167
|
-
def binary_vector_field_by(size: HASH_LENGTH, value: 0)
|
168
|
-
binary_vector_from_array(Array.new(size, value))
|
70
|
+
def vector_from_array(v)
|
71
|
+
vector.new(v)
|
169
72
|
end
|
170
73
|
|
171
74
|
# Create new instance of Digest
|
172
|
-
def create_digest(
|
173
|
-
digest.new(
|
174
|
-
end
|
175
|
-
|
176
|
-
def binary_vector
|
177
|
-
@binary_vector ||= BinaryVector
|
75
|
+
def create_digest(vector)
|
76
|
+
digest.new(vector: vector)
|
178
77
|
end
|
179
78
|
|
180
79
|
def digest
|
data/lib/stribog/digest.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'base64'
|
2
|
+
|
1
3
|
module Stribog
|
2
4
|
# Digest
|
3
5
|
#
|
@@ -12,18 +14,31 @@ module Stribog
|
|
12
14
|
# @example
|
13
15
|
# digest.binary
|
14
16
|
# @return [Array] binary representation of digest
|
15
|
-
attr_reader :
|
17
|
+
attr_reader :vector
|
18
|
+
attr_reader :dec
|
16
19
|
# Contains hex value of hash
|
17
20
|
#
|
18
21
|
# @api public
|
19
22
|
# @example
|
20
23
|
# digest.hex
|
21
24
|
# @return [String] hex representation of digest
|
22
|
-
attr_reader :hex
|
23
25
|
|
24
|
-
def initialize(
|
25
|
-
@
|
26
|
-
@
|
26
|
+
def initialize(vector:)
|
27
|
+
@vector = vector
|
28
|
+
@dec = vector.to_dec
|
29
|
+
end
|
30
|
+
|
31
|
+
def hex
|
32
|
+
dec.to_s(16)
|
33
|
+
end
|
34
|
+
alias to_hex hex
|
35
|
+
|
36
|
+
def base64
|
37
|
+
Base64.encode64(dec.to_s)
|
38
|
+
end
|
39
|
+
|
40
|
+
def pack(meaning = 'C*')
|
41
|
+
binary.to_byte_array.pack(meaning)
|
27
42
|
end
|
28
43
|
end
|
29
44
|
end
|
data/lib/stribog/hash_params.rb
CHANGED
@@ -38,17 +38,17 @@ module Stribog
|
|
38
38
|
0x70a6a56e2440598e, 0x3853dc371220a247, 0x1ca76e95091051ad, 0x0edd37c48a08a6d8,
|
39
39
|
0x07e095624504536c, 0x8d70c431ac02a736, 0xc83862965601dd1b, 0x641c314b2b8ee083].freeze
|
40
40
|
|
41
|
-
CONSTANTS_C =
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
41
|
+
CONSTANTS_C = [0xb1085bda1ecadae9ebcb2f81c0657c1f2f6a76432e45d016714eb88d7585c4fc4b7ce09192676901a2422a08a460d31505767436cc744d23dd806559f2a64507,
|
42
|
+
0x6fa3b58aa99d2f1a4fe39d460f70b5d7f3feea720a232b9861d55e0f16b501319ab5176b12d699585cb561c2db0aa7ca55dda21bd7cbcd56e679047021b19bb7,
|
43
|
+
0xf574dcac2bce2fc70a39fc286a3d843506f15e5f529c1f8bf2ea7514b1297b7bd3e20fe490359eb1c1c93a376062db09c2b6f443867adb31991e96f50aba0ab2,
|
44
|
+
0xef1fdfb3e81566d2f948e1a05d71e4dd488e857e335c3c7d9d721cad685e353fa9d72c82ed03d675d8b71333935203be3453eaa193e837f1220cbebc84e3d12e,
|
45
|
+
0x4bea6bacad4747999a3f410c6ca923637f151c1f1686104a359e35d7800fffbdbfcd1747253af5a3dfff00b723271a167a56a27ea9ea63f5601758fd7c6cfe57,
|
46
|
+
0xae4faeae1d3ad3d96fa4c33b7a3039c02d66c4f95142a46c187f9ab49af08ec6cffaa6b71c9ab7b40af21f66c2bec6b6bf71c57236904f35fa68407a46647d6e,
|
47
|
+
0xf4c70e16eeaac5ec51ac86febf240954399ec6c7e6bf87c9d3473e33197a93c90992abc52d822c3706476983284a05043517454ca23c4af38886564d3a14d493,
|
48
|
+
0x9b1f5b424d93c9a703e7aa020c6e41414eb7f8719c36de1e89b4443b4ddbc49af4892bcb929b069069d18d2bd1a5c42f36acc2355951a8d9a47f0dd4bf02e71e,
|
49
|
+
0x378f5a541631229b944c9ad8ec165fde3a7d3a1b258942243cd955b7e00d0984800a440bdbb2ceb17b2b8a9aa6079c540e38dc92cb1f2a607261445183235adb,
|
50
|
+
0xabbedea680056f52382ae548b2e4f3f38941e71cff8a78db1fffe18a1b3361039fe76702af69334b7a1e6c303b7652f43698fad1153bb6c374b4c7fb98459ced,
|
51
|
+
0x7bcd9ed0efc889fb3002c6cd635afe94d8fa6bbbebab076120018021148466798a1d71efea48b9caefbacd1d7d476e98dea2594ac06fd85d6bcaa4cd81f32d1b,
|
52
|
+
0x378ee767f11631bad21380b00449b17acda43c32bcdf1d77f82012d430219f9b5d80ef9d1891cc86e71da4aa88e12852faf417d5d9b21b9948bc924af11bd720].freeze
|
53
53
|
end
|
54
54
|
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module Stribog
|
2
|
+
# Stage
|
3
|
+
#
|
4
|
+
# @author WildDima
|
5
|
+
module Stage
|
6
|
+
# Base
|
7
|
+
#
|
8
|
+
# @author WildDima
|
9
|
+
class Base
|
10
|
+
attr_reader :prev_stage
|
11
|
+
attr_reader :vector
|
12
|
+
attr_accessor :n
|
13
|
+
attr_accessor :sum
|
14
|
+
attr_accessor :digest_length
|
15
|
+
attr_accessor :hash_vector
|
16
|
+
attr_accessor :message_vector
|
17
|
+
attr_accessor :message_head
|
18
|
+
attr_accessor :current_vector
|
19
|
+
|
20
|
+
def initialize(prev_stage, vector = Stribog.vector)
|
21
|
+
@prev_stage = prev_stage
|
22
|
+
@vector = vector
|
23
|
+
end
|
24
|
+
|
25
|
+
def call
|
26
|
+
raise NotImplementedYet
|
27
|
+
end
|
28
|
+
|
29
|
+
protected
|
30
|
+
|
31
|
+
def prev_stage_call
|
32
|
+
@prev_stage_call ||= prev_stage.call
|
33
|
+
end
|
34
|
+
|
35
|
+
def field_vector(value:, size: 64)
|
36
|
+
vector.new(Array.new(size, value))
|
37
|
+
end
|
38
|
+
|
39
|
+
def empty_vector(size: 64)
|
40
|
+
field_vector(value: 0, size: size)
|
41
|
+
end
|
42
|
+
|
43
|
+
def slice_message_head(message_vector)
|
44
|
+
vector.new(message_vector.vector[0...-HASH_LENGTH / 8])
|
45
|
+
end
|
46
|
+
|
47
|
+
# Method, which slices head of tail
|
48
|
+
def slice_message_tail(message_vector)
|
49
|
+
vector.new(message_vector.vector[-HASH_LENGTH / 8..-1])
|
50
|
+
end
|
51
|
+
|
52
|
+
# Compression method
|
53
|
+
def compress(message:, hash_vector:, n: empty_vector)
|
54
|
+
CompressionFunc.new(n, message, hash_vector).call
|
55
|
+
end
|
56
|
+
|
57
|
+
def addition_in_ring(first, second, ring = 2**HASH_LENGTH)
|
58
|
+
vector.convert((first + second) % ring)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Stribog
|
2
|
+
# BinaryVector
|
3
|
+
#
|
4
|
+
# @author WildDima
|
5
|
+
module Stage
|
6
|
+
# Compression
|
7
|
+
#
|
8
|
+
# @author WildDima
|
9
|
+
class Compression < Base
|
10
|
+
def call
|
11
|
+
set_params
|
12
|
+
compression
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def set_params
|
18
|
+
@n = prev_stage_call[:n]
|
19
|
+
@sum = prev_stage_call[:sum]
|
20
|
+
@digest_length = prev_stage_call[:digest_length]
|
21
|
+
@hash_vector = prev_stage_call[:hash_vector]
|
22
|
+
@message_vector = prev_stage_call[:message_vector]
|
23
|
+
@message_head = nil
|
24
|
+
end
|
25
|
+
|
26
|
+
def return_params
|
27
|
+
{
|
28
|
+
n: n,
|
29
|
+
sum: sum,
|
30
|
+
digest_length: digest_length,
|
31
|
+
hash_vector: hash_vector,
|
32
|
+
message_vector: current_vector
|
33
|
+
}
|
34
|
+
end
|
35
|
+
|
36
|
+
def compression
|
37
|
+
self.current_vector = message_head || message_vector
|
38
|
+
return return_params if current_vector.size * 8 < HASH_LENGTH
|
39
|
+
transformation
|
40
|
+
compression
|
41
|
+
end
|
42
|
+
|
43
|
+
def transformation
|
44
|
+
self.hash_vector = compress(n: n,
|
45
|
+
message: slice_message_tail(current_vector),
|
46
|
+
hash_vector: hash_vector)
|
47
|
+
self.sum = addition_in_ring(sum.to_dec, current_vector.to_dec)
|
48
|
+
self.n = addition_in_ring(n.to_dec, slice_message_tail(current_vector).size * 8)
|
49
|
+
self.message_head = slice_message_head(current_vector)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Stribog
|
2
|
+
# BinaryVector
|
3
|
+
#
|
4
|
+
# @author WildDima
|
5
|
+
module Stage
|
6
|
+
# Final
|
7
|
+
#
|
8
|
+
# @author WildDima
|
9
|
+
class Final < Base
|
10
|
+
def call
|
11
|
+
set_params
|
12
|
+
final
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def set_params
|
18
|
+
@n = prev_stage_call[:n]
|
19
|
+
@sum = prev_stage_call[:sum]
|
20
|
+
@digest_length = prev_stage_call[:digest_length]
|
21
|
+
@hash_vector = prev_stage_call[:hash_vector]
|
22
|
+
@message_vector = prev_stage_call[:message_vector]
|
23
|
+
@message_head = nil
|
24
|
+
end
|
25
|
+
|
26
|
+
def final
|
27
|
+
self.hash_vector = compress(n: n.addition(size: HASH_LENGTH / 8),
|
28
|
+
message: message_vector.padding,
|
29
|
+
hash_vector: hash_vector)
|
30
|
+
self.sum = addition_in_ring(sum.to_dec, message_vector.padding.to_dec)
|
31
|
+
self.n = addition_in_ring(n.to_dec, message_vector.size * 8)
|
32
|
+
|
33
|
+
compress(message: sum, hash_vector: compress(message: n, hash_vector: hash_vector))
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Stribog
|
2
|
+
# BinaryVector
|
3
|
+
#
|
4
|
+
# @author WildDima
|
5
|
+
module Stage
|
6
|
+
# Initial
|
7
|
+
#
|
8
|
+
# @author WildDima
|
9
|
+
class Initial < Base
|
10
|
+
def call
|
11
|
+
return_params
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def return_params
|
17
|
+
{
|
18
|
+
n: empty_vector,
|
19
|
+
sum: empty_vector,
|
20
|
+
digest_length: digest_length,
|
21
|
+
hash_vector: hash_vector,
|
22
|
+
message_vector: message_vector
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
def hash_vector
|
27
|
+
case digest_length
|
28
|
+
when 512
|
29
|
+
empty_vector
|
30
|
+
when 256
|
31
|
+
field_vector(value: 1)
|
32
|
+
else
|
33
|
+
raise ArgumentError,
|
34
|
+
"digest length must be equal to 256 or 512, not #{digest_length}"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def digest_length
|
39
|
+
@digest_length ||= prev_stage.digest_length
|
40
|
+
end
|
41
|
+
|
42
|
+
def message_vector
|
43
|
+
@message_vector ||= vector.convert(prev_stage.message)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/lib/stribog/version.rb
CHANGED
data/stribog.gemspec
CHANGED
@@ -34,5 +34,5 @@ Gem::Specification.new do |spec|
|
|
34
34
|
spec.add_development_dependency "rake", "~> 10.0"
|
35
35
|
spec.add_development_dependency "rspec", "~> 3.0"
|
36
36
|
spec.add_development_dependency "rubocop", "~> 0.45.0"
|
37
|
-
spec.add_development_dependency "
|
37
|
+
spec.add_development_dependency "pry", "~> 0.10.4"
|
38
38
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: stribog
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- WildDima
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-04-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -67,19 +67,19 @@ dependencies:
|
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: 0.45.0
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
70
|
+
name: pry
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version:
|
75
|
+
version: 0.10.4
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version:
|
82
|
+
version: 0.10.4
|
83
83
|
description:
|
84
84
|
email:
|
85
85
|
- dtopornin@gmail.com
|
@@ -99,11 +99,15 @@ files:
|
|
99
99
|
- bin/console
|
100
100
|
- bin/setup
|
101
101
|
- lib/stribog.rb
|
102
|
-
- lib/stribog/
|
103
|
-
- lib/stribog/
|
102
|
+
- lib/stribog/byte_vector.rb
|
103
|
+
- lib/stribog/compression_func.rb
|
104
104
|
- lib/stribog/create_hash.rb
|
105
105
|
- lib/stribog/digest.rb
|
106
106
|
- lib/stribog/hash_params.rb
|
107
|
+
- lib/stribog/stage/base.rb
|
108
|
+
- lib/stribog/stage/compression.rb
|
109
|
+
- lib/stribog/stage/final.rb
|
110
|
+
- lib/stribog/stage/initial.rb
|
107
111
|
- lib/stribog/version.rb
|
108
112
|
- stribog.gemspec
|
109
113
|
homepage: https://github.com/WildDima/stribog
|
@@ -1,105 +0,0 @@
|
|
1
|
-
module Stribog
|
2
|
-
# BinaryVector
|
3
|
-
#
|
4
|
-
# @author WildDima
|
5
|
-
class BinaryVector
|
6
|
-
include Enumerable
|
7
|
-
|
8
|
-
attr_reader :vector
|
9
|
-
|
10
|
-
class << self
|
11
|
-
def from_byte(byte, size: 8)
|
12
|
-
new(byte.to_s(2).chars.map(&:to_i)).addition_by_zeros(size: size)
|
13
|
-
end
|
14
|
-
|
15
|
-
def from_byte_array(byte_array, size: 8)
|
16
|
-
new(byte_array.map { |byte| from_byte(byte, size: size).to_a }
|
17
|
-
.inject([]) { |acc, elem| acc + elem })
|
18
|
-
end
|
19
|
-
|
20
|
-
def from_hex(hex)
|
21
|
-
new hex_to_bin(hex)
|
22
|
-
end
|
23
|
-
|
24
|
-
def hex_to_bin(hex)
|
25
|
-
hex.chars.map do |x|
|
26
|
-
bin = x.to_i(16).to_s(2)
|
27
|
-
'0' * (4 - bin.length) + bin
|
28
|
-
end.join.chars.map(&:to_i)
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
def initialize(vector)
|
33
|
-
@vector = vector
|
34
|
-
raise 'NotBinaryError' unless binary?
|
35
|
-
end
|
36
|
-
|
37
|
-
def ^(other)
|
38
|
-
raise 'DimensionError' unless according_dimension?(other)
|
39
|
-
self.class.new vector.map.with_index { |bit, index| bit ^ other[index] }
|
40
|
-
end
|
41
|
-
|
42
|
-
def +(other)
|
43
|
-
self.class.new vector + other.to_a
|
44
|
-
end
|
45
|
-
|
46
|
-
def addition_by_zeros(size: 512)
|
47
|
-
return self if vector.size >= size
|
48
|
-
self.class.new(Array.new(size - vector.size, 0) + @vector)
|
49
|
-
end
|
50
|
-
|
51
|
-
def addition_bit_padding(size: 512)
|
52
|
-
return self if vector.size >= size
|
53
|
-
(self.class.new([1]) + vector).addition_by_zeros(size: 512)
|
54
|
-
end
|
55
|
-
|
56
|
-
def to_dec
|
57
|
-
to_s.to_i(2)
|
58
|
-
end
|
59
|
-
|
60
|
-
def to_hex
|
61
|
-
to_s.to_i(2).to_s(16)
|
62
|
-
end
|
63
|
-
|
64
|
-
def to_s
|
65
|
-
vector.join
|
66
|
-
end
|
67
|
-
|
68
|
-
def size
|
69
|
-
vector.size
|
70
|
-
end
|
71
|
-
|
72
|
-
def [](index)
|
73
|
-
vector[index]
|
74
|
-
end
|
75
|
-
|
76
|
-
def each
|
77
|
-
vector.each do |v|
|
78
|
-
yield(v)
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
def to_a
|
83
|
-
vector
|
84
|
-
end
|
85
|
-
|
86
|
-
def to_byte_array
|
87
|
-
raise 'DimensionError' unless (vector.size % 8).zero?
|
88
|
-
vector.each_slice(8).map { |byte| byte.join.to_i(2) }
|
89
|
-
end
|
90
|
-
|
91
|
-
def zero?
|
92
|
-
to_dec.zero?
|
93
|
-
end
|
94
|
-
|
95
|
-
private
|
96
|
-
|
97
|
-
def binary?
|
98
|
-
vector.all? { |el| [0, 1].include? el }
|
99
|
-
end
|
100
|
-
|
101
|
-
def according_dimension?(second_vector)
|
102
|
-
vector.size == second_vector.size
|
103
|
-
end
|
104
|
-
end
|
105
|
-
end
|