poseidon_hash 1.0.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.
@@ -0,0 +1,123 @@
1
+ module Poseidon
2
+ class Hash
3
+ include Constant
4
+
5
+ def s_box(x)
6
+ p = 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001
7
+ a = (x * x) % p
8
+ b = (a * a) % p
9
+ (x * b) % p
10
+ end
11
+
12
+ def dotprod(a, b)
13
+ p = 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001
14
+ raise 'Length of a and b must be equal' unless a.length == b.length
15
+
16
+ res = 0
17
+ for i in 0...a.length
18
+ res += ((a[i] * b[i]) % p)
19
+ end
20
+ res % p
21
+ end
22
+
23
+ def matrix_multiply(m, x)
24
+ b = []
25
+ raise 'M must be a square matrix' unless m.length == m[0].length
26
+ raise 'Length of M and x must be equal' unless m.length == x.length
27
+
28
+ for i in 0...x.length
29
+ b << dotprod(m[i], x)
30
+ end
31
+ b
32
+ end
33
+
34
+ def perm(input_words, t)
35
+ p = 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001
36
+ raise 'Length of input_words must be equal to t' unless input_words.length == t
37
+
38
+ rp = get_RP(t)
39
+ rf = 4
40
+ m = get_mds(t)
41
+ rc = get_round_constants(t)
42
+ state_words = input_words.dup
43
+
44
+ rc_counter = 0
45
+ # First full rounds
46
+ for r in 0...rf
47
+ # Round constants, nonlinear layer, matrix multiplication
48
+ for i in 0...t
49
+ state_words[i] = (state_words[i] + rc[rc_counter]) % p
50
+ rc_counter += 1
51
+ end
52
+ for i in 0...t
53
+ state_words[i] = s_box(state_words[i])
54
+ end
55
+ state_words = matrix_multiply(m, state_words)
56
+ end
57
+
58
+ # Middle partial rounds
59
+ for r in 0...rp
60
+ # Round constants, nonlinear layer, matrix multiplication
61
+ for i in 0...t
62
+ state_words[i] = (state_words[i] + rc[rc_counter]) % p
63
+ rc_counter += 1
64
+ end
65
+ state_words[0] = s_box(state_words[0])
66
+ state_words = matrix_multiply(m, state_words)
67
+ end
68
+
69
+ # Last full rounds
70
+ for r in 0...rf
71
+ # Round constants, nonlinear layer, matrix multiplication
72
+ for i in 0...t
73
+ state_words[i] = (state_words[i] + rc[rc_counter]) % p
74
+ rc_counter += 1
75
+ end
76
+ for i in 0...t
77
+ state_words[i] = s_box(state_words[i])
78
+ end
79
+ state_words = matrix_multiply(m, state_words)
80
+ end
81
+
82
+ raise 'rc_counter must be equal to length of RC' unless rc_counter == rc.length
83
+
84
+ state_words
85
+ end
86
+
87
+ def hash(input, arity)
88
+ raise 'The length of the input must be equal to the arity' unless input.length == arity
89
+
90
+ copied_input = input.dup
91
+ state = [0] + copied_input
92
+ output = perm(state, arity + 1)
93
+ output[0]
94
+ end
95
+
96
+ def linear_hash_many(inputs, arity = 16)
97
+ # base case
98
+ if inputs.length <= arity
99
+ base_hash_inputs = inputs + ([0] * (arity - inputs.length))
100
+ current_hash = hash(base_hash_inputs, arity)
101
+ remaining_inputs = []
102
+ else
103
+ base_hash_inputs = inputs[0...arity]
104
+ remaining_inputs = inputs[arity..-1]
105
+ current_hash = hash(base_hash_inputs, arity)
106
+ end
107
+
108
+ while remaining_inputs.length > 0
109
+ if remaining_inputs.length <= arity - 1
110
+ hash_inputs = [current_hash] + remaining_inputs + ([0] * (arity - remaining_inputs.length - 1))
111
+ remaining_inputs = []
112
+ current_hash = hash(hash_inputs, arity)
113
+ else
114
+ hash_inputs = [current_hash] + remaining_inputs[0...arity - 1]
115
+ remaining_inputs = remaining_inputs[arity - 1..-1]
116
+ current_hash = hash(hash_inputs, arity)
117
+ end
118
+ end
119
+
120
+ current_hash
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,2 @@
1
+ require 'poseidon/constant'
2
+ require 'poseidon/hash'
metadata ADDED
@@ -0,0 +1,45 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: poseidon_hash
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Nhan Vu
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-06-29 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Ruby implementation of Poseidon hash function
14
+ email: nhannvu.19@gmail.com
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - lib/poseidon/constant.rb
20
+ - lib/poseidon/hash.rb
21
+ - lib/poseidon_hash.rb
22
+ homepage: https://rubygems.org/gems/poseidon_hash
23
+ licenses:
24
+ - MIT
25
+ metadata: {}
26
+ post_install_message:
27
+ rdoc_options: []
28
+ require_paths:
29
+ - lib
30
+ required_ruby_version: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ required_rubygems_version: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ requirements: []
41
+ rubygems_version: 3.2.33
42
+ signing_key:
43
+ specification_version: 4
44
+ summary: Poseidon hash function
45
+ test_files: []