diff --git a/opentimestamps/core/op.py b/opentimestamps/core/op.py index b67a2b7..d351d25 100644 --- a/opentimestamps/core/op.py +++ b/opentimestamps/core/op.py @@ -347,3 +347,6 @@ def _do_op_call(self, msg): r = sha3.keccak_256(bytes(msg)).digest() assert len(r) == self.DIGEST_LENGTH return r + +from opentimestamps.core.secp256k1 import OpSecp256k1Commitment + diff --git a/opentimestamps/core/secp256k1.py b/opentimestamps/core/secp256k1.py index 48de306..e99b8dc 100644 --- a/opentimestamps/core/secp256k1.py +++ b/opentimestamps/core/secp256k1.py @@ -9,6 +9,27 @@ # modified, propagated, or distributed except according to the terms contained # in the LICENSE file. +import hashlib + +from opentimestamps.core.op import BinaryOp, MsgValueError + +@BinaryOp._register_op +class OpSecp256k1Commitment(BinaryOp): + """Execute the map commit -> [P + sha256(P||commit)G]_x for a given secp256k1 point P""" + TAG = b'\x09' + TAG_NAME = 'secp256k1commitment' + + def _do_op_call(self, msg): + hasher = hashlib.sha256() + pt = Point.decode(self[0]) + hasher.update(pt.encode()) + hasher.update(msg) + tweak = int.from_bytes(hasher.digest(), 'big') + tweak_pt = SECP256K1_GEN.scalar_mul(tweak) + final_pt = pt.add(tweak_pt) + return final_pt.x.to_bytes(32, 'big') + + ## What follows is a lot of inefficient but explicit secp256k1 math class Point(object): inf = True diff --git a/opentimestamps/tests/core/test_secp256k1.py b/opentimestamps/tests/core/test_secp256k1.py index 3d2226b..6eaeed5 100644 --- a/opentimestamps/tests/core/test_secp256k1.py +++ b/opentimestamps/tests/core/test_secp256k1.py @@ -9,6 +9,7 @@ # modified, propagated, or distributed except according to the terms contained # in the LICENSE file. +import hashlib import binascii import unittest @@ -20,7 +21,7 @@ def test_point_rt(self): gen = SECP256K1_GEN encode = gen.encode() self.assertEqual(encode, binascii.unhexlify("0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798")) - gen2 = Point().decode(encode) + gen2 = Point.decode(encode) self.assertEqual(gen, gen2) def test_pinv(self): @@ -99,3 +100,9 @@ def test_scalar_mul(self): self.assertEqual(p2.scalar_mul(-1), np2) self.assertEqual(p1.scalar_mul(3), p3) + def test_op_signtocontract(self): + pt_encode = binascii.unhexlify("0308aec434612f56df3f02c4e678260424415882ebd3efc16d52e3f9c1e39afdb0") + msg = hashlib.sha256("This is andytoshi on 2017-05-16 21:30 UTC".encode()).digest() + result = binascii.unhexlify("d386ef692770fcecad43362cf541858662e4ebe31d3ad04d196f94168897947a") + self.assertEqual(OpSecp256k1Commitment(pt_encode)(msg), result) +