3 """Test sign/verify commands."""
8 from testlib import util, cmd, check
9 from testlib.proc import Tinc
10 from testlib.test import Test
13 -----BEGIN ED25519 PRIVATE KEY-----
14 4Q8bJqfN60s0tOiZdAhAWLgB9+o947cta2WMXmQIz8mCdBdcphzhp23Wt2vUzfQ6
15 XHt9+5IqidIw/lLXG61Nbc6IZ+4Fy1XOO1uJ6j4hqIKjdSytD2Vb7MPlNJfPdCDu
16 -----END ED25519 PRIVATE KEY-----
20 Ed25519PublicKey = nOSmPehc9ljTtbi+IeoKiyYnkc7gd12OzTZTy3TnwgL
24 # Do not replace \n or this will break on Windows if cloned with native line endings
25 SIGNED_BYTES = """Signature = foo 1653397516 \
26 T8Bjg7dc7IjsCrZQC/20qLRsWPlrbthnjyDHQM0BMLoTeAHbLt0fxP5CbTy7Cifgg7P0K179GeahBFsnaIr4MA\n\
33 RAW_DATA = tempfile.mktemp()
35 with open(RAW_DATA, "wb") as raw_file:
36 raw_file.write(util.random_string(64).encode("utf-8"))
39 def init(ctx: Test) -> Tinc:
40 """Initialize a node."""
48 def test_sign_errors(foo: Tinc) -> None:
49 """Test `sign` error conditions."""
51 _, err = foo.cmd("sign", "foo", "bar", code=1)
52 check.is_in("Too many arguments", err)
54 _, err = foo.cmd("sign", "/nonexistent", code=1)
55 check.is_in("Could not open", err)
57 os.truncate(foo.sub("ed25519_key.priv"), 0)
58 _, err = foo.cmd("sign", RAW_DATA, code=1)
59 check.is_in("Could not read private key from", err)
61 os.remove(foo.sub("ed25519_key.priv"))
62 _, err = foo.cmd("sign", RAW_DATA, code=1)
63 check.is_in("Could not open", err)
66 def test_verify(foo: Tinc) -> None:
67 """Test `verify` of data known to work."""
69 signed_file = tempfile.mktemp()
70 with open(signed_file, "wb") as f:
74 util.write_text(foo.sub("tinc.conf"), f"Name = {foo}")
75 util.write_text(foo.sub(f"hosts/{foo}"), HOST)
76 util.write_text(foo.sub("ed25519_key.priv"), PRIV_KEY)
78 for name in ".", foo.name:
79 foo.cmd("verify", name, stdin=SIGNED_BYTES)
80 foo.cmd("verify", name, signed_file)
83 foo.cmd("verify", "*", stdin=SIGNED_BYTES)
84 foo.cmd("verify", "*", signed_file)
86 os.remove(signed_file)
89 def test_verify_errors(foo: Tinc) -> None:
90 """Test `verify` error conditions."""
92 _, err = foo.cmd("verify", code=1)
93 check.is_in("Not enough arguments", err)
95 _, err = foo.cmd("verify", foo.name, "bar", "baz", code=1)
96 check.is_in("Too many arguments", err)
98 _, err = foo.cmd("verify", "foo@", code=1)
99 check.is_in("Invalid node name", err)
101 _, err = foo.cmd("verify", foo.name, "/nonexistent", code=1)
102 check.is_in("Could not open", err)
104 _, err = foo.cmd("verify", foo.name, stdin="", code=1)
105 check.is_in("Invalid input", err)
107 _, err = foo.cmd("verify", foo.name, stdin="Signature = foo bar baz", code=1)
108 check.is_in("Invalid input", err)
113 "D25ACFD89jaV9+6g9TNMDTDxH8JGd3wLMv/YNMwXbrj9Bos9q6IW/tuFPxGxYNQ6qAc93XFzkH5u7Gw+Z86GDA\n"
115 _, err = foo.cmd("verify", foo.name, stdin=sig, code=1)
116 check.is_in(f"Signature is not made by {foo}", err)
119 f"Signature = {foo} "
121 "D25ACFD89jaV9+6g9TNMDTDxH8JGd3wLMv/YNMwXbrj9Bos9q6IW/tuFPxGxYNQ6qAc93XFzkH5u7Gw+Z86GDA\n"
123 _, err = foo.cmd("verify", foo.name, stdin=sig, code=1)
124 check.is_in("Invalid signature", err)
126 util.write_text(foo.sub(f"hosts/{foo}"), "foobar")
127 _, err = foo.cmd("verify", foo.name, stdin=sig, code=1)
128 check.is_in("Could not read public key from", err)
131 def test_sign_verify(foo: Tinc, bar: Tinc) -> None:
132 """Test `sign` and pass its result to `verify`."""
134 signed, _ = foo.cmd("sign", RAW_DATA, stdin=b"")
135 assert isinstance(signed, bytes)
137 signed_file = tempfile.mktemp()
138 with open(signed_file, "wb") as f:
141 for name in ".", foo.name:
142 foo.cmd("verify", name, signed_file)
143 foo.cmd("verify", name, stdin=signed)
146 foo.cmd("verify", "*", signed_file)
147 foo.cmd("verify", "*", stdin=signed)
149 os.remove(signed_file)
151 cmd.exchange(foo, bar)
154 signed, _ = foo.cmd("sign", RAW_DATA)
155 bar.cmd("verify", "*", stdin=signed)
157 signed, _ = bar.cmd("sign", RAW_DATA)
158 foo.cmd("verify", bar.name, stdin=signed)
161 with Test("test errors in `sign`") as context:
162 test_sign_errors(init(context))
164 with Test("test errors in `verify`") as context:
165 test_verify_errors(init(context))
167 with Test("test successful `verify`") as context:
168 test_verify(init(context))
170 with Test("test `sign` and `verify`") as context:
171 test_sign_verify(init(context), init(context))