Class: Fabric::ECCryptoSuite
- Inherits:
-
Object
- Object
- Fabric::ECCryptoSuite
- Defined in:
- lib/fabric/ec_crypto_suite.rb
Overview
TODO:
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
- #openssl_pkey_from_public_key(public_key) ⇒ Object
- #pkey_from_x509_certificate(certificate) ⇒ Object
- #pkey_pem_from_private_key(private_key) ⇒ 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
97 98 99 100 101 102 |
# 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 |
#build_shared_key(private_key, public_key) ⇒ Object
104 105 106 107 108 109 110 111 |
# File 'lib/fabric/ec_crypto_suite.rb', line 104 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
84 85 86 |
# File 'lib/fabric/ec_crypto_suite.rb', line 84 def decode_hex(string) [string].pack('H*') end |
#decrypt(secret, data) ⇒ Object
123 124 125 126 127 128 129 130 131 132 133 134 |
# 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) ⇒ Object
76 77 78 |
# File 'lib/fabric/ec_crypto_suite.rb', line 76 def digest() @digest_instance.digest end |
#encode_hex(bytes) ⇒ Object
80 81 82 |
# File 'lib/fabric/ec_crypto_suite.rb', line 80 def encode_hex(bytes) bytes.unpack1('H*') end |
#encrypt(secret, data) ⇒ Object
113 114 115 116 117 118 119 120 121 |
# 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 = []) ⇒ Object
57 58 59 60 61 62 63 64 65 66 |
# 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) ⇒ Object
68 69 70 |
# File 'lib/fabric/ec_crypto_suite.rb', line 68 def generate_nonce(length = 24) OpenSSL::Random.random_bytes length end |
#generate_private_key ⇒ Object
50 51 52 53 54 55 |
# 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) ⇒ Object
72 73 74 |
# File 'lib/fabric/ec_crypto_suite.rb', line 72 def hexdigest() @digest_instance.hexdigest end |
#key_from_pem(pem) ⇒ Object
149 150 151 152 |
# 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) ⇒ Object
159 160 161 162 163 164 |
# 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) ⇒ Object
154 155 156 157 |
# 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) ⇒ Object
136 137 138 139 140 141 142 143 144 145 146 147 |
# 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) ⇒ Object
88 89 90 91 92 93 94 95 |
# 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) ⇒ 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 = 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 |