class Fabric::ECCryptoSuite
Elliptic-curve Crypto Suite using OpenSSL
@todo missing tests
Constants
- CIPHER
- DEFAULT_AES_KEY_SIZE
- DEFAULT_DIGEST_ALGORITHM
- DEFAULT_KEY_SIZE
- EC_CURVES
Attributes
cipher[R]
curve[R]
digest_algorithm[R]
digest_instance[R]
key_size[R]
Public Class Methods
new(opts = {})
click to toggle source
# File lib/fabric/ec_crypto_suite.rb, line 23 def initialize(opts = {}) @key_size = opts[:key_size] || DEFAULT_KEY_SIZE @digest_algorithm = opts[:digest_algorithm] || DEFAULT_DIGEST_ALGORITHM @digest_instance = OpenSSL::Digest.new digest_algorithm @curve = EC_CURVES[key_size] @cipher = opts[:cipher] || CIPHER end
Public Instance Methods
address_from_public_key(public_key)
click to toggle source
# File lib/fabric/ec_crypto_suite.rb, line 97 def address_from_public_key(public_key) bytes = decode_hex public_key address_bytes = digest(bytes[1..])[-20..] encode_hex address_bytes end
decode_hex(string)
click to toggle source
# File lib/fabric/ec_crypto_suite.rb, line 84 def decode_hex(string) [string].pack('H*') end
decrypt(secret, data)
click to toggle source
# File lib/fabric/ec_crypto_suite.rb, line 123 def decrypt(secret, data) return unless data encrypted_data = Base64.strict_decode64 data aes = OpenSSL::Cipher.new cipher aes.decrypt aes.key = decode_hex(secret) aes.iv = encrypted_data[0..15] encrypted_data = encrypted_data[16..] aes.update(encrypted_data) + aes.final end
digest(message)
click to toggle source
# File lib/fabric/ec_crypto_suite.rb, line 76 def digest(message) @digest_instance.digest message end
encode_hex(bytes)
click to toggle source
# File lib/fabric/ec_crypto_suite.rb, line 80 def encode_hex(bytes) bytes.unpack1('H*') end
encrypt(secret, data)
click to toggle source
# File lib/fabric/ec_crypto_suite.rb, line 113 def encrypt(secret, data) aes = OpenSSL::Cipher.new cipher aes.encrypt aes.key = decode_hex(secret) iv = aes.random_iv aes.iv = iv Base64.strict_encode64(iv + aes.update(data) + aes.final) end
generate_csr(private_key, attrs = [])
click to toggle source
# File lib/fabric/ec_crypto_suite.rb, line 57 def generate_csr(private_key, attrs = []) key = pkey_from_private_key private_key req = OpenSSL::X509::Request.new req.public_key = key req.subject = OpenSSL::X509::Name.new attrs req.sign key, @digest_instance req end
generate_nonce(length = 24)
click to toggle source
# File lib/fabric/ec_crypto_suite.rb, line 68 def generate_nonce(length = 24) OpenSSL::Random.random_bytes length end
generate_private_key()
click to toggle source
# File lib/fabric/ec_crypto_suite.rb, line 50 def generate_private_key key = OpenSSL::PKey::EC.new curve key.generate_key! key.private_key.to_s(16).downcase end
hexdigest(message)
click to toggle source
# File lib/fabric/ec_crypto_suite.rb, line 72 def hexdigest(message) @digest_instance.hexdigest message end
key_from_pem(pem)
click to toggle source
# File lib/fabric/ec_crypto_suite.rb, line 149 def key_from_pem(pem) key = OpenSSL::PKey::EC.new(pem) key.private_key.to_s(16).downcase end
openssl_pkey_from_public_key(public_key)
click to toggle source
# File lib/fabric/ec_crypto_suite.rb, line 159 def openssl_pkey_from_public_key(public_key) pkey = OpenSSL::PKey::EC.new curve pkey.public_key = OpenSSL::PKey::EC::Point.new(pkey.group, OpenSSL::BN.new(public_key, 16)) pkey end
pkey_from_x509_certificate(certificate)
click to toggle source
# File lib/fabric/ec_crypto_suite.rb, line 154 def pkey_from_x509_certificate(certificate) cert = OpenSSL::X509::Certificate.new(certificate) cert.public_key.public_key.to_bn.to_s(16).downcase end
pkey_pem_from_private_key(private_key)
click to toggle source
# File lib/fabric/ec_crypto_suite.rb, line 136 def pkey_pem_from_private_key(private_key) public_key = restore_public_key private_key key = OpenSSL::PKey::EC.new curve key.private_key = OpenSSL::BN.new private_key, 16 key.public_key = OpenSSL::PKey::EC::Point.new key.group, OpenSSL::BN.new(public_key, 16) pkey = OpenSSL::PKey::EC.new(key.public_key.group) pkey.public_key = key.public_key pkey.to_pem end
restore_public_key(private_key)
click to toggle source
# File lib/fabric/ec_crypto_suite.rb, line 88 def restore_public_key(private_key) private_bn = OpenSSL::BN.new private_key, 16 group = OpenSSL::PKey::EC::Group.new curve public_bn = group.generator.mul(private_bn).to_bn public_bn = OpenSSL::PKey::EC::Point.new(group, public_bn).to_bn public_bn.to_s(16).downcase end
sign(private_key, message)
click to toggle source
# File lib/fabric/ec_crypto_suite.rb, line 31 def sign(private_key, message) digest = digest message key = pkey_from_private_key private_key signature = key.dsa_sign_asn1 digest sequence = OpenSSL::ASN1.decode signature sequence = prevent_malleability sequence, key.group.order sequence.to_der end
verify(public_key, message, signature)
click to toggle source
# File lib/fabric/ec_crypto_suite.rb, line 41 def verify(public_key, message, signature) digest = digest message openssl_pkey = openssl_pkey_from_public_key public_key sequence = OpenSSL::ASN1.decode signature return false unless check_malleability sequence, openssl_pkey.group.order openssl_pkey.dsa_verify_asn1(digest, signature) end
Private Instance Methods
check_malleability(sequence, order)
click to toggle source
ported from python code, understanding extremely limited. from what I gather, sequence.value and sequence.value are the r and s values from the python implementation github.com/hyperledger/fabric-sdk-py/blob/25209f61518873da68d28313582607c29b5bae7d/hfc/util/crypto/crypto.py#L259
# File lib/fabric/ec_crypto_suite.rb, line 194 def check_malleability(sequence, order) half_order = order >> 1 sequence.value[1].value <= half_order end
pkey_from_private_key(private_key)
click to toggle source
# File lib/fabric/ec_crypto_suite.rb, line 168 def pkey_from_private_key(private_key) public_key = restore_public_key private_key key = OpenSSL::PKey::EC.new curve key.private_key = OpenSSL::BN.new private_key, 16 key.public_key = OpenSSL::PKey::EC::Point.new key.group, OpenSSL::BN.new(public_key, 16) key end
prevent_malleability(sequence, order)
click to toggle source
barely understand this code - this link provides a good explanation: coders-errand.com/malleability-ecdsa-signatures/
# File lib/fabric/ec_crypto_suite.rb, line 180 def prevent_malleability(sequence, order) half_order = order >> 1 if (half_key = sequence.value[1].value) > half_order sequence.value[1].value = order - half_key end sequence end