fabric-gateway 0.1.0 → 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.
@@ -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