ccipher_factory 0.1.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 +7 -0
- data/.rspec +3 -0
- data/Gemfile +30 -0
- data/Gemfile.lock-java +65 -0
- data/Gemfile.lock-ruby +67 -0
- data/README.md +80 -0
- data/Rakefile +10 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/ccipher_factory.gemspec +46 -0
- data/lib/ccipher_factory/asymkey/asymkey.rb +16 -0
- data/lib/ccipher_factory/asymkey/asymkey_generator.rb +87 -0
- data/lib/ccipher_factory/asymkey/ecc_keypair.rb +56 -0
- data/lib/ccipher_factory/asymkey_cipher/asymkey_cipher.rb +63 -0
- data/lib/ccipher_factory/asymkey_cipher/asymkey_signer.rb +44 -0
- data/lib/ccipher_factory/asymkey_cipher/ecc/ecc_att_decrypt.rb +55 -0
- data/lib/ccipher_factory/asymkey_cipher/ecc/ecc_att_encrypt.rb +70 -0
- data/lib/ccipher_factory/asymkey_cipher/ecc/ecc_att_signer.rb +88 -0
- data/lib/ccipher_factory/asymkey_cipher/ecc/ecc_att_verifier.rb +100 -0
- data/lib/ccipher_factory/asymkey_cipher/ecc/ecc_decrypt.rb +80 -0
- data/lib/ccipher_factory/asymkey_cipher/ecc/ecc_encrypt.rb +101 -0
- data/lib/ccipher_factory/asymkey_cipher/ecc/ecc_signer.rb +80 -0
- data/lib/ccipher_factory/asymkey_cipher/ecc/ecc_verifier.rb +56 -0
- data/lib/ccipher_factory/composite_cipher/composite_cipher.rb +28 -0
- data/lib/ccipher_factory/composite_cipher/decrypt_verifier.rb +116 -0
- data/lib/ccipher_factory/composite_cipher/sign_encryptor.rb +100 -0
- data/lib/ccipher_factory/compression/compression_helper.rb +103 -0
- data/lib/ccipher_factory/compression/compressor.rb +55 -0
- data/lib/ccipher_factory/compression/zlib_compressor.rb +48 -0
- data/lib/ccipher_factory/compression/zlib_decompressor.rb +67 -0
- data/lib/ccipher_factory/digest/digest.rb +180 -0
- data/lib/ccipher_factory/digest/supported_digest.rb +47 -0
- data/lib/ccipher_factory/encoding/asn1.rb +43 -0
- data/lib/ccipher_factory/encoding/bin_struct.rb +207 -0
- data/lib/ccipher_factory/encoding/binenc_constant.rb +149 -0
- data/lib/ccipher_factory/helpers/common.rb +124 -0
- data/lib/ccipher_factory/kcv/kcv.rb +89 -0
- data/lib/ccipher_factory/kdf/hkdf.rb +114 -0
- data/lib/ccipher_factory/kdf/kdf.rb +73 -0
- data/lib/ccipher_factory/kdf/pbkdf2.rb +82 -0
- data/lib/ccipher_factory/kdf/scrypt.rb +105 -0
- data/lib/ccipher_factory/shamir/shamir_sharing.rb +293 -0
- data/lib/ccipher_factory/shamir/shamir_sharing_helper.rb +88 -0
- data/lib/ccipher_factory/symkey/derived_symkey.rb +110 -0
- data/lib/ccipher_factory/symkey/hardware_symkey.rb +0 -0
- data/lib/ccipher_factory/symkey/soft_symkey.rb +63 -0
- data/lib/ccipher_factory/symkey/symkey.rb +122 -0
- data/lib/ccipher_factory/symkey/symkey_generator.rb +70 -0
- data/lib/ccipher_factory/symkey_cipher/symkey_att_decrypt.rb +64 -0
- data/lib/ccipher_factory/symkey_cipher/symkey_att_encrypt.rb +65 -0
- data/lib/ccipher_factory/symkey_cipher/symkey_att_sign.rb +84 -0
- data/lib/ccipher_factory/symkey_cipher/symkey_att_verify.rb +85 -0
- data/lib/ccipher_factory/symkey_cipher/symkey_cipher.rb +101 -0
- data/lib/ccipher_factory/symkey_cipher/symkey_decrypt.rb +144 -0
- data/lib/ccipher_factory/symkey_cipher/symkey_encrypt.rb +164 -0
- data/lib/ccipher_factory/symkey_cipher/symkey_sign.rb +70 -0
- data/lib/ccipher_factory/symkey_cipher/symkey_signer.rb +59 -0
- data/lib/ccipher_factory/symkey_cipher/symkey_verify.rb +76 -0
- data/lib/ccipher_factory/version.rb +5 -0
- data/lib/ccipher_factory.rb +52 -0
- data/run_test.rb +27 -0
- metadata +172 -0
@@ -0,0 +1,114 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
|
4
|
+
require_relative '../digest/digest'
|
5
|
+
require_relative '../digest/supported_digest'
|
6
|
+
|
7
|
+
module CcipherFactory
|
8
|
+
module KDF
|
9
|
+
module HKDF
|
10
|
+
include TR::CondUtils
|
11
|
+
include Common
|
12
|
+
include TR::DataConvUtils
|
13
|
+
|
14
|
+
attr_accessor :outByteLength, :salt
|
15
|
+
attr_accessor :digestAlgo
|
16
|
+
attr_reader :derivedVal
|
17
|
+
def derive_init(*args, &block)
|
18
|
+
|
19
|
+
len = args.first
|
20
|
+
@outByteLength = len/8 if not_empty?(len)
|
21
|
+
|
22
|
+
@salt = SecureRandom.random_bytes(@outByteLength) if is_empty?(@salt)
|
23
|
+
|
24
|
+
if block
|
25
|
+
instance_eval(&block)
|
26
|
+
derive_final
|
27
|
+
else
|
28
|
+
self
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
def derive_update(val)
|
34
|
+
intOutputBuf.write(val)
|
35
|
+
end
|
36
|
+
|
37
|
+
def derive_final
|
38
|
+
|
39
|
+
raise KDFError, "outByteLength is required" if is_empty?(@outByteLength)
|
40
|
+
|
41
|
+
digest = nil
|
42
|
+
digestId = nil
|
43
|
+
#if not_empty?(@digest)
|
44
|
+
|
45
|
+
# case @digest
|
46
|
+
# when String, Symbol
|
47
|
+
# logger.tdebug :hkdf_derive_final, "Given digest object is a string/symbol #{@digest}"
|
48
|
+
# @digestAlgo = @digest
|
49
|
+
|
50
|
+
# #when OpenSSL::Digest
|
51
|
+
# # digestId = Digest.to_digest_string(@digest.name)
|
52
|
+
# # logger.tdebug :hkdf_derive_final, "Using user given OpenSSL digest object #{@digest}"
|
53
|
+
# # digest = @digest
|
54
|
+
|
55
|
+
# #when CcipherFactory::Digest
|
56
|
+
# # digestId = @digest.algo
|
57
|
+
|
58
|
+
# # logger.tdebug :hkdf_derive_final, "Using user given CipherFactory digest #{@digest}"
|
59
|
+
# # digest = OpenSSL::Digest.new(digestId)
|
60
|
+
|
61
|
+
# else
|
62
|
+
# raise KDFError, "Digest object #{@digest.class} is not supported"
|
63
|
+
# end
|
64
|
+
|
65
|
+
#end
|
66
|
+
|
67
|
+
if is_empty?(@digestAlgo)
|
68
|
+
digestVal = CcipherFactory::Digest::SupportedDigest.instance.default_digest
|
69
|
+
digestId = digestVal
|
70
|
+
|
71
|
+
logger.tdebug :hkdf_derive_final, "digest algo is nil. Using default digest #{digestVal}"
|
72
|
+
|
73
|
+
else
|
74
|
+
raise KDFError, "Given digest algo '#{@digestAlgo}' is not supported" if not Digest::SupportedDigest.instance.is_supported?(@digestAlgo)
|
75
|
+
|
76
|
+
logger.tdebug :hkdf_derive_final, "Using user given digest algo #{@digestAlgo}"
|
77
|
+
|
78
|
+
digestId = @digestAlgo
|
79
|
+
end
|
80
|
+
|
81
|
+
@info = "" if @info.nil?
|
82
|
+
|
83
|
+
hconf = Ccrypto::HKDFConfig.new
|
84
|
+
hconf.digest = digestId
|
85
|
+
hconf.salt = @salt
|
86
|
+
hconf.info = @info
|
87
|
+
hconf.outBitLength = @outByteLength*8
|
88
|
+
|
89
|
+
hkdf = Ccrypto::AlgoFactory.engine(hconf)
|
90
|
+
|
91
|
+
@derivedVal = hkdf.derive(intOutputBuf.bytes)
|
92
|
+
|
93
|
+
write_to_output(@derivedVal) if is_output_given?
|
94
|
+
|
95
|
+
ts = BinStruct.instance.struct(:kdf_hkdf)
|
96
|
+
ts.digest = BTag.constant_value(digestId)
|
97
|
+
ts.salt = @salt
|
98
|
+
ts.outByteLength = @outByteLength
|
99
|
+
ts.encoded
|
100
|
+
|
101
|
+
end
|
102
|
+
|
103
|
+
private
|
104
|
+
def logger
|
105
|
+
if @logger.nil?
|
106
|
+
@logger = Tlogger.new
|
107
|
+
@logger.tag = :hkdf
|
108
|
+
end
|
109
|
+
@logger
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
|
2
|
+
require_relative 'scrypt'
|
3
|
+
require_relative 'hkdf'
|
4
|
+
require_relative 'pbkdf2'
|
5
|
+
|
6
|
+
module CcipherFactory
|
7
|
+
module KDF
|
8
|
+
|
9
|
+
class KDFError < StandardError; end
|
10
|
+
|
11
|
+
class KDFEngine; end
|
12
|
+
|
13
|
+
def KDF.instance(eng = :scrypt, &block)
|
14
|
+
kdf = KDFEngine.new
|
15
|
+
|
16
|
+
case eng
|
17
|
+
when :scrypt
|
18
|
+
kdf.extend(Scrypt)
|
19
|
+
when :hkdf
|
20
|
+
kdf.extend(HKDF)
|
21
|
+
when :pbkdf2
|
22
|
+
kdf.extend(PBKDF2)
|
23
|
+
else
|
24
|
+
raise KDFError, "Unknown KDF engine '#{eng}'"
|
25
|
+
end
|
26
|
+
|
27
|
+
kdf
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.supported_kdf_algo
|
31
|
+
[:scrypt, :hkdf, :pbkdf2].freeze
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.from_encoded(bin, &block)
|
35
|
+
ts = BinStruct.instance.struct_from_bin(bin)
|
36
|
+
from_tspec(ts, &block)
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.from_tspec(ts, &block)
|
40
|
+
case BTag.value_constant(ts.oid)
|
41
|
+
when :kdf_scrypt
|
42
|
+
kdf = KDFEngine.new
|
43
|
+
kdf.extend(Scrypt)
|
44
|
+
kdf.cost = ts.cost
|
45
|
+
kdf.parallel = ts.parallel
|
46
|
+
kdf.blocksize = ts.blocksize
|
47
|
+
kdf.salt = ts.salt
|
48
|
+
kdf.outByteLength = ts.outByteLength
|
49
|
+
kdf.digest = Digest.from_encoded(ts.digest)
|
50
|
+
kdf.derive_init
|
51
|
+
kdf
|
52
|
+
when :kdf_hkdf
|
53
|
+
kdf = KDFEngine.new
|
54
|
+
kdf.extend(HKDF)
|
55
|
+
kdf.digestAlgo = BTag.value_constant(ts.digest)
|
56
|
+
kdf.salt = ts.salt
|
57
|
+
kdf.outByteLength = ts.outByteLength
|
58
|
+
kdf.derive_init
|
59
|
+
when :kdf_pbkdf2
|
60
|
+
kdf = KDFEngine.new
|
61
|
+
kdf.extend(PBKDF2)
|
62
|
+
kdf.digestAlgo = BTag.value_constant(ts.digest)
|
63
|
+
kdf.salt = ts.salt
|
64
|
+
kdf.iter = ts.iterations
|
65
|
+
kdf.outByteLength = ts.outByteLength
|
66
|
+
kdf.derive_init
|
67
|
+
else
|
68
|
+
raise KDFError, "Unknown KDF envelope ID '#{ts.oid}'"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
module CcipherFactory
|
4
|
+
module KDF
|
5
|
+
module PBKDF2
|
6
|
+
include TR::CondUtils
|
7
|
+
include Common
|
8
|
+
|
9
|
+
attr_accessor :salt, :iter, :outByteLength, :digestAlgo
|
10
|
+
|
11
|
+
def derive_init(*args, &block)
|
12
|
+
|
13
|
+
len = args.first
|
14
|
+
@outByteLength = len/8 if not_empty?(len)
|
15
|
+
|
16
|
+
@salt = SecureRandom.random_bytes(@outByteLength) if is_empty?(@salt)
|
17
|
+
|
18
|
+
if block
|
19
|
+
instance_eval(&block)
|
20
|
+
derive_final
|
21
|
+
else
|
22
|
+
self
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
def derive_update(val)
|
28
|
+
intOutputBuf.write(val)
|
29
|
+
end
|
30
|
+
|
31
|
+
def derive_final
|
32
|
+
|
33
|
+
raise KDFError, "outByteLength is required" if is_empty?(@outByteLength)
|
34
|
+
|
35
|
+
#if is_empty?(@digestAlgo)
|
36
|
+
# digestVal = CcipherFactory::Digest::SupportedDigest.instance.default_digest
|
37
|
+
# digestId = digestVal
|
38
|
+
|
39
|
+
# logger.tdebug :pbkdf2_derive_final, "digest algo is nil. Using default digest #{digestVal}"
|
40
|
+
|
41
|
+
#else
|
42
|
+
# raise KDFError, "Given digest algo '#{@digestAlgo}' is not supported" if not Digest::SupportedDigest.instance.is_supported?(@digestAlgo)
|
43
|
+
|
44
|
+
# logger.tdebug :pbkdf2_derive_final, "Using user given digest algo #{@digestAlgo}"
|
45
|
+
|
46
|
+
# digestId = @digestAlgo
|
47
|
+
#end
|
48
|
+
|
49
|
+
hconf = Ccrypto::PBKDF2Config.new
|
50
|
+
#hconf.digest = digestId
|
51
|
+
hconf.digest = @digestAlgo
|
52
|
+
hconf.salt = @salt if not_empty?(@salt)
|
53
|
+
hconf.iter = @iter if not_empty?(@iter)
|
54
|
+
hconf.outBitLength = @outByteLength*8
|
55
|
+
|
56
|
+
hkdf = Ccrypto::AlgoFactory.engine(hconf)
|
57
|
+
|
58
|
+
@derivedVal = hkdf.derive(intOutputBuf.bytes)
|
59
|
+
|
60
|
+
write_to_output(@derivedVal) if is_output_given?
|
61
|
+
|
62
|
+
ts = BinStruct.instance.struct(:kdf_pbkdf2)
|
63
|
+
#ts.digest = BTag.constant_value(digestId)
|
64
|
+
ts.digest = BTag.constant_value(hconf.digest)
|
65
|
+
ts.salt = @salt
|
66
|
+
ts.outByteLength = @outByteLength
|
67
|
+
ts.iterations = hconf.iter
|
68
|
+
ts.encoded
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
def logger
|
73
|
+
if @logger.nil?
|
74
|
+
@logger = TeLogger::Tlogger.new
|
75
|
+
@logger.tag = :pbkdf2
|
76
|
+
end
|
77
|
+
@logger
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
require_relative '../digest/digest'
|
4
|
+
require_relative '../digest/supported_digest'
|
5
|
+
|
6
|
+
module CcipherFactory
|
7
|
+
module KDF
|
8
|
+
module Scrypt
|
9
|
+
include TR::CondUtils
|
10
|
+
include Common
|
11
|
+
|
12
|
+
##
|
13
|
+
# Mixin methods
|
14
|
+
##
|
15
|
+
attr_accessor :cost, :parallel, :blocksize, :salt, :outByteLength
|
16
|
+
attr_accessor :digestAlgo, :digest
|
17
|
+
attr_reader :derivedVal
|
18
|
+
def derive_init(*args, &block)
|
19
|
+
|
20
|
+
len = args.first
|
21
|
+
@outByteLength = len/8 if not_empty?(len)
|
22
|
+
|
23
|
+
@cost = 65536 if is_empty?(@cost)
|
24
|
+
@parallel = 1 if is_empty?(@parallel)
|
25
|
+
@blocksize = 8 if is_empty?(@blocksize)
|
26
|
+
@salt = SecureRandom.random_bytes(16) if is_empty?(@salt)
|
27
|
+
|
28
|
+
logger.debug "Cost : #{@cost}"
|
29
|
+
logger.debug "Parallel : #{@parallel}"
|
30
|
+
logger.debug "Blocksize : #{@blocksize}"
|
31
|
+
logger.debug "Salt : #{@salt.inspect}"
|
32
|
+
logger.debug "Digest Algo : #{@digestAlgo}"
|
33
|
+
logger.debug "Digest : #{@digest}"
|
34
|
+
|
35
|
+
if @digest.nil?
|
36
|
+
logger.debug "Initializing digest with algo #{@digestAlgo}"
|
37
|
+
@digestAlgo = Digest::SupportedDigest.instance.default_digest if is_empty?(@digestAlgo)
|
38
|
+
@digest = Digest.instance
|
39
|
+
@digest.digest_init(@digestAlgo)
|
40
|
+
else
|
41
|
+
logger.debug "Setting digest algo value from digest #{@digest}"
|
42
|
+
@digestAlgo = @digest.algo
|
43
|
+
end
|
44
|
+
|
45
|
+
@digest.output(intOutputBuf)
|
46
|
+
|
47
|
+
if block
|
48
|
+
instance_eval(&block)
|
49
|
+
derive_final
|
50
|
+
else
|
51
|
+
self
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
def derive_update(val)
|
57
|
+
@digest.digest_update(val)
|
58
|
+
end
|
59
|
+
|
60
|
+
def derive_final(&block)
|
61
|
+
|
62
|
+
raise KDFError, "outByteLength is required" if is_empty?(@outByteLength)
|
63
|
+
|
64
|
+
digMeta = @digest.digest_final
|
65
|
+
|
66
|
+
sconf = Ccrypto::ScryptConfig.new
|
67
|
+
sconf.outBitLength = @outByteLength*8
|
68
|
+
sconf.salt = @salt
|
69
|
+
sconf.cost = @cost
|
70
|
+
sconf.parallel = @parallel
|
71
|
+
sconf.blockSize = @blocksize
|
72
|
+
|
73
|
+
scrypt = Ccrypto::AlgoFactory.engine(sconf)
|
74
|
+
|
75
|
+
@derivedVal = scrypt.derive(intOutputBuf.bytes)
|
76
|
+
|
77
|
+
if is_output_given?
|
78
|
+
write_to_output(@derivedVal)
|
79
|
+
end
|
80
|
+
|
81
|
+
ts = BinStruct.instance.struct(:kdf_scrypt)
|
82
|
+
ts.digest = digMeta
|
83
|
+
ts.salt = @salt
|
84
|
+
ts.cost = @cost
|
85
|
+
ts.blocksize = @blocksize
|
86
|
+
ts.parallel = @parallel
|
87
|
+
ts.outByteLength = @outByteLength
|
88
|
+
ts.encoded
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
private
|
93
|
+
def logger
|
94
|
+
if @logger.nil?
|
95
|
+
@logger = TeLogger::Tlogger.new
|
96
|
+
@logger.tag = :scrypt
|
97
|
+
end
|
98
|
+
|
99
|
+
@logger
|
100
|
+
end
|
101
|
+
|
102
|
+
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,293 @@
|
|
1
|
+
|
2
|
+
#
|
3
|
+
# This code is borrowed from PolyPasswordHasher-Ruby project at https://github.com/PolyPasswordHasher/PolyPasswordHasher-Ruby
|
4
|
+
#
|
5
|
+
|
6
|
+
|
7
|
+
#require "openssl"
|
8
|
+
|
9
|
+
module CcipherFactory
|
10
|
+
|
11
|
+
class ShamirSharing
|
12
|
+
attr_reader :_coefficients
|
13
|
+
attr_reader :secretdata
|
14
|
+
|
15
|
+
def initialize(threshold, secretdata=nil)
|
16
|
+
@threshold = threshold
|
17
|
+
@secretdata = secretdata
|
18
|
+
@_coefficients = []
|
19
|
+
|
20
|
+
if secretdata
|
21
|
+
secretdata.each_char do |secretbyte|
|
22
|
+
rand = Ccrypto::AlgoFactory.engine(Ccrypto::SecureRandomConfig)
|
23
|
+
randVal = rand.random_bytes(@threshold-1)
|
24
|
+
thesecoefficients = secretbyte+randVal
|
25
|
+
#thesecoefficients = secretbyte+OpenSSL::Random.random_bytes(@threshold-1)
|
26
|
+
@_coefficients << thesecoefficients
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def is_valid_share?(share)
|
32
|
+
raise "Share is of incorrect length: #{share.size}" if share.size !=2
|
33
|
+
raise "Must initialize coefficient before checking is_valid_share?" unless @_coefficients
|
34
|
+
raise "Must initialize coefficient before checking is_valid_share?" if @_coefficients.size != share[1].size
|
35
|
+
|
36
|
+
x = share[0]
|
37
|
+
fx = share[1]
|
38
|
+
|
39
|
+
correctshare = compute_share(x)
|
40
|
+
|
41
|
+
correctshare == share
|
42
|
+
end
|
43
|
+
|
44
|
+
def compute_share(x)
|
45
|
+
raise "x should be integer" unless x.class == Fixnum
|
46
|
+
raise "x must be between 1 and 255" if x <= 0 || x >256
|
47
|
+
raise "@_coefficient must be initialized" if @_coefficients.empty?
|
48
|
+
|
49
|
+
sharebytes = []
|
50
|
+
|
51
|
+
@_coefficients.each do |thiscoefficient|
|
52
|
+
thisshare = _f(x,thiscoefficient)
|
53
|
+
sharebytes << thisshare
|
54
|
+
end
|
55
|
+
|
56
|
+
return x, sharebytes
|
57
|
+
end
|
58
|
+
|
59
|
+
def recover_secretdata(shares)
|
60
|
+
newshares = []
|
61
|
+
|
62
|
+
shares.each do |share|
|
63
|
+
newshares << share unless newshares.include?(share)
|
64
|
+
end
|
65
|
+
|
66
|
+
shares = newshares
|
67
|
+
|
68
|
+
if @threshold > shares.size
|
69
|
+
raise "Threshold: #{@threshold} is smaller than the number of uniquie shares: #{shares.size}"
|
70
|
+
end
|
71
|
+
|
72
|
+
if @secretdata
|
73
|
+
raise "Recovoring secretdata when some is stored. Use check_share instead"
|
74
|
+
end
|
75
|
+
|
76
|
+
xs = []
|
77
|
+
|
78
|
+
shares.each do |share|
|
79
|
+
if xs.include?(share[0])
|
80
|
+
raise "Different shares with the same first byte: #{share[0]}"
|
81
|
+
end
|
82
|
+
|
83
|
+
if share[1].size != shares[0][1].size
|
84
|
+
raise "Shares have different lengths!"
|
85
|
+
end
|
86
|
+
|
87
|
+
xs << share[0]
|
88
|
+
end
|
89
|
+
|
90
|
+
mycoefficients = []
|
91
|
+
mysecretdata = ''
|
92
|
+
|
93
|
+
shares[0][1].size.times.each do |byte_to_use|
|
94
|
+
fxs = []
|
95
|
+
shares.each do |share|
|
96
|
+
fxs << share[1][byte_to_use]
|
97
|
+
end
|
98
|
+
|
99
|
+
resulting_poly = _full_lagrange(xs,fxs)
|
100
|
+
|
101
|
+
if resulting_poly[0..@threshold-1] + [0]*(shares.size - @threshold) != resulting_poly
|
102
|
+
raise "Share do not match. Cannot decode"
|
103
|
+
end
|
104
|
+
|
105
|
+
mycoefficients << resulting_poly.map{|p| p.chr}.join
|
106
|
+
|
107
|
+
mysecretdata += resulting_poly[0].chr
|
108
|
+
end
|
109
|
+
|
110
|
+
@_coefficients = mycoefficients
|
111
|
+
@secretdata = mysecretdata
|
112
|
+
end
|
113
|
+
|
114
|
+
private
|
115
|
+
def _f(x, coefs_bytes)
|
116
|
+
raise "invalid share index value. cannot be 0" if x == 0
|
117
|
+
|
118
|
+
accumulator = 0
|
119
|
+
|
120
|
+
x_i = 1
|
121
|
+
|
122
|
+
coefs_bytes.each_byte do |c|
|
123
|
+
accumulator = _gf256_add(accumulator, _gf256_mul(c, x_i))
|
124
|
+
x_i = _gf256_mul(x_i, x)
|
125
|
+
end
|
126
|
+
|
127
|
+
return accumulator
|
128
|
+
end
|
129
|
+
|
130
|
+
def _multiply_polynomials(a,b)
|
131
|
+
resultterms = []
|
132
|
+
|
133
|
+
termpadding = []
|
134
|
+
|
135
|
+
b.each do |bterm|
|
136
|
+
thisvalue = termpadding.clone
|
137
|
+
|
138
|
+
a.each do |aterm|
|
139
|
+
val = _gf256_mul(aterm, bterm)
|
140
|
+
thisvalue << _gf256_mul(aterm, bterm)
|
141
|
+
end
|
142
|
+
|
143
|
+
resultterms = _add_polynomials(resultterms, thisvalue)
|
144
|
+
|
145
|
+
termpadding << 0
|
146
|
+
end
|
147
|
+
|
148
|
+
return resultterms
|
149
|
+
end
|
150
|
+
|
151
|
+
def _add_polynomials(a,b)
|
152
|
+
if a.size < b.size
|
153
|
+
a = a + [0]*(b.size - a.size)
|
154
|
+
elsif a.size > b.size
|
155
|
+
b = b + [0]*(a.size - b.size)
|
156
|
+
end
|
157
|
+
|
158
|
+
result = []
|
159
|
+
|
160
|
+
a.size.times do |pos|
|
161
|
+
result << _gf256_add(a[pos], b[pos])
|
162
|
+
end
|
163
|
+
|
164
|
+
return result
|
165
|
+
end
|
166
|
+
|
167
|
+
def _full_lagrange(xs, fxs)
|
168
|
+
returnedcoefficients = []
|
169
|
+
|
170
|
+
fxs.size.times do |i|
|
171
|
+
this_polynomial = [1]
|
172
|
+
|
173
|
+
fxs.size.times do |j|
|
174
|
+
next if i == j
|
175
|
+
|
176
|
+
denominator = _gf256_sub(xs[i], xs[j])
|
177
|
+
|
178
|
+
this_term = [_gf256_div(xs[j], denominator), _gf256_div(1, denominator)]
|
179
|
+
|
180
|
+
this_polynomial = _multiply_polynomials(this_polynomial, this_term)
|
181
|
+
end
|
182
|
+
|
183
|
+
this_polynomial = _multiply_polynomials(this_polynomial, [fxs[i]]) if fxs[i]
|
184
|
+
|
185
|
+
returnedcoefficients = _add_polynomials(returnedcoefficients, this_polynomial)
|
186
|
+
end
|
187
|
+
|
188
|
+
return returnedcoefficients
|
189
|
+
|
190
|
+
end
|
191
|
+
|
192
|
+
GF256_EXP = [
|
193
|
+
0x01, 0x03, 0x05, 0x0f, 0x11, 0x33, 0x55, 0xff,
|
194
|
+
0x1a, 0x2e, 0x72, 0x96, 0xa1, 0xf8, 0x13, 0x35,
|
195
|
+
0x5f, 0xe1, 0x38, 0x48, 0xd8, 0x73, 0x95, 0xa4,
|
196
|
+
0xf7, 0x02, 0x06, 0x0a, 0x1e, 0x22, 0x66, 0xaa,
|
197
|
+
0xe5, 0x34, 0x5c, 0xe4, 0x37, 0x59, 0xeb, 0x26,
|
198
|
+
0x6a, 0xbe, 0xd9, 0x70, 0x90, 0xab, 0xe6, 0x31,
|
199
|
+
0x53, 0xf5, 0x04, 0x0c, 0x14, 0x3c, 0x44, 0xcc,
|
200
|
+
0x4f, 0xd1, 0x68, 0xb8, 0xd3, 0x6e, 0xb2, 0xcd,
|
201
|
+
0x4c, 0xd4, 0x67, 0xa9, 0xe0, 0x3b, 0x4d, 0xd7,
|
202
|
+
0x62, 0xa6, 0xf1, 0x08, 0x18, 0x28, 0x78, 0x88,
|
203
|
+
0x83, 0x9e, 0xb9, 0xd0, 0x6b, 0xbd, 0xdc, 0x7f,
|
204
|
+
0x81, 0x98, 0xb3, 0xce, 0x49, 0xdb, 0x76, 0x9a,
|
205
|
+
0xb5, 0xc4, 0x57, 0xf9, 0x10, 0x30, 0x50, 0xf0,
|
206
|
+
0x0b, 0x1d, 0x27, 0x69, 0xbb, 0xd6, 0x61, 0xa3,
|
207
|
+
0xfe, 0x19, 0x2b, 0x7d, 0x87, 0x92, 0xad, 0xec,
|
208
|
+
0x2f, 0x71, 0x93, 0xae, 0xe9, 0x20, 0x60, 0xa0,
|
209
|
+
0xfb, 0x16, 0x3a, 0x4e, 0xd2, 0x6d, 0xb7, 0xc2,
|
210
|
+
0x5d, 0xe7, 0x32, 0x56, 0xfa, 0x15, 0x3f, 0x41,
|
211
|
+
0xc3, 0x5e, 0xe2, 0x3d, 0x47, 0xc9, 0x40, 0xc0,
|
212
|
+
0x5b, 0xed, 0x2c, 0x74, 0x9c, 0xbf, 0xda, 0x75,
|
213
|
+
0x9f, 0xba, 0xd5, 0x64, 0xac, 0xef, 0x2a, 0x7e,
|
214
|
+
0x82, 0x9d, 0xbc, 0xdf, 0x7a, 0x8e, 0x89, 0x80,
|
215
|
+
0x9b, 0xb6, 0xc1, 0x58, 0xe8, 0x23, 0x65, 0xaf,
|
216
|
+
0xea, 0x25, 0x6f, 0xb1, 0xc8, 0x43, 0xc5, 0x54,
|
217
|
+
0xfc, 0x1f, 0x21, 0x63, 0xa5, 0xf4, 0x07, 0x09,
|
218
|
+
0x1b, 0x2d, 0x77, 0x99, 0xb0, 0xcb, 0x46, 0xca,
|
219
|
+
0x45, 0xcf, 0x4a, 0xde, 0x79, 0x8b, 0x86, 0x91,
|
220
|
+
0xa8, 0xe3, 0x3e, 0x42, 0xc6, 0x51, 0xf3, 0x0e,
|
221
|
+
0x12, 0x36, 0x5a, 0xee, 0x29, 0x7b, 0x8d, 0x8c,
|
222
|
+
0x8f, 0x8a, 0x85, 0x94, 0xa7, 0xf2, 0x0d, 0x17,
|
223
|
+
0x39, 0x4b, 0xdd, 0x7c, 0x84, 0x97, 0xa2, 0xfd,
|
224
|
+
0x1c, 0x24, 0x6c, 0xb4, 0xc7, 0x52, 0xf6, 0x01]
|
225
|
+
|
226
|
+
GF256_LOG = [
|
227
|
+
0x00, 0x00, 0x19, 0x01, 0x32, 0x02, 0x1a, 0xc6,
|
228
|
+
0x4b, 0xc7, 0x1b, 0x68, 0x33, 0xee, 0xdf, 0x03,
|
229
|
+
0x64, 0x04, 0xe0, 0x0e, 0x34, 0x8d, 0x81, 0xef,
|
230
|
+
0x4c, 0x71, 0x08, 0xc8, 0xf8, 0x69, 0x1c, 0xc1,
|
231
|
+
0x7d, 0xc2, 0x1d, 0xb5, 0xf9, 0xb9, 0x27, 0x6a,
|
232
|
+
0x4d, 0xe4, 0xa6, 0x72, 0x9a, 0xc9, 0x09, 0x78,
|
233
|
+
0x65, 0x2f, 0x8a, 0x05, 0x21, 0x0f, 0xe1, 0x24,
|
234
|
+
0x12, 0xf0, 0x82, 0x45, 0x35, 0x93, 0xda, 0x8e,
|
235
|
+
0x96, 0x8f, 0xdb, 0xbd, 0x36, 0xd0, 0xce, 0x94,
|
236
|
+
0x13, 0x5c, 0xd2, 0xf1, 0x40, 0x46, 0x83, 0x38,
|
237
|
+
0x66, 0xdd, 0xfd, 0x30, 0xbf, 0x06, 0x8b, 0x62,
|
238
|
+
0xb3, 0x25, 0xe2, 0x98, 0x22, 0x88, 0x91, 0x10,
|
239
|
+
0x7e, 0x6e, 0x48, 0xc3, 0xa3, 0xb6, 0x1e, 0x42,
|
240
|
+
0x3a, 0x6b, 0x28, 0x54, 0xfa, 0x85, 0x3d, 0xba,
|
241
|
+
0x2b, 0x79, 0x0a, 0x15, 0x9b, 0x9f, 0x5e, 0xca,
|
242
|
+
0x4e, 0xd4, 0xac, 0xe5, 0xf3, 0x73, 0xa7, 0x57,
|
243
|
+
0xaf, 0x58, 0xa8, 0x50, 0xf4, 0xea, 0xd6, 0x74,
|
244
|
+
0x4f, 0xae, 0xe9, 0xd5, 0xe7, 0xe6, 0xad, 0xe8,
|
245
|
+
0x2c, 0xd7, 0x75, 0x7a, 0xeb, 0x16, 0x0b, 0xf5,
|
246
|
+
0x59, 0xcb, 0x5f, 0xb0, 0x9c, 0xa9, 0x51, 0xa0,
|
247
|
+
0x7f, 0x0c, 0xf6, 0x6f, 0x17, 0xc4, 0x49, 0xec,
|
248
|
+
0xd8, 0x43, 0x1f, 0x2d, 0xa4, 0x76, 0x7b, 0xb7,
|
249
|
+
0xcc, 0xbb, 0x3e, 0x5a, 0xfb, 0x60, 0xb1, 0x86,
|
250
|
+
0x3b, 0x52, 0xa1, 0x6c, 0xaa, 0x55, 0x29, 0x9d,
|
251
|
+
0x97, 0xb2, 0x87, 0x90, 0x61, 0xbe, 0xdc, 0xfc,
|
252
|
+
0xbc, 0x95, 0xcf, 0xcd, 0x37, 0x3f, 0x5b, 0xd1,
|
253
|
+
0x53, 0x39, 0x84, 0x3c, 0x41, 0xa2, 0x6d, 0x47,
|
254
|
+
0x14, 0x2a, 0x9e, 0x5d, 0x56, 0xf2, 0xd3, 0xab,
|
255
|
+
0x44, 0x11, 0x92, 0xd9, 0x23, 0x20, 0x2e, 0x89,
|
256
|
+
0xb4, 0x7c, 0xb8, 0x26, 0x77, 0x99, 0xe3, 0xa5,
|
257
|
+
0x67, 0x4a, 0xed, 0xde, 0xc5, 0x31, 0xfe, 0x18,
|
258
|
+
0x0d, 0x63, 0x8c, 0x80, 0xc0, 0xf7, 0x70, 0x07]
|
259
|
+
|
260
|
+
|
261
|
+
def _gf256_add(a, b)
|
262
|
+
val = a ^ b
|
263
|
+
val
|
264
|
+
end
|
265
|
+
|
266
|
+
def _gf256_sub(a,b)
|
267
|
+
_gf256_add(a,b)
|
268
|
+
end
|
269
|
+
|
270
|
+
def _gf256_mul(a,b)
|
271
|
+
a = a.to_i
|
272
|
+
b = b.to_i
|
273
|
+
if a == 0 || b == 0
|
274
|
+
return 0
|
275
|
+
else
|
276
|
+
GF256_EXP[(GF256_LOG[a] + GF256_LOG[b]) % 255]
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
280
|
+
def _gf256_div(a,b)
|
281
|
+
if a == 0
|
282
|
+
return 0
|
283
|
+
elsif b == 0
|
284
|
+
raise ZeroDivisionError
|
285
|
+
else
|
286
|
+
GF256_EXP[(GF256_LOG[a] - GF256_LOG[b]) % 255]
|
287
|
+
end
|
288
|
+
end
|
289
|
+
end
|
290
|
+
|
291
|
+
|
292
|
+
|
293
|
+
end
|