Comparison

spec/util_crypto_spec.lua @ 12802:4a8740e01813

Merge 0.12->trunk
author Kim Alvefur <zash@zash.se>
date Mon, 12 Dec 2022 07:10:54 +0100
parent 12737:924bc1c8d0d9
child 12837:d3ae47d8a7a7
comparison
equal deleted inserted replaced
12801:ebd6b4d8bf04 12802:4a8740e01813
1 local test_keys = require "spec.inputs.test_keys";
2
3 describe("util.crypto", function ()
4 local crypto = require "util.crypto";
5 local random = require "util.random";
6
7 describe("generate_ed25519_keypair", function ()
8 local keypair = crypto.generate_ed25519_keypair();
9 assert.is_not_nil(keypair);
10 assert.equal("ED25519", keypair:get_type());
11 end)
12
13 describe("import_private_pem", function ()
14 it("can import ECDSA keys", function ()
15 local ecdsa_key = crypto.import_private_pem(test_keys.ecdsa_private_pem);
16 assert.equal("id-ecPublicKey", ecdsa_key:get_type());
17 end);
18
19 it("can import EdDSA (Ed25519) keys", function ()
20 local ed25519_key = crypto.import_private_pem(crypto.generate_ed25519_keypair():private_pem());
21 assert.equal("ED25519", ed25519_key:get_type());
22 end);
23
24 it("can import RSA keys", function ()
25 -- TODO
26 end);
27
28 it("rejects invalid keys", function ()
29 assert.is_nil(crypto.import_private_pem(test_keys.eddsa_public_pem));
30 assert.is_nil(crypto.import_private_pem(test_keys.ecdsa_public_pem));
31 assert.is_nil(crypto.import_private_pem("foo"));
32 assert.is_nil(crypto.import_private_pem(""));
33 end);
34 end);
35
36 describe("import_public_pem", function ()
37 it("can import ECDSA public keys", function ()
38 local ecdsa_key = crypto.import_public_pem(test_keys.ecdsa_public_pem);
39 assert.equal("id-ecPublicKey", ecdsa_key:get_type());
40 end);
41
42 it("can import EdDSA (Ed25519) public keys", function ()
43 local ed25519_key = crypto.import_public_pem(test_keys.eddsa_public_pem);
44 assert.equal("ED25519", ed25519_key:get_type());
45 end);
46
47 it("can import RSA public keys", function ()
48 -- TODO
49 end);
50 end);
51
52 describe("PEM export", function ()
53 it("works", function ()
54 local ecdsa_key = crypto.import_public_pem(test_keys.ecdsa_public_pem);
55 assert.equal("id-ecPublicKey", ecdsa_key:get_type());
56 assert.equal(test_keys.ecdsa_public_pem, ecdsa_key:public_pem());
57
58 assert.has_error(function ()
59 -- Fails because private key is not available
60 ecdsa_key:private_pem();
61 end);
62
63 local ecdsa_private_key = crypto.import_private_pem(test_keys.ecdsa_private_pem);
64 assert.equal(test_keys.ecdsa_private_pem, ecdsa_private_key:private_pem());
65 end);
66 end);
67
68 describe("sign/verify with", function ()
69 local test_cases = {
70 ed25519 = {
71 crypto.ed25519_sign, crypto.ed25519_verify;
72 key = crypto.import_private_pem(test_keys.eddsa_private_pem);
73 sig_length = 64;
74 };
75 ecdsa = {
76 crypto.ecdsa_sha256_sign, crypto.ecdsa_sha256_verify;
77 key = crypto.import_private_pem(test_keys.ecdsa_private_pem);
78 };
79 };
80 for test_name, test in pairs(test_cases) do
81 local key = test.key;
82 describe(test_name, function ()
83 it("works", function ()
84 local sign, verify = test[1], test[2];
85 local sig = assert(sign(key, "Hello world"));
86 assert.is_string(sig);
87 if test.sig_length then
88 assert.equal(test.sig_length, #sig);
89 end
90
91 do
92 local ok = verify(key, "Hello world", sig);
93 assert.is_truthy(ok);
94 end
95 do -- Incorrect signature
96 local ok = verify(key, "Hello world", sig:sub(1, -2)..string.char((sig:byte(-1)+1)%255));
97 assert.is_falsy(ok);
98 end
99 do -- Incorrect message
100 local ok = verify(key, "Hello earth", sig);
101 assert.is_falsy(ok);
102 end
103 do -- Incorrect message (embedded NUL)
104 local ok = verify(key, "Hello world\0foo", sig);
105 assert.is_falsy(ok);
106 end
107 end);
108 end);
109 end
110 end);
111
112 describe("ECDSA signatures", function ()
113 local hex = require "util.hex";
114 local sig = hex.decode((([[
115 304402203e936e7b0bc62887e0e9d675afd08531a930384cfcf301
116 f25d13053a2ebf141d02205a5a7c7b7ac5878d004cb79b17b39346
117 6b0cd1043718ffc31c153b971d213a8e
118 ]]):gsub("%s+", "")));
119 it("can be parsed", function ()
120 local r, s = crypto.parse_ecdsa_signature(sig, 32);
121 assert.is_string(r);
122 assert.is_string(s);
123 assert.equal(32, #r);
124 assert.equal(32, #s);
125 end);
126 it("fails to parse invalid signatures", function ()
127 local invalid_sigs = {
128 "";
129 "\000";
130 string.rep("\000", 64);
131 string.rep("\000", 72);
132 string.rep("\000", 256);
133 string.rep("\255", 72);
134 string.rep("\255", 3);
135 };
136 for _, invalid_sig in ipairs(invalid_sigs) do
137 local r, s = crypto.parse_ecdsa_signature(invalid_sig, 32);
138 assert.is_nil(r);
139 assert.is_nil(s);
140 end
141 end);
142 it("can be built", function ()
143 local r, s = crypto.parse_ecdsa_signature(sig, 32);
144 local rebuilt_sig = crypto.build_ecdsa_signature(r, s);
145 assert.equal(sig, rebuilt_sig);
146 end);
147 end);
148
149 describe("AES-GCM encryption", function ()
150 it("works", function ()
151 local message = "foo\0bar";
152 local key_128_bit = random.bytes(16);
153 local key_256_bit = random.bytes(32);
154 local test_cases = {
155 { crypto.aes_128_gcm_encrypt, crypto.aes_128_gcm_decrypt, key = key_128_bit };
156 { crypto.aes_256_gcm_encrypt, crypto.aes_256_gcm_decrypt, key = key_256_bit };
157 };
158 for _, params in pairs(test_cases) do
159 local iv = params.iv or random.bytes(12);
160 local encrypted = params[1](params.key, iv, message);
161 assert.not_equal(message, encrypted);
162 local decrypted = params[2](params.key, iv, encrypted);
163 assert.equal(message, decrypted);
164 end
165 end);
166 end);
167 end);