Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add EC_POINT_add support #261

Merged
merged 1 commit into from
Jul 4, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions ext/openssl/ossl_pkey_ec.c
Original file line number Diff line number Diff line change
Expand Up @@ -1562,6 +1562,34 @@ ossl_ec_point_to_octet_string(VALUE self, VALUE conversion_form)
return str;
}

/*
* call-seq:
* point.add(point) => point
*
* Performs elliptic curve point addition.
*/
static VALUE ossl_ec_point_add(VALUE self, VALUE other)
{
EC_POINT *point_self, *point_other, *point_result;
const EC_GROUP *group;
VALUE group_v = rb_attr_get(self, id_i_group);
VALUE result;

GetECPoint(self, point_self);
GetECPoint(other, point_other);
GetECGroup(group_v, group);

result = rb_obj_alloc(cEC_POINT);
ossl_ec_point_initialize(1, &group_v, result);
GetECPoint(result, point_result);

if (EC_POINT_add(group, point_result, point_self, point_other, ossl_bn_ctx) != 1) {
ossl_raise(eEC_POINT, "EC_POINT_add");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this actually mean?

Copy link
Contributor Author

@jdhollis jdhollis Jul 4, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I gave this some thought earlier today, and I’m not sure more documentation makes sense here.

In ECC, point multiplication acts as a one-way hash, and while it probably isn’t implemented this way under the hood for performance reasons, point addition is a more primitive operation that forms the basis for point multiplication.

Most people won’t typically need this operation unless they’re implementing their own protocol (at which point, they’ll know what it is and what to do with it).

As you can see from the Wikipedia overview, the math is somewhat involved (though this post on Hacker Noon may be easier to follow).

I’m not sure a fuller description of ECC makes sense in context of the API docs.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair enough - I was just specifically wondering how this could fail, and under what situations the exception would be raised.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah. So digging through the OpenSSL source code, it looks like the top level checks involve whether a point is compatible with a particular curve. But given how points are created in Ruby, this would trigger an exception elsewhere. I suspect there are also other low-level checks further in depending on the group type.

I had assumed from looking at the other code in the openssl gem that ossl_raise would just do the right thing in any case.

}

return result;
}

/*
* call-seq:
* point.mul(bn1 [, bn2]) => point
Expand Down Expand Up @@ -1786,6 +1814,7 @@ void Init_ossl_ec(void)
/* all the other methods */

rb_define_method(cEC_POINT, "to_octet_string", ossl_ec_point_to_octet_string, 1);
rb_define_method(cEC_POINT, "add", ossl_ec_point_add, 1);
rb_define_method(cEC_POINT, "mul", ossl_ec_point_mul, -1);

id_i_group = rb_intern("@group");
Expand Down
16 changes: 16 additions & 0 deletions test/test_pkey_ec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,22 @@ def test_ec_point
assert_equal true, point.on_curve?
end

def test_ec_point_add
group = OpenSSL::PKey::EC::Group.new(:GFp, 17, 2, 2)
group.point_conversion_form = :uncompressed
gen = OpenSSL::PKey::EC::Point.new(group, B(%w{ 04 05 01 }))
group.set_generator(gen, 19, 1)

point_a = OpenSSL::PKey::EC::Point.new(group, B(%w{ 04 06 03 }))
point_b = OpenSSL::PKey::EC::Point.new(group, B(%w{ 04 10 0D }))

result = point_a.add(point_b)
assert_equal B(%w{ 04 0D 07 }), result.to_octet_string(:uncompressed)

assert_raise(TypeError) { point_a.add(nil) }
assert_raise(ArgumentError) { point_a.add }
end

def test_ec_point_mul
begin
# y^2 = x^3 + 2x + 2 over F_17
Expand Down