Class: Fabric::ECCryptoSuite
- Inherits:
-
Object
- Object
- Fabric::ECCryptoSuite
- Defined in:
- lib/fabric/ec_crypto_suite.rb
Overview
missing tests
Elliptic-curve Crypto Suite using OpenSSL
Constant Summary collapse
- DEFAULT_KEY_SIZE =
rubocop:disable Metrics/ClassLength
256
- DEFAULT_DIGEST_ALGORITHM =
'SHA256'
- DEFAULT_AES_KEY_SIZE =
128
- EC_CURVES =
{ 256 => 'prime256v1', 384 => 'secp384r1' }.freeze
- CIPHER =
'aes-256-cbc'
Instance Attribute Summary collapse
-
#cipher ⇒ Object
readonly
Returns the value of attribute cipher.
-
#curve ⇒ Object
readonly
Returns the value of attribute curve.
-
#digest_algorithm ⇒ Object
readonly
Returns the value of attribute digest_algorithm.
-
#digest_instance ⇒ Object
readonly
Returns the value of attribute digest_instance.
-
#key_size ⇒ Object
readonly
Returns the value of attribute key_size.
Instance Method Summary collapse
- #address_from_public_key(public_key) ⇒ Object
- #build_shared_key(private_key, public_key) ⇒ Object
- #decode_hex(string) ⇒ Object
- #decrypt(secret, data) ⇒ Object
- #digest(message) ⇒ Object
- #encode_hex(bytes) ⇒ Object
- #encrypt(secret, data) ⇒ Object
- #generate_csr(private_key, attrs = []) ⇒ Object
- #generate_nonce(length = 24) ⇒ Object
- #generate_private_key ⇒ Object
- #hexdigest(message) ⇒ Object
-
#initialize(opts = {}) ⇒ ECCryptoSuite
constructor
A new instance of ECCryptoSuite.
- #key_from_pem(pem) ⇒ Object
-
#pem_from_private_key(private_key) ⇒ Object
rubocop:enable Metrics/AbcSize rubocop:enable Metrics/MethodLength.
-
#pkey_from_private_key(private_key) ⇒ Object
when https://github.com/ruby/openssl/pull/555 gets merged, consider refactoring the code here rubocop:disable Metrics/AbcSize rubocop:disable Metrics/MethodLength.
-
#pkey_from_public_key(public_key) ⇒ Object
rubocop:disable Metrics/MethodLength.
- #public_key_from_x509_certificate(certificate) ⇒ Object
- #restore_public_key(private_key) ⇒ Object
- #sign(private_key, message) ⇒ Object
- #verify(public_key, message, signature) ⇒ Object
Constructor Details
#initialize(opts = {}) ⇒ ECCryptoSuite
Returns a new instance of ECCryptoSuite.
23 24 25 26 27 28 29 |
# 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 |
Instance Attribute Details
#cipher ⇒ Object (readonly)
Returns the value of attribute cipher.
21 22 23 |
# File 'lib/fabric/ec_crypto_suite.rb', line 21 def cipher @cipher end |
#curve ⇒ Object (readonly)
Returns the value of attribute curve.
21 22 23 |
# File 'lib/fabric/ec_crypto_suite.rb', line 21 def curve @curve end |
#digest_algorithm ⇒ Object (readonly)
Returns the value of attribute digest_algorithm.
21 22 23 |
# File 'lib/fabric/ec_crypto_suite.rb', line 21 def digest_algorithm @digest_algorithm end |
#digest_instance ⇒ Object (readonly)
Returns the value of attribute digest_instance.
21 22 23 |
# File 'lib/fabric/ec_crypto_suite.rb', line 21 def digest_instance @digest_instance end |
#key_size ⇒ Object (readonly)
Returns the value of attribute key_size.
21 22 23 |
# File 'lib/fabric/ec_crypto_suite.rb', line 21 def key_size @key_size end |
Instance Method Details
#address_from_public_key(public_key) ⇒ Object
96 97 98 99 100 101 |
# File 'lib/fabric/ec_crypto_suite.rb', line 96 def address_from_public_key(public_key) bytes = decode_hex public_key address_bytes = digest(bytes[1..])[-20..] encode_hex address_bytes end |
#build_shared_key(private_key, public_key) ⇒ Object
103 104 105 106 107 108 109 110 |
# File 'lib/fabric/ec_crypto_suite.rb', line 103 def build_shared_key(private_key, public_key) pkey = pkey_from_private_key private_key public_bn = OpenSSL::BN.new public_key, 16 group = OpenSSL::PKey::EC::Group.new curve public_point = OpenSSL::PKey::EC::Point.new group, public_bn encode_hex pkey.dh_compute_key(public_point) end |
#decode_hex(string) ⇒ Object
83 84 85 |
# File 'lib/fabric/ec_crypto_suite.rb', line 83 def decode_hex(string) [string].pack('H*') end |
#decrypt(secret, data) ⇒ Object
122 123 124 125 126 127 128 129 130 131 132 133 |
# File 'lib/fabric/ec_crypto_suite.rb', line 122 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) ⇒ Object
75 76 77 |
# File 'lib/fabric/ec_crypto_suite.rb', line 75 def digest() @digest_instance.digest end |
#encode_hex(bytes) ⇒ Object
79 80 81 |
# File 'lib/fabric/ec_crypto_suite.rb', line 79 def encode_hex(bytes) bytes.unpack1('H*') end |
#encrypt(secret, data) ⇒ Object
112 113 114 115 116 117 118 119 120 |
# File 'lib/fabric/ec_crypto_suite.rb', line 112 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 = []) ⇒ Object
56 57 58 59 60 61 62 63 64 65 |
# File 'lib/fabric/ec_crypto_suite.rb', line 56 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) ⇒ Object
67 68 69 |
# File 'lib/fabric/ec_crypto_suite.rb', line 67 def generate_nonce(length = 24) OpenSSL::Random.random_bytes length end |
#generate_private_key ⇒ Object
50 51 52 53 54 |
# File 'lib/fabric/ec_crypto_suite.rb', line 50 def generate_private_key key = OpenSSL::PKey::EC.generate(curve) key.private_key.to_s(16).downcase end |
#hexdigest(message) ⇒ Object
71 72 73 |
# File 'lib/fabric/ec_crypto_suite.rb', line 71 def hexdigest() @digest_instance.hexdigest end |
#key_from_pem(pem) ⇒ Object
168 169 170 171 |
# File 'lib/fabric/ec_crypto_suite.rb', line 168 def key_from_pem(pem) key = OpenSSL::PKey::EC.new(pem) key.private_key.to_s(16).downcase end |
#pem_from_private_key(private_key) ⇒ Object
rubocop:enable Metrics/AbcSize rubocop:enable Metrics/MethodLength
162 163 164 165 166 |
# File 'lib/fabric/ec_crypto_suite.rb', line 162 def pem_from_private_key(private_key) pkey = pkey_from_private_key(private_key) pkey.to_pem end |
#pkey_from_private_key(private_key) ⇒ Object
when https://github.com/ruby/openssl/pull/555 gets merged, consider refactoring the code here rubocop:disable Metrics/AbcSize rubocop:disable Metrics/MethodLength
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 |
# File 'lib/fabric/ec_crypto_suite.rb', line 139 def pkey_from_private_key(private_key) public_key = restore_public_key private_key group = OpenSSL::PKey::EC::Group.new(curve) private_key_bn = OpenSSL::BN.new(private_key, 16) public_key_bn = OpenSSL::BN.new(public_key, 16) public_key_point = OpenSSL::PKey::EC::Point.new(group, public_key_bn) asn1 = OpenSSL::ASN1::Sequence( [ OpenSSL::ASN1::Integer.new(1), OpenSSL::ASN1::OctetString(private_key_bn.to_s(2)), OpenSSL::ASN1::ObjectId(curve, 0, :EXPLICIT), OpenSSL::ASN1::BitString(public_key_point.to_octet_string(:uncompressed), 1, :EXPLICIT) ] ) OpenSSL::PKey::EC.new(asn1.to_der) end |
#pkey_from_public_key(public_key) ⇒ Object
rubocop:disable Metrics/MethodLength
179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 |
# File 'lib/fabric/ec_crypto_suite.rb', line 179 def pkey_from_public_key(public_key) group = OpenSSL::PKey::EC::Group.new(curve) public_key_bn = OpenSSL::BN.new(public_key, 16) public_key_point = OpenSSL::PKey::EC::Point.new(group, public_key_bn) asn1 = OpenSSL::ASN1::Sequence.new( [ OpenSSL::ASN1::Sequence.new([ OpenSSL::ASN1::ObjectId.new('id-ecPublicKey'), OpenSSL::ASN1::ObjectId.new(group.curve_name) ]), OpenSSL::ASN1::BitString.new(public_key_point.to_octet_string(:uncompressed)) ] ) OpenSSL::PKey::EC.new(asn1.to_der) end |
#public_key_from_x509_certificate(certificate) ⇒ Object
173 174 175 176 |
# File 'lib/fabric/ec_crypto_suite.rb', line 173 def public_key_from_x509_certificate(certificate) cert = OpenSSL::X509::Certificate.new(certificate) cert.public_key.public_key.to_bn.to_s(16).downcase end |
#restore_public_key(private_key) ⇒ Object
87 88 89 90 91 92 93 94 |
# File 'lib/fabric/ec_crypto_suite.rb', line 87 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) ⇒ Object
31 32 33 34 35 36 37 38 39 |
# File 'lib/fabric/ec_crypto_suite.rb', line 31 def sign(private_key, ) digest = digest 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) ⇒ Object
41 42 43 44 45 46 47 48 |
# File 'lib/fabric/ec_crypto_suite.rb', line 41 def verify(public_key, , signature) digest = digest openssl_pkey = 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 |