openssl icon indicating copy to clipboard operation
openssl copied to clipboard

Public EC key from buffer

Open voxik opened this issue 2 years ago • 3 comments

In net-ssh, there is following code:

        public_key_oct = buffer.read_string
        begin
          key = OpenSSL::PKey::EC.new(OpenSSL::PKey::EC::CurveNameAlias[curve_name_in_key])
          group = key.group
          point = OpenSSL::PKey::EC::Point.new(group, OpenSSL::BN.new(public_key_oct, 2))
          key.public_key = point

          return key
        rescue OpenSSL::PKey::ECError
          raise NotImplementedError, "unsupported key type `#{type}'"
        end

Which fails with OpenSSL 3.x:

  1) Error:
Transport::Kex::TestEcdhSHA2NistP256#test_exchange_keys_should_return_expected_results_when_successful:
OpenSSL::PKey::PKeyError: pkeys are immutable on OpenSSL 3.0
    /builddir/net-ssh/lib/net/ssh/transport/openssl.rb:164:in `public_key='
    /builddir/net-ssh/lib/net/ssh/transport/openssl.rb:164:in `read_keyblob'
    /builddir/net-ssh/lib/net/ssh/buffer.rb:325:in `read_keyblob'
    /builddir/net-ssh/lib/net/ssh/buffer.rb:248:in `read_key'
    /builddir/net-ssh/lib/net/ssh/transport/kex/abstract5656.rb:54:in `send_kexinit'
    /builddir/net-ssh/lib/net/ssh/transport/kex/abstract.rb:48:in `exchange_keys'
    /builddir/net-ssh/test/transport/kex/test_ecdh_sha2_nistp256.rb:96:in `exchange!'
    /builddir/net-ssh/test/transport/kex/test_ecdh_sha2_nistp256.rb:18:in `test_exchange_keys_should_return_expected_results_when_successful'

Unfortunately, I struggle to find the right equivalent to implement this with immutable pkeys.

voxik avatar Feb 25 '22 19:02 voxik

Coincidentally or not, I've been working on this exact part of the code and come up with the following solution:

         public_key_oct = buffer.read_string
         begin
          curvename = OpenSSL::PKey::EC::CurveNameAlias[curve_name_in_key]
          group = OpenSSL::PKey::EC::Group.new(curvename)
           point = OpenSSL::PKey::EC::Point.new(group, OpenSSL::BN.new(public_key_oct, 2))
          asn1 = OpenSSL::ASN1::Sequence([
            OpenSSL::ASN1::Sequence([
              OpenSSL::ASN1::ObjectId("id-ecPublicKey"),
              OpenSSL::ASN1::ObjectId(curvename)
            ]),
            OpenSSL::ASN1::BitString(point.to_octet_string(:uncompressed))
          ])

          key = OpenSSL::PKey::EC.new(asn1.to_der)
          return key

I'm not entirely sure whether this is the right solution, but it seems to be and it does fix the failing tests.

sergiodj avatar Mar 11 '22 22:03 sergiodj

@sergiodj thank you so much for this!

julik avatar Dec 03 '22 01:12 julik

@sergiodj thank you for the code! You saved my evening of bashing my head against the weird #public_key APIs

DimaD avatar Dec 30 '22 12:12 DimaD