зеркало из https://github.com/github/ruby.git
* ext/openssl/{extconf.rb,ossl_ssl_session.c}:
Fix ruby-Bugs-11513. * ext/openssl/ossl_pkey_ec.c New methods EC::Point.[eql,make_affine!,invert!,on_curve?,infinity?] By default output the same key form as the openssl command. * ext/openssl/ossl_rand.c New method Random.status? * test/openssl/test_ec.rb New tests. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12571 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
Родитель
1c03862049
Коммит
9fa80b19a6
14
ChangeLog
14
ChangeLog
|
@ -1,3 +1,17 @@
|
|||
Mon Jun 18 08:47:54 2007 Technorama Ltd. <oss-ruby@technorama.net>
|
||||
* ext/openssl/{extconf.rb,ossl_ssl_session.c}:
|
||||
Fix ruby-Bugs-11513.
|
||||
|
||||
* ext/openssl/ossl_pkey_ec.c
|
||||
New methods EC::Point.[eql,make_affine!,invert!,on_curve?,infinity?]
|
||||
By default output the same key form as the openssl command.
|
||||
|
||||
* ext/openssl/ossl_rand.c
|
||||
New method Random.status?
|
||||
|
||||
* test/openssl/test_ec.rb
|
||||
New tests.
|
||||
|
||||
Mon Jun 18 17:04:07 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||
|
||||
* eval_load.c (rb_require_safe, ruby_init_ext): load with ruby level
|
||||
|
|
|
@ -96,6 +96,7 @@ have_func("X509_CRL_sort")
|
|||
have_func("X509_STORE_get_ex_data")
|
||||
have_func("X509_STORE_set_ex_data")
|
||||
have_func("OBJ_NAME_do_all_sorted")
|
||||
have_func("SSL_SESSION_get_id")
|
||||
have_func("OPENSSL_cleanse")
|
||||
if try_compile("#define FOO(a, ...) foo(a, ##__VA_ARGS__)\n int x(){FOO(1);FOO(1,2);FOO(1,2,3);}\n")
|
||||
$defs.push("-DHAVE_VA_ARGS_MACRO")
|
||||
|
|
|
@ -209,6 +209,9 @@ static VALUE ossl_ec_key_initialize(int argc, VALUE *argv, VALUE self)
|
|||
|
||||
if ((ec = EC_KEY_new_by_curve_name(nid)) == NULL)
|
||||
ossl_raise(eECError, "unable to create curve (%s)\n", name);
|
||||
|
||||
EC_KEY_set_asn1_flag(ec, OPENSSL_EC_NAMED_CURVE);
|
||||
EC_KEY_set_conv_form(ec, POINT_CONVERSION_UNCOMPRESSED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -569,23 +572,6 @@ static VALUE ossl_ec_key_to_text(VALUE self)
|
|||
return str;
|
||||
}
|
||||
|
||||
static VALUE ossl_ec_key_to_public_key(VALUE self)
|
||||
{
|
||||
EC_KEY *ec;
|
||||
|
||||
VALUE new_obj;
|
||||
|
||||
Require_EC_KEY(self, ec);
|
||||
|
||||
new_obj = rb_obj_alloc(cEC);
|
||||
|
||||
/* BUG: finish .to_public_key */
|
||||
rb_notimplement();
|
||||
|
||||
|
||||
return new_obj;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* key.generate_key => self
|
||||
|
@ -664,7 +650,7 @@ static VALUE ossl_ec_key_dh_compute_key(VALUE self, VALUE pubkey)
|
|||
static VALUE ossl_ec_key_dsa_sign_asn1(VALUE self, VALUE data)
|
||||
{
|
||||
EC_KEY *ec;
|
||||
int buf_len;
|
||||
unsigned int buf_len;
|
||||
VALUE str;
|
||||
|
||||
Require_EC_KEY(self, ec);
|
||||
|
@ -674,7 +660,7 @@ static VALUE ossl_ec_key_dsa_sign_asn1(VALUE self, VALUE data)
|
|||
ossl_raise(eECError, "Private EC key needed!");
|
||||
|
||||
str = rb_str_new(0, ECDSA_size(ec) + 16);
|
||||
if (ECDSA_sign(0, RSTRING_PTR(data), RSTRING_LEN(data), RSTRING_PTR(str), &buf_len, ec) != 1)
|
||||
if (ECDSA_sign(0, (unsigned char *) RSTRING_PTR(data), RSTRING_LEN(data), (unsigned char *) RSTRING_PTR(str), &buf_len, ec) != 1)
|
||||
ossl_raise(eECError, "ECDSA_sign");
|
||||
|
||||
rb_str_resize(str, buf_len);
|
||||
|
@ -696,7 +682,7 @@ static VALUE ossl_ec_key_dsa_verify_asn1(VALUE self, VALUE data, VALUE sig)
|
|||
StringValue(data);
|
||||
StringValue(sig);
|
||||
|
||||
switch (ECDSA_verify(0, RSTRING_PTR(data), RSTRING_LEN(data), RSTRING_PTR(sig), RSTRING_LEN(sig), ec)) {
|
||||
switch (ECDSA_verify(0, (unsigned char *) RSTRING_PTR(data), RSTRING_LEN(data), (unsigned char *) RSTRING_PTR(sig), RSTRING_LEN(sig), ec)) {
|
||||
case 1: return Qtrue;
|
||||
case 0: return Qfalse;
|
||||
default: break;
|
||||
|
@ -788,15 +774,18 @@ static VALUE ossl_ec_group_initialize(int argc, VALUE *argv, VALUE self)
|
|||
BIO_free(in);
|
||||
|
||||
if (!group) {
|
||||
const char *name = STR2CSTR(arg1);
|
||||
int nid = OBJ_sn2nid(name);
|
||||
const char *name = STR2CSTR(arg1);
|
||||
int nid = OBJ_sn2nid(name);
|
||||
|
||||
if (nid == NID_undef)
|
||||
ossl_raise(eEC_GROUP, "unknown curve name (%s)", name);
|
||||
if (nid == NID_undef)
|
||||
ossl_raise(eEC_GROUP, "unknown curve name (%s)", name);
|
||||
|
||||
group = EC_GROUP_new_by_curve_name(nid);
|
||||
if (group == NULL)
|
||||
ossl_raise(eEC_GROUP, "unable to create curve (%s)", name);
|
||||
|
||||
EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
|
||||
EC_GROUP_set_point_conversion_form(group, POINT_CONVERSION_UNCOMPRESSED);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -836,6 +825,23 @@ static VALUE ossl_ec_group_initialize(int argc, VALUE *argv, VALUE self)
|
|||
return self;
|
||||
}
|
||||
|
||||
/* call-seq:
|
||||
* group1 == group2 => true | false
|
||||
*
|
||||
*/
|
||||
static VALUE ossl_ec_group_eql(VALUE a, VALUE b)
|
||||
{
|
||||
EC_GROUP *group1 = NULL, *group2 = NULL;
|
||||
|
||||
Require_EC_GROUP(a, group1);
|
||||
SafeRequire_EC_GROUP(b, group2);
|
||||
|
||||
if (EC_GROUP_cmp(group1, group2, ossl_bn_ctx) == 1)
|
||||
return Qfalse;
|
||||
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
/* call-seq:
|
||||
* group.generator => ec_point
|
||||
*
|
||||
|
@ -1287,6 +1293,133 @@ static VALUE ossl_ec_point_initialize(int argc, VALUE *argv, VALUE self)
|
|||
return self;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* point1 == point2 => true | false
|
||||
*
|
||||
*/
|
||||
static VALUE ossl_ec_point_eql(VALUE a, VALUE b)
|
||||
{
|
||||
EC_POINT *point1, *point2;
|
||||
VALUE group_v1 = rb_iv_get(a, "@group");
|
||||
VALUE group_v2 = rb_iv_get(b, "@group");
|
||||
const EC_GROUP *group;
|
||||
|
||||
if (ossl_ec_group_eql(group_v1, group_v2) == Qfalse)
|
||||
return Qfalse;
|
||||
|
||||
Require_EC_POINT(a, point1);
|
||||
SafeRequire_EC_POINT(b, point2);
|
||||
SafeRequire_EC_GROUP(group_v1, group);
|
||||
|
||||
if (EC_POINT_cmp(group, point1, point2, ossl_bn_ctx) == 1)
|
||||
return Qfalse;
|
||||
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* point.infinity? => true | false
|
||||
*
|
||||
*/
|
||||
static VALUE ossl_ec_point_is_at_infinity(VALUE self)
|
||||
{
|
||||
EC_POINT *point;
|
||||
VALUE group_v = rb_iv_get(self, "@group");
|
||||
const EC_GROUP *group;
|
||||
|
||||
Require_EC_POINT(self, point);
|
||||
SafeRequire_EC_GROUP(group_v, group);
|
||||
|
||||
switch (EC_POINT_is_at_infinity(group, point)) {
|
||||
case 1: return Qtrue;
|
||||
case 0: return Qfalse;
|
||||
default: ossl_raise(cEC_POINT, "EC_POINT_is_at_infinity");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* point.on_curve? => true | false
|
||||
*
|
||||
*/
|
||||
static VALUE ossl_ec_point_is_on_curve(VALUE self)
|
||||
{
|
||||
EC_POINT *point;
|
||||
VALUE group_v = rb_iv_get(self, "@group");
|
||||
const EC_GROUP *group;
|
||||
|
||||
Require_EC_POINT(self, point);
|
||||
SafeRequire_EC_GROUP(group_v, group);
|
||||
|
||||
switch (EC_POINT_is_on_curve(group, point, ossl_bn_ctx)) {
|
||||
case 1: return Qtrue;
|
||||
case 0: return Qfalse;
|
||||
default: ossl_raise(cEC_POINT, "EC_POINT_is_on_curve");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* point.make_affine! => self
|
||||
*
|
||||
*/
|
||||
static VALUE ossl_ec_point_make_affine(VALUE self)
|
||||
{
|
||||
EC_POINT *point;
|
||||
VALUE group_v = rb_iv_get(self, "@group");
|
||||
const EC_GROUP *group;
|
||||
|
||||
Require_EC_POINT(self, point);
|
||||
SafeRequire_EC_GROUP(group_v, group);
|
||||
|
||||
if (EC_POINT_make_affine(group, point, ossl_bn_ctx) != 1)
|
||||
ossl_raise(cEC_POINT, "EC_POINT_make_affine");
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* point.invert! => self
|
||||
*
|
||||
*/
|
||||
static VALUE ossl_ec_point_invert(VALUE self)
|
||||
{
|
||||
EC_POINT *point;
|
||||
VALUE group_v = rb_iv_get(self, "@group");
|
||||
const EC_GROUP *group;
|
||||
|
||||
Require_EC_POINT(self, point);
|
||||
SafeRequire_EC_GROUP(group_v, group);
|
||||
|
||||
if (EC_POINT_invert(group, point, ossl_bn_ctx) != 1)
|
||||
ossl_raise(cEC_POINT, "EC_POINT_invert");
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* point.set_to_infinity! => self
|
||||
*
|
||||
*/
|
||||
static VALUE ossl_ec_point_set_to_infinity(VALUE self)
|
||||
{
|
||||
EC_POINT *point;
|
||||
VALUE group_v = rb_iv_get(self, "@group");
|
||||
const EC_GROUP *group;
|
||||
|
||||
Require_EC_POINT(self, point);
|
||||
SafeRequire_EC_GROUP(group_v, group);
|
||||
|
||||
if (EC_POINT_set_to_infinity(group, point) != 1)
|
||||
ossl_raise(cEC_POINT, "EC_POINT_set_to_infinity");
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* point.to_bn => OpenSSL::BN
|
||||
|
@ -1350,6 +1483,10 @@ void Init_ossl_ec()
|
|||
ID_compressed = rb_intern("compressed");
|
||||
ID_hybrid = rb_intern("hybrid");
|
||||
|
||||
#ifdef OPENSSL_EC_NAMED_CURVE
|
||||
rb_define_const(cEC, "NAMED_CURVE", ULONG2NUM(OPENSSL_EC_NAMED_CURVE));
|
||||
#endif
|
||||
|
||||
rb_define_singleton_method(cEC, "builtin_curves", ossl_s_builtin_curves, 0);
|
||||
|
||||
rb_define_method(cEC, "initialize", ossl_ec_key_initialize, -1);
|
||||
|
@ -1373,7 +1510,7 @@ void Init_ossl_ec()
|
|||
rb_define_method(cEC, "generate_key", ossl_ec_key_generate_key, 0);
|
||||
rb_define_method(cEC, "check_key", ossl_ec_key_check_key, 0);
|
||||
|
||||
rb_define_method(cEC, "dh_compute_key", ossl_ec_key_dh_compute_key, 2);
|
||||
rb_define_method(cEC, "dh_compute_key", ossl_ec_key_dh_compute_key, 1);
|
||||
rb_define_method(cEC, "dsa_sign_asn1", ossl_ec_key_dsa_sign_asn1, 1);
|
||||
rb_define_method(cEC, "dsa_verify_asn1", ossl_ec_key_dsa_verify_asn1, 2);
|
||||
/* do_sign/do_verify */
|
||||
|
@ -1385,6 +1522,8 @@ void Init_ossl_ec()
|
|||
|
||||
rb_define_alloc_func(cEC_GROUP, ossl_ec_group_alloc);
|
||||
rb_define_method(cEC_GROUP, "initialize", ossl_ec_group_initialize, -1);
|
||||
rb_define_method(cEC_GROUP, "eql?", ossl_ec_group_eql, 1);
|
||||
rb_define_alias(cEC_GROUP, "==", "eql?");
|
||||
/* copy/dup/cmp */
|
||||
|
||||
rb_define_method(cEC_GROUP, "generator", ossl_ec_group_get_generator, 0);
|
||||
|
@ -1419,6 +1558,14 @@ void Init_ossl_ec()
|
|||
rb_define_alloc_func(cEC_POINT, ossl_ec_point_alloc);
|
||||
rb_define_method(cEC_POINT, "initialize", ossl_ec_point_initialize, -1);
|
||||
rb_attr(cEC_POINT, rb_intern("group"), 1, 0, 0);
|
||||
rb_define_method(cEC_POINT, "eql?", ossl_ec_point_eql, 1);
|
||||
rb_define_alias(cEC_POINT, "==", "eql?");
|
||||
|
||||
rb_define_method(cEC_POINT, "infinity?", ossl_ec_point_is_at_infinity, 0);
|
||||
rb_define_method(cEC_POINT, "on_curve?", ossl_ec_point_is_on_curve, 0);
|
||||
rb_define_method(cEC_POINT, "make_affine!", ossl_ec_point_make_affine, 0);
|
||||
rb_define_method(cEC_POINT, "invert!", ossl_ec_point_invert, 0);
|
||||
rb_define_method(cEC_POINT, "set_to_infinity!", ossl_ec_point_set_to_infinity, 0);
|
||||
/* all the other methods */
|
||||
|
||||
rb_define_method(cEC_POINT, "to_bn", ossl_ec_point_to_bn, 0);
|
||||
|
|
|
@ -135,6 +135,18 @@ ossl_rand_egd_bytes(VALUE self, VALUE filename, VALUE len)
|
|||
return Qtrue;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* status? => true | false
|
||||
*
|
||||
* Return true if the PRNG has been seeded with enough data, false otherwise.
|
||||
*/
|
||||
static VALUE
|
||||
ossl_rand_status(VALUE self)
|
||||
{
|
||||
return RAND_status() ? Qtrue : Qfalse;
|
||||
}
|
||||
|
||||
#define DEFMETH(class, name, func, argc) \
|
||||
rb_define_method(class, name, func, argc); \
|
||||
rb_define_singleton_method(class, name, func, argc);
|
||||
|
@ -160,5 +172,6 @@ Init_ossl_rand()
|
|||
DEFMETH(mRandom, "pseudo_bytes", ossl_rand_pseudo_bytes, 1);
|
||||
DEFMETH(mRandom, "egd", ossl_rand_egd, 1);
|
||||
DEFMETH(mRandom, "egd_bytes", ossl_rand_egd_bytes, 2);
|
||||
DEFMETH(mRandom, "status?", ossl_rand_status, 0)
|
||||
}
|
||||
|
||||
|
|
|
@ -157,6 +157,7 @@ static VALUE ossl_ssl_session_get_timeout(VALUE self)
|
|||
SSLSESSION_SET_TIME(time)
|
||||
SSLSESSION_SET_TIME(timeout)
|
||||
|
||||
#ifdef HAVE_SSL_SESSION_GET_ID
|
||||
/*
|
||||
* call-seq:
|
||||
* session.id -> aString
|
||||
|
@ -175,6 +176,7 @@ static VALUE ossl_ssl_session_get_id(VALUE self)
|
|||
|
||||
return rb_str_new(p, i);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
|
@ -285,7 +287,9 @@ void Init_ossl_ssl_session(void)
|
|||
rb_define_method(cSSLSession, "timeout", ossl_ssl_session_get_timeout, 0);
|
||||
rb_define_method(cSSLSession, "timeout=", ossl_ssl_session_set_timeout, 1);
|
||||
|
||||
#ifdef HAVE_SSL_SESSION_GET_ID
|
||||
rb_define_method(cSSLSession, "id", ossl_ssl_session_get_id, 0);
|
||||
#endif
|
||||
rb_define_method(cSSLSession, "to_der", ossl_ssl_session_to_der, 0);
|
||||
rb_define_method(cSSLSession, "to_pem", ossl_ssl_session_to_pem, 0);
|
||||
rb_define_method(cSSLSession, "to_text", ossl_ssl_session_to_text, 0);
|
||||
|
|
|
@ -0,0 +1,113 @@
|
|||
begin
|
||||
require "openssl"
|
||||
require File.join(File.dirname(__FILE__), "utils.rb")
|
||||
rescue LoadError
|
||||
end
|
||||
require "test/unit"
|
||||
|
||||
if defined?(OpenSSL::PKey::EC)
|
||||
|
||||
class OpenSSL::TestEC < Test::Unit::TestCase
|
||||
def setup
|
||||
@data1 = 'foo'
|
||||
@data2 = 'bar' * 1000 # data too long for DSA sig
|
||||
|
||||
@group1 = OpenSSL::PKey::EC::Group.new('secp112r1')
|
||||
@group2 = OpenSSL::PKey::EC::Group.new('sect163k1')
|
||||
|
||||
@key1 = OpenSSL::PKey::EC.new
|
||||
@key1.group = @group1
|
||||
@key1.generate_key
|
||||
|
||||
@key2 = OpenSSL::PKey::EC.new(@group2.curve_name)
|
||||
@key2.generate_key
|
||||
|
||||
@groups = [@group1, @group2]
|
||||
@keys = [@key1, @key2]
|
||||
end
|
||||
|
||||
def compare_keys(k1, k2)
|
||||
assert_equal(k1.to_pem, k2.to_pem)
|
||||
end
|
||||
|
||||
def test_curve_names
|
||||
@groups.each_with_index do |group, idx|
|
||||
key = @keys[idx]
|
||||
assert_equal(group.curve_name, key.group.curve_name)
|
||||
end
|
||||
end
|
||||
|
||||
def test_check_key
|
||||
for key in @keys
|
||||
assert_equal(key.check_key, true)
|
||||
assert_equal(key.private_key?, true)
|
||||
assert_equal(key.public_key?, true)
|
||||
end
|
||||
end
|
||||
|
||||
def test_encoding
|
||||
for group in @groups
|
||||
for meth in [:to_der, :to_pem]
|
||||
txt = group.send(meth)
|
||||
gr = OpenSSL::PKey::EC::Group.new(txt)
|
||||
assert_equal(txt, gr.send(meth))
|
||||
|
||||
assert_equal(group.generator.to_bn, gr.generator.to_bn)
|
||||
assert_equal(group.cofactor, gr.cofactor)
|
||||
assert_equal(group.order, gr.order)
|
||||
assert_equal(group.seed, gr.seed)
|
||||
assert_equal(group.degree, gr.degree)
|
||||
end
|
||||
end
|
||||
|
||||
for key in @keys
|
||||
group = key.group
|
||||
|
||||
for meth in [:to_der, :to_pem]
|
||||
txt = key.send(meth)
|
||||
assert_equal(txt, OpenSSL::PKey::EC.new(txt).send(meth))
|
||||
end
|
||||
|
||||
bn = key.public_key.to_bn
|
||||
assert_equal(bn, OpenSSL::PKey::EC::Point.new(group, bn).to_bn)
|
||||
end
|
||||
end
|
||||
|
||||
def test_set_keys
|
||||
for key in @keys
|
||||
k = OpenSSL::PKey::EC.new
|
||||
k.group = key.group
|
||||
k.private_key = key.private_key
|
||||
k.public_key = key.public_key
|
||||
|
||||
compare_keys(key, k)
|
||||
end
|
||||
end
|
||||
|
||||
def test_dsa_sign_verify
|
||||
for key in @keys
|
||||
sig = key.dsa_sign_asn1(@data1)
|
||||
assert_equal(key.dsa_verify_asn1(@data1, sig), true)
|
||||
|
||||
assert_raises(OpenSSL::PKey::ECError) { key.dsa_sign_asn1(@data2) }
|
||||
end
|
||||
end
|
||||
|
||||
def test_dh_compute_key
|
||||
for key in @keys
|
||||
k = OpenSSL::PKey::EC.new(key.group)
|
||||
k.generate_key
|
||||
|
||||
puba = key.public_key
|
||||
pubb = k.public_key
|
||||
a = key.dh_compute_key(pubb)
|
||||
b = k.dh_compute_key(puba)
|
||||
assert_equal(a, b)
|
||||
end
|
||||
end
|
||||
|
||||
# test Group: asn1_flag, point_conversion
|
||||
|
||||
end
|
||||
|
||||
end
|
Загрузка…
Ссылка в новой задаче