templates.test_check_signature

 1import smartpy as sp
 2
 3
 4@sp.module
 5def main():
 6    class TestCheckSignature(sp.Contract):
 7        def __init__(self, boss_pk):
 8            self.data.currentValue = "Hello World"
 9            self.data.counter = 0
10            self.data.bossPublicKey = boss_pk
11
12        @sp.entrypoint
13        def setCurrentValue(self, params):
14            # We will also need Michelson SELF and CHAIN_ID to avoid all replay attacks:
15            thingToSign = sp.pack(
16                sp.record(
17                    o=self.data.currentValue, n=params.newValue, c=self.data.counter
18                )
19            )
20            assert sp.check_signature(
21                self.data.bossPublicKey, params.userSignature, thingToSign
22            )
23            self.data.currentValue = params.newValue
24            self.data.counter = self.data.counter + 1
25
26
27@sp.add_test()
28def test():
29    scenario = sp.test_scenario("CheckSignature", main)
30    scenario.h1("Check Signature")
31    rightful_owner = sp.test_account("Alice")
32    attacker = sp.test_account("Robert")
33    c1 = main.TestCheckSignature(rightful_owner.public_key)
34
35    scenario += c1
36    # Let's build a successful call:
37    #
38    scenario.h2("Successful Call")
39    first_message_packed = sp.pack(sp.record(o="Hello World", n="should work", c=0))
40    sig_from_alice = sp.make_signature(
41        secret_key=rightful_owner.secret_key,
42        message=first_message_packed,
43        message_format="Raw",
44    )
45    c1.setCurrentValue(
46        newValue="should work", userSignature=sig_from_alice, _valid=True
47    )
48    #
49    scenario.h2("Replay Attack")
50    scenario.p(
51        "Trying to reuse the same signature is blocked by the value of the counter."
52    )
53    c1.setCurrentValue(
54        newValue="should work", userSignature=sig_from_alice, _valid=False
55    )
56    #
57    #
58    scenario.h2("Signature From Wrong Secret Key")
59    scenario.p("Signing the right thing from a different secret-key.")
60    #
61    #
62    # Gives:
63    second_message_packed = sp.pack(
64        sp.record(o="should work", n="Hello again World", c=1)
65    )
66    sig_from_bob = sp.make_signature(
67        secret_key=attacker.secret_key,
68        message=second_message_packed,
69        message_format="Raw",
70    )
71    c1.setCurrentValue(
72        newValue="Hello again World", userSignature=sig_from_bob, _valid=False
73    )
74    #
75    scenario.h2("Second Successful Call")
76    scenario.p(
77        "Showing that the previous call failed <b>because</b> of the secret-key (signing same bytes)."
78    )
79    sig_from_alice = sp.make_signature(
80        secret_key=rightful_owner.secret_key,
81        message=second_message_packed,
82        message_format="Raw",
83    )
84    c1.setCurrentValue(
85        newValue="Hello again World", userSignature=sig_from_alice, _valid=True
86    )