Class: Secp256k1::Context
- Inherits:
-
Object
- Object
- Secp256k1::Context
- Defined in:
- lib/rbsecp256k1/context.rb,
ext/rbsecp256k1/rbsecp256k1.c
Overview
Wrapper around a secp256k1_context object.
Class Method Summary collapse
-
.create ⇒ Secp256k1::Context
Create a new randomized context.
-
.create_unrandomized ⇒ Secp256k1::Context
Create a new non-randomized context.
Instance Method Summary collapse
-
#ecdh(point, scalar) ⇒ Secp256k1::SharedSecret
Compute EC Diffie-Hellman secret in constant time.
-
#generate_key_pair ⇒ Secp256k1::KeyPair
Generates a new random key pair.
-
#initialize(*args) ⇒ Secp256k1::Context
constructor
Initialize a new context.
-
#key_pair_from_private_key(in_private_key_data) ⇒ Secp256k1::KeyPair
Converts binary private key data into a new key pair.
-
#recoverable_signature_from_compact(in_compact_sig, in_recovery_id) ⇒ Secp256k1::RecoverableSignature
Loads recoverable signature from compact representation and recovery ID.
-
#sign(in_private_key, in_hash32) ⇒ Secp256k1::Signature
Computes the ECDSA signature of the data using the secp256k1 elliptic curve.
-
#sign_recoverable(in_private_key, in_hash32) ⇒ Secp256k1::RecoverableSignature
Computes the recoverable ECDSA signature of data signed with private key.
-
#verify(in_signature, in_pubkey, in_hash32) ⇒ Boolean
Verifies that signature matches public key and data.
Constructor Details
#initialize(*args) ⇒ Secp256k1::Context
Initialize a new context.
Context initialization should be infrequent as it is an expensive operation.
1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 |
# File 'ext/rbsecp256k1/rbsecp256k1.c', line 1135
static VALUE
Context_initialize(int argc, const VALUE* argv, VALUE self)
{
Context *context;
unsigned char *seed32;
VALUE context_randomization_bytes;
VALUE opts;
static ID kwarg_ids;
context_randomization_bytes = Qnil;
if (!kwarg_ids)
{
CONST_ID(kwarg_ids, "context_randomization_bytes");
}
TypedData_Get_Struct(self, Context, &Context_DataType, context);
context->ctx = secp256k1_context_create(
SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY
);
// Handle optional second argument containing random bytes to use for
// randomization. We pass ":" to rb_scan_args to say that we expect keyword
// arguments. We then parse the opts result of the scan in order to grab
// context_randomization_bytes from the hash.
rb_scan_args(argc, argv, ":", &opts);
rb_get_kwargs(opts, &kwarg_ids, 0, 1, &context_randomization_bytes);
// We need this check because rb_get_kwargs will set the result to Qundef if
// the keyword argument is not provided. This lets us use the NIL_P
// predicate.
if (context_randomization_bytes == Qundef)
{
context_randomization_bytes = Qnil;
}
if (!NIL_P(context_randomization_bytes)) // Random bytes given
{
Check_Type(context_randomization_bytes, T_STRING);
if (RSTRING_LEN(context_randomization_bytes) != 32)
{
rb_raise(
Secp256k1_Error_class,
"context_randomization_bytes must be 32 bytes in length"
);
}
seed32 = (unsigned char*)StringValuePtr(context_randomization_bytes);
// Randomize the context at initialization time rather than before calls so
// the same context can be used across threads safely.
if (secp256k1_context_randomize(context->ctx, seed32) != 1)
{
rb_raise(
Secp256k1_Error_class,
"context randomization failed"
);
}
}
return self;
}
|
Class Method Details
.create ⇒ Secp256k1::Context
Create a new randomized context.
11 12 13 |
# File 'lib/rbsecp256k1/context.rb', line 11 def self.create new(context_randomization_bytes: SecureRandom.random_bytes(32)) end |
.create_unrandomized ⇒ Secp256k1::Context
Create a new non-randomized context.
18 19 20 |
# File 'lib/rbsecp256k1/context.rb', line 18 def self.create_unrandomized new end |
Instance Method Details
#ecdh(point, scalar) ⇒ Secp256k1::SharedSecret
Compute EC Diffie-Hellman secret in constant time.
Creates a new shared secret from public_key and private_key.
1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 |
# File 'ext/rbsecp256k1/rbsecp256k1.c', line 1453
static VALUE
Context_ecdh(VALUE self, VALUE point, VALUE scalar)
{
Context *context;
PublicKey *public_key;
PrivateKey *private_key;
SharedSecret *shared_secret;
VALUE result;
TypedData_Get_Struct(self, Context, &Context_DataType, context);
TypedData_Get_Struct(point, PublicKey, &PublicKey_DataType, public_key);
TypedData_Get_Struct(scalar, PrivateKey, &PrivateKey_DataType, private_key);
result = SharedSecret_alloc(Secp256k1_SharedSecret_class);
TypedData_Get_Struct(
result, SharedSecret, &SharedSecret_DataType, shared_secret
);
if (secp256k1_ecdh(context->ctx,
shared_secret->data,
&(public_key->pubkey),
(unsigned char*)private_key->data,
NULL,
NULL) != 1)
{
rb_raise(Secp256k1_Error_class, "invalid scalar provided to ecdh");
}
rb_iv_set(result, "@data", rb_str_new((char*)shared_secret->data, 32));
return result;
}
|
#generate_key_pair ⇒ Secp256k1::KeyPair
Generates a new random key pair.
25 26 27 |
# File 'lib/rbsecp256k1/context.rb', line 25 def generate_key_pair key_pair_from_private_key(SecureRandom.random_bytes(32)) end |
#key_pair_from_private_key(in_private_key_data) ⇒ Secp256k1::KeyPair
Converts binary private key data into a new key pair.
1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 |
# File 'ext/rbsecp256k1/rbsecp256k1.c', line 1206
static VALUE
Context_key_pair_from_private_key(VALUE self, VALUE in_private_key_data)
{
Context *context;
VALUE public_key;
VALUE private_key;
unsigned char *private_key_data;
Check_Type(in_private_key_data, T_STRING);
TypedData_Get_Struct(self, Context, &Context_DataType, context);
if (RSTRING_LEN(in_private_key_data) != 32)
{
rb_raise(Secp256k1_Error_class, "private key data must be 32 bytes in length");
}
private_key_data = (unsigned char*)StringValuePtr(in_private_key_data);
private_key = PrivateKey_create(private_key_data);
public_key = PublicKey_create_from_private_key(context, private_key_data);
return rb_funcall(
Secp256k1_KeyPair_class,
rb_intern("new"),
2,
public_key,
private_key
);
}
|
#recoverable_signature_from_compact(in_compact_sig, in_recovery_id) ⇒ Secp256k1::RecoverableSignature
Loads recoverable signature from compact representation and recovery ID.
1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 |
# File 'ext/rbsecp256k1/rbsecp256k1.c', line 1390
static VALUE
Context_recoverable_signature_from_compact(
VALUE self, VALUE in_compact_sig, VALUE in_recovery_id)
{
Context *context;
RecoverableSignature *recoverable_signature;
unsigned char *compact_sig;
int recovery_id;
VALUE result;
Check_Type(in_compact_sig, T_STRING);
Check_Type(in_recovery_id, T_FIXNUM);
TypedData_Get_Struct(self, Context, &Context_DataType, context);
compact_sig = (unsigned char*)StringValuePtr(in_compact_sig);
recovery_id = FIX2INT(in_recovery_id);
if (RSTRING_LEN(in_compact_sig) != 64)
{
rb_raise(Secp256k1_Error_class, "compact signature is not 64 bytes");
}
if (recovery_id < 0 || recovery_id > 3)
{
rb_raise(Secp256k1_Error_class, "invalid recovery ID, must be in range [0, 3]");
}
result = RecoverableSignature_alloc(Secp256k1_RecoverableSignature_class);
TypedData_Get_Struct(
result,
RecoverableSignature,
&RecoverableSignature_DataType,
recoverable_signature
);
if (secp256k1_ecdsa_recoverable_signature_parse_compact(
secp256k1_context_no_precomp,
&(recoverable_signature->sig),
compact_sig,
recovery_id) == 1)
{
recoverable_signature->ctx = secp256k1_context_clone(context->ctx);
return result;
}
rb_raise(Secp256k1_DeserializationError_class, "unable to parse recoverable signature");
}
|
#sign(in_private_key, in_hash32) ⇒ Secp256k1::Signature
Computes the ECDSA signature of the data using the secp256k1 elliptic curve.
1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 |
# File 'ext/rbsecp256k1/rbsecp256k1.c', line 1246
static VALUE
Context_sign(VALUE self, VALUE in_private_key, VALUE in_hash32)
{
unsigned char *hash32;
PrivateKey *private_key;
Context *context;
Signature *signature;
VALUE signature_result;
Check_Type(in_hash32, T_STRING);
if (RSTRING_LEN(in_hash32) != 32)
{
rb_raise(Secp256k1_Error_class, "in_hash32 is not 32 bytes in length");
}
TypedData_Get_Struct(self, Context, &Context_DataType, context);
TypedData_Get_Struct(in_private_key, PrivateKey, &PrivateKey_DataType, private_key);
hash32 = (unsigned char*)StringValuePtr(in_hash32);
signature_result = Signature_alloc(Secp256k1_Signature_class);
TypedData_Get_Struct(signature_result, Signature, &Signature_DataType, signature);
// Attempt to sign the hash of the given data
if (SUCCESS(SignData(context->ctx,
hash32,
private_key->data,
&(signature->sig))))
{
return signature_result;
}
rb_raise(Secp256k1_Error_class, "unable to compute signature");
}
|
#sign_recoverable(in_private_key, in_hash32) ⇒ Secp256k1::RecoverableSignature
Computes the recoverable ECDSA signature of data signed with private key.
1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 |
# File 'ext/rbsecp256k1/rbsecp256k1.c', line 1337
static VALUE
Context_sign_recoverable(VALUE self, VALUE in_private_key, VALUE in_hash32)
{
Context *context;
PrivateKey *private_key;
RecoverableSignature *recoverable_signature;
unsigned char *hash32;
VALUE result;
Check_Type(in_hash32, T_STRING);
if (RSTRING_LEN(in_hash32) != 32)
{
rb_raise(Secp256k1_Error_class, "in_hash32 is not 32 bytes in length");
}
TypedData_Get_Struct(self, Context, &Context_DataType, context);
TypedData_Get_Struct(
in_private_key, PrivateKey, &PrivateKey_DataType, private_key
);
hash32 = (unsigned char*)StringValuePtr(in_hash32);
result = RecoverableSignature_alloc(Secp256k1_RecoverableSignature_class);
TypedData_Get_Struct(
result,
RecoverableSignature,
&RecoverableSignature_DataType,
recoverable_signature
);
if (SUCCESS(RecoverableSignData(context->ctx,
hash32,
private_key->data,
&(recoverable_signature->sig))))
{
recoverable_signature->ctx = secp256k1_context_clone(context->ctx);
return result;
}
rb_raise(Secp256k1_Error_class, "unable to compute recoverable signature");
}
|
#verify(in_signature, in_pubkey, in_hash32) ⇒ Boolean
Verifies that signature matches public key and data.
1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 |
# File 'ext/rbsecp256k1/rbsecp256k1.c', line 1292
static VALUE
Context_verify(VALUE self, VALUE in_signature, VALUE in_pubkey, VALUE in_hash32)
{
Context *context;
PublicKey *public_key;
Signature *signature;
unsigned char *hash32;
Check_Type(in_hash32, T_STRING);
if (RSTRING_LEN(in_hash32) != 32)
{
rb_raise(Secp256k1_Error_class, "in_hash32 is not 32-bytes in length");
}
TypedData_Get_Struct(self, Context, &Context_DataType, context);
TypedData_Get_Struct(in_pubkey, PublicKey, &PublicKey_DataType, public_key);
TypedData_Get_Struct(in_signature, Signature, &Signature_DataType, signature);
hash32 = (unsigned char*)StringValuePtr(in_hash32);
if (secp256k1_ecdsa_verify(context->ctx,
&(signature->sig),
hash32,
&(public_key->pubkey)) == 1)
{
return Qtrue;
}
return Qfalse;
}
|