Create API to get curve parameters on a group
You are able to call new(:GFp, p, a, b) but are not able to pull those values later.
This becomes a problem when you want to for instance open a curve by name and the the value for field for modular operations. I think we should support a method like OpenSSL::PKey::EC::Group#curve_params => [ :GFp, p, a, b ]
This will require doing a little more work because that getter will first need to query the EC_GROUP_method_of for the group, then if it is GFp or GF2m pull the values of the field, a, b, etc as needed for the curve type. Since creating a new curve this is supported it can be a get only attribute.
Upon thought perhaps this should be a few different calls:
OpenSSL::PKey::EC::Group#method => Symbol where symbol is in [ :GFp_simple, :GFp_mont, :GFp_nist, :GF2m_simple ]
OpenSSL::PKey::EC::Group#field_type => Symbol where symbol in [ :GFp, GF2m ]
OpenSSL::PKey::EC::Group#field => aBN where result is the field
OpenSSL::PKey::EC::Group#curve_params => [ ... ] where the array returns the values as stated originally so that they can be used directly into a call to #new
OpenSSL::PKey::EC::Group#method => Symbolwhere symbol is in[ :GFp_simple, :GFp_mont, :GFp_nist, :GF2m_simple ]
This sounds like just OpenSSL's implementation detail. #432 doesn't include this and I feel this could be skipped.
OpenSSL::PKey::EC::Group#field_type => Symbolwhere symbol in[ :GFp, GF2m ]
Should it simply return the text representation of the NID (in other words, "prime-field" or "characteristic-two-field" - as returned by OBJ_nid2ln())?
In the upcoming OpenSSL 3.0, EC_METHOD_get_field_type() is going to be replaced by EVP_PKEY_get_params() with OSSL_PKEY_PARAM_EC_FIELD_TYPE argument. OpenSSL 3.0 is still in development and the API will likely change, but the general trend is to use strings to specify algorithm (rather than NID - exposing them out of internals has caused issues for OpenSSL).
It's not ideal if we have to maintain code like:
if (!strcmp(ft, "prime-field"))
return ID2SYM(rb_intern("GFp"));
if (!strcmp(ft, "characteristic-two-field"))
return ID2SYM(rb_intern("GF2m"));
OpenSSL::PKey::EC::Group#field => aBNwhere result is the field
OpenSSL::PKey::EC::Group#curve_params => [ ... ]where the array returns the values as stated originally so that they can be used directly into a call to#new
Why should it be an Array? Hash seems to be a better fit. If a new Group object with the same parameters is required, one can simply use #dup.
Also perhaps it could be named #params - "curve" is obvious anyway.
Should it simply return the text representation of the NID (in other words, "prime-field" or "characteristic-two-field" - as returned by
OBJ_nid2ln())?
I did it this way to match Group#initialize where it takes those symbols.
Why should it be an Array? Hash seems to be a better fit. If a new Group object with the same parameters is required, one can simply use #dup.
Again, done to match #initialize which is a arg list not a hash (I agree hashes are a better idea though)
Also perhaps it could be named #params - "curve" is obvious anyway.
Wanted to avoid conflict with other params concepts like rails
Should it simply return the text representation of the NID (in other words, "prime-field" or "characteristic-two-field" - as returned by
OBJ_nid2ln())?I did it this way to match
Group#initializewhere it takes those symbols.
I understand. I think we should rather have Group#initialize take sn/ln ("prime-field" or "characteristic-two-field"), too, for consistency.
The :GFp and :GF2m are ruby/openssl-specific keywords and those have increased maintenance burden, when OpenSSL is a moving target. It seems about the right timing to switch to OpenSSL's vocabulary.
Why should it be an Array? Hash seems to be a better fit. If a new Group object with the same parameters is required, one can simply use #dup.
Again, done to match
#initializewhich is a arg list not a hash (I agree hashes are a better idea though)
I don't get why one would want to pass the returned value to Group#initialize as-is. If it's not needed, can we use Hash instead?
Group#initialize could also take keyword arguments, but that would be a different topic.
Also perhaps it could be named #params - "curve" is obvious anyway.
Wanted to avoid conflict with other params concepts like rails
OpenSSL::PKey::{RSA,DSA,DH} have #params method to dump the content as a Hash, so I'm not worried about that.
I understand. I think we should rather have Group#initialize take sn/ln ("prime-field" or "characteristic-two-field"), too, for consistency.
What about taking an Int and defining const values for OpenSSL::PKey::EC::NID_X9_62_prime_field and OpenSSL::PKey::EC:: NID_X9_62_characteristic_two_field instead of strings? (I too hate magic strings).
At least that way if there is a third value some time if the feature clients can just have their own const.
I don't get why one would want to pass the returned value to Group#initialize as-is. If it's not needed, can we use Hash instead?
Yeah - a hash is a better call here, will make changes. Not like it cant be called with Group.new(NID_X9_62_prime_field, params[:p], params[:a], params[:b]) right?
Also looks like EC_GROUP_get_field_type was added in OpenSSL 3
For prior versions will have to check using EC_GROUP_method_of
Will implement with a have_func ifdef
What about taking an Int and defining const values for
OpenSSL::PKey::EC::NID_X9_62_prime_fieldandOpenSSL::PKey::EC:: NID_X9_62_characteristic_two_fieldinstead of strings? (I too hate magic strings).
group.field_type returning Integer 406 (== NID_X9_62_prime_field) wouldn't be very useful.
Actually, OpenSSL looks like going towards getting rid of NID in public API and has started using const char * as the canonical way to represent identifiers; EVP_PKEY_get_params() is a (somewhat extreme) example. So I don't think we have a choice here...
I don't think OpenSSL::PKey::EC::NID_X9_62_prime_field = "prime-field" would contribute to making code more readable.