fabric-gateway 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,13 +0,0 @@
1
- module Fabric
2
- module Gateway
3
- class Client
4
- attr_accessor :identity
5
- attr_accessor :connection
6
-
7
- def initialize(connection, identity)
8
- self.identity = identity
9
- self.connection = connection
10
- end
11
- end
12
- end
13
- end
@@ -1,20 +0,0 @@
1
- module Fabric
2
- module Gateway
3
- module Constants
4
- ## System Chaincodes
5
- LSCC = 'lscc'.freeze
6
- QSCC = 'qscc'.freeze
7
- CSCC = 'cscc'.freeze
8
-
9
- ## System Channels
10
- SYSTEM_CHANNEL_NAME = 'testchainid'.freeze
11
-
12
- ## System Functions
13
- FUNC_GET_CHANNELS = 'GetChannels'.freeze
14
- FUNC_GET_CONFIG_BLOCK = 'GetConfigBlock'.freeze
15
-
16
- ## Variables
17
- CHANNEL_HEADER_VERSION = 1
18
- end
19
- end
20
- end
@@ -1,172 +0,0 @@
1
- require 'openssl'
2
-
3
- module Fabric
4
- module Gateway
5
- # Elliptic-curve Crypto Suite using OpenSSL
6
- class ECCryptoSuite
7
- DEFAULT_KEY_SIZE = 256
8
- DEFAULT_DIGEST_ALGORITHM = 'SHA256'.freeze
9
- DEFAULT_AES_KEY_SIZE = 128
10
-
11
- EC_CURVES = { 256 => 'prime256v1', 384 => 'secp384r1' }.freeze
12
-
13
- CIPHER = 'aes-256-cbc'.freeze
14
-
15
- attr_reader :key_size, :digest_algorithm, :digest, :curve, :cipher
16
-
17
- def initialize(opts = {})
18
- @key_size = opts[:key_size] || DEFAULT_KEY_SIZE
19
- @digest_algorithm = opts[:digest_algorithm] || DEFAULT_DIGEST_ALGORITHM
20
- @digest = OpenSSL::Digest.new digest_algorithm
21
- @curve = EC_CURVES[key_size]
22
- @cipher = opts[:cipher] || CIPHER
23
- end
24
-
25
- def sign(private_key, message)
26
- digest = digest message
27
- key = pkey_from_private_key private_key
28
- signature = key.dsa_sign_asn1 digest
29
- sequence = OpenSSL::ASN1.decode signature
30
- sequence = prevent_malleability sequence, key.group.order
31
-
32
- sequence.to_der
33
- end
34
-
35
- def generate_private_key
36
- key = OpenSSL::PKey::EC.new curve
37
- key.generate_key!
38
-
39
- key.private_key.to_s(16).downcase
40
- end
41
-
42
- def generate_csr(private_key, attrs = [])
43
- key = pkey_from_private_key private_key
44
-
45
- req = OpenSSL::X509::Request.new
46
- req.public_key = key
47
- req.subject = OpenSSL::X509::Name.new attrs
48
- req.sign key, @digest
49
-
50
- req
51
- end
52
-
53
- def generate_nonce(length = 24)
54
- OpenSSL::Random.random_bytes length
55
- end
56
-
57
- def hexdigest(message)
58
- @digest.hexdigest message
59
- end
60
-
61
- def digest(message)
62
- @digest.digest message
63
- end
64
-
65
- def encode_hex(bytes)
66
- bytes.unpack('H*').first
67
- end
68
-
69
- def decode_hex(string)
70
- [string].pack('H*')
71
- end
72
-
73
- def keccak256(bytes)
74
- OpenSSL::Digest.new('SHA3-256').digest bytes
75
- end
76
-
77
-
78
- def restore_public_key(private_key)
79
- private_bn = OpenSSL::BN.new private_key, 16
80
- group = OpenSSL::PKey::EC::Group.new curve
81
- public_bn = group.generator.mul(private_bn).to_bn
82
- public_bn = OpenSSL::PKey::EC::Point.new(group, public_bn).to_bn
83
-
84
- public_bn.to_s(16).downcase
85
- end
86
-
87
- def address_from_public_key(public_key)
88
- bytes = decode_hex public_key
89
- address_bytes = keccak256(bytes[1..-1])[-20..-1]
90
-
91
- encode_hex address_bytes
92
- end
93
-
94
- def build_shared_key(private_key, public_key)
95
- pkey = pkey_from_private_key private_key
96
- public_bn = OpenSSL::BN.new public_key, 16
97
- group = OpenSSL::PKey::EC::Group.new curve
98
- public_point = OpenSSL::PKey::EC::Point.new group, public_bn
99
-
100
- encode_hex pkey.dh_compute_key(public_point)
101
- end
102
-
103
- def encrypt(secret, data)
104
- aes = OpenSSL::Cipher.new cipher
105
- aes.encrypt
106
- aes.key = decode_hex(secret)
107
- iv = aes.random_iv
108
- aes.iv = iv
109
-
110
- Base64.strict_encode64(iv + aes.update(data) + aes.final)
111
- end
112
-
113
- def decrypt(secret, data)
114
- return unless data
115
-
116
- encrypted_data = Base64.strict_decode64 data
117
- aes = OpenSSL::Cipher.new cipher
118
- aes.decrypt
119
- aes.key = decode_hex(secret)
120
- aes.iv = encrypted_data[0..15]
121
- encrypted_data = encrypted_data[16..-1]
122
-
123
- aes.update(encrypted_data) + aes.final
124
- end
125
-
126
- def pkey_pem_from_private_key(private_key)
127
- public_key = restore_public_key private_key
128
- key = OpenSSL::PKey::EC.new curve
129
- key.private_key = OpenSSL::BN.new private_key, 16
130
- key.public_key = OpenSSL::PKey::EC::Point.new key.group,
131
- OpenSSL::BN.new(public_key, 16)
132
-
133
- pkey = OpenSSL::PKey::EC.new(key.public_key.group)
134
- pkey.public_key = key.public_key
135
-
136
- pkey.to_pem
137
- end
138
-
139
- def key_from_pem(pem)
140
- key = OpenSSL::PKey::EC.new(pem)
141
- key.private_key.to_s(16)
142
- end
143
-
144
- def pkey_from_x509_certificate(certificate)
145
- cert = OpenSSL::X509::Certificate.new(certificate)
146
- cert.public_key.public_key.to_bn.to_s(16)
147
- end
148
-
149
- private
150
-
151
- def pkey_from_private_key(private_key)
152
- public_key = restore_public_key private_key
153
- key = OpenSSL::PKey::EC.new curve
154
- key.private_key = OpenSSL::BN.new private_key, 16
155
- key.public_key = OpenSSL::PKey::EC::Point.new key.group,
156
- OpenSSL::BN.new(public_key, 16)
157
-
158
- key
159
- end
160
-
161
- def prevent_malleability(sequence, order)
162
- half_order = order >> 1
163
-
164
- if (half_key = sequence.value[1].value) > half_order
165
- sequence.value[1].value = order - half_key
166
- end
167
-
168
- sequence
169
- end
170
- end
171
- end
172
- end
@@ -1,47 +0,0 @@
1
- require 'msp/identities_pb'
2
- require 'base64'
3
-
4
- module Fabric
5
- module Gateway
6
- class Identity
7
- attr_reader :private_key,
8
- :public_key,
9
- :address,
10
- :crypto_suite
11
-
12
- attr_accessor :pem_certificate, :certificate, :mspid
13
-
14
- def initialize(opts = {})
15
- @crypto_suite = opts[:crypto_suite] || Fabric::Gateway.crypto_suite
16
-
17
- @private_key = opts[:private_key] || @crypto_suite.generate_private_key
18
- @public_key = opts[:public_key] || @crypto_suite.restore_public_key(private_key)
19
- @certificate = opts[:certificate]
20
- @pem_certificate = opts[:pem_certificate]
21
- @mspid = opts[:mspid]
22
-
23
- @address = @crypto_suite.address_from_public_key public_key
24
- end
25
-
26
- def generate_csr(attrs = [])
27
- @crypto_suite.generate_csr private_key, attrs
28
- end
29
-
30
- def sign(message)
31
- @crypto_suite.sign(private_key, message)
32
- end
33
-
34
- def shared_secret_by(public_key)
35
- @crypto_suite.build_shared_key private_key, public_key
36
- end
37
-
38
- def decoded_certificate
39
- Base64.strict_decode64 certificate
40
- end
41
-
42
- def serialize
43
- Msp::SerializedIdentity.new(mspid: mspid, id_bytes: pem_certificate).to_proto
44
- end
45
- end
46
- end
47
- end
@@ -1,105 +0,0 @@
1
- module Fabric
2
- module Gateway
3
- class Proposal
4
- attr_reader :identity, :request
5
-
6
- def initialize(identity, request = {})
7
- @identity = identity
8
- @request = request
9
-
10
- assign_tx request[:transaction_info] if request[:transaction_info]
11
- end
12
-
13
- def crypto_suite
14
- identity.crypto_suite
15
- end
16
-
17
- def nonce
18
- @nonce ||= crypto_suite.generate_nonce
19
- end
20
-
21
- def channel_id
22
- request[:channel_id]
23
- end
24
-
25
- def chaincode_id
26
- request[:chaincode_id]
27
- end
28
-
29
- def args
30
- request[:args].compact.map &:to_s
31
- end
32
-
33
- def transient
34
- request[:transient] || {}
35
- end
36
-
37
- def transaction_id
38
- request[:transaction_id]
39
- end
40
-
41
- def tx_id
42
- @tx_id ||= crypto_suite.hexdigest(nonce + identity.serialize)
43
- end
44
-
45
- def proposal
46
- @proposal ||= Protos::Proposal.new header: header.to_proto,
47
- payload: chaincode_proposal.to_proto
48
- end
49
-
50
- def signed_proposal
51
- proposal_bytes = proposal.to_proto
52
- signature = identity.sign proposal_bytes
53
-
54
- Protos::SignedProposal.new proposal_bytes: proposal_bytes, signature: signature
55
- end
56
-
57
- def header
58
- Common::Header.new channel_header: channel_header.to_proto,
59
- signature_header: signature_header.to_proto
60
- end
61
-
62
- def channel_header
63
- Common::ChannelHeader.new type: Common::HeaderType::ENDORSER_TRANSACTION,
64
- channel_id: channel_id, tx_id: tx_id,
65
- extension: channel_header_extension.to_proto,
66
- timestamp: tx_timestamp,
67
- version: Constants::CHANNEL_HEADER_VERSION
68
- end
69
-
70
- def channel_header_extension
71
- id = Protos::ChaincodeID.new name: chaincode_id
72
-
73
- Protos::ChaincodeHeaderExtension.new chaincode_id: id
74
- end
75
-
76
- def tx_timestamp
77
- now = Time.now
78
-
79
- @tx_timestamp ||= Google::Protobuf::Timestamp.new seconds: now.to_i, nanos: now.nsec
80
- end
81
-
82
- def signature_header
83
- Common::SignatureHeader.new creator: identity.serialize, nonce: nonce
84
- end
85
-
86
- def chaincode_proposal
87
- id = Protos::ChaincodeID.new name: chaincode_id
88
- chaincode_input = Protos::ChaincodeInput.new args: args
89
- chaincode_spec = Protos::ChaincodeSpec.new type: Protos::ChaincodeSpec::Type::NODE,
90
- chaincode_id: id,
91
- input: chaincode_input
92
- input = Protos::ChaincodeInvocationSpec.new chaincode_spec: chaincode_spec
93
-
94
- Protos::ChaincodeProposalPayload.new input: input.to_proto, TransientMap: transient
95
- end
96
-
97
- private
98
-
99
- def assign_tx(transaction_info)
100
- @tx_id = transaction_info[:tx_id]
101
- @nonce = crypto_suite.decode_hex transaction_info[:nonce_hex]
102
- end
103
- end
104
- end
105
- end
@@ -1,5 +0,0 @@
1
- module Fabric
2
- module Gateway
3
- VERSION = "0.1.0"
4
- end
5
- end