1 #define BOOST_TEST_DYN_LINK
2 #define BOOST_TEST_NO_MAIN
6 #include <boost/test/unit_test.hpp>
7 #include <boost/assign/list_of.hpp>
11 #include "dnsseckeeper.hh"
12 #include "dnssecinfra.hh"
16 #include <unordered_map>
18 // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables): Boost stuff.
19 BOOST_AUTO_TEST_SUITE(test_signers
)
27 std::vector
<uint8_t> signature
;
28 std::string zoneRepresentation
;
30 std::string rfcMsgDump
;
31 std::string rfcB64Signature
;
41 static const SignerParams rsaSha256SignerParams
= SignerParams
43 .iscMap
= "Algorithm: 8\n"
44 "Modulus: qtunSiHnYq4XRLBehKAw1Glxb+48oIpAC7w3Jhpj570bb2uHt6orWGqnuyRtK8oqUi2ABoV0PFm8+IPgDMEdCQ==\n"
45 "PublicExponent: AQAB\n"
46 "PrivateExponent: MiItniUAngXzMeaGdWgDq/AcpvlCtOCcFlVt4TJRKkfp8DNRSxIxG53NNlOFkp1W00iLHqYC2GrH1qkKgT9l+Q==\n"
47 "Prime1: 3sZmM+5FKFy5xaRt0n2ZQOZ2C+CoKzVil6/al9LmYVs=\n"
48 "Prime2: xFcNWSIW6v8dDL2JQ1kxFDm/8RVeUSs1BNXXnvCjBGs=\n"
49 "Exponent1: WuUwhjfN1+4djlrMxHmisixWNfpwI1Eg7Ss/UXsnrMk=\n"
50 "Exponent2: vfMqas1cNsXRqP3Fym6D2Pl2BRuTQBv5E1B/ZrmQPTk=\n"
51 "Coefficient: Q10z43cA3hkwOkKsj5T0W5jrX97LBwZoY5lIjDCa4+M=\n",
54 "172a500b374158d1a64ba3073cdbbc319b2fdf2c",
56 .dsSHA256
= "1506 8 2 "
57 "253b099ff47b02c6ffa52695a30a94c6681c56befe0e71a5077d6f79514972f9",
59 .dsSHA384
= "1506 8 4 "
60 "22ea940600dc2d9a98b1126c26ac0dc5c91b31eb50fe784b"
61 "36ad675e9eecfe6573c1f85c53b6bc94580f3ac443d13c4c",
63 /* from https://github.com/CZ-NIC/knot/blob/master/src/dnssec/tests/sign.c */
65 0x93, 0x93, 0x5f, 0xd8, 0xa1, 0x2b, 0x4c, 0x0b, 0xf3, 0x67, 0x42, 0x13, 0x52,
66 0x00, 0x35, 0xdc, 0x09, 0xe0, 0xdf, 0xe0, 0x3e, 0xc2, 0xcf, 0x64, 0xab, 0x9f,
67 0x9f, 0x51, 0x5f, 0x5c, 0x27, 0xbe, 0x13, 0xd6, 0x17, 0x07, 0xa6, 0xe4, 0x3b,
68 0x63, 0x44, 0x85, 0x06, 0x13, 0xaa, 0x01, 0x3c, 0x58, 0x52, 0xa3, 0x98, 0x20,
69 0x65, 0x03, 0xd0, 0x40, 0xc8, 0xa0, 0xe9, 0xd2, 0xc0, 0x03, 0x5a, 0xab
72 .zoneRepresentation
= "256 3 8 "
73 "AwEAAarbp0oh52KuF0SwXoSgMNRpcW/uPKCKQAu8NyYaY+"
74 "e9G29rh7eqK1hqp7skbSvKKlItgAaFdDxZvPiD4AzBHQk=",
79 .rfcB64Signature
= "",
85 .algorithm
= DNSSECKeeper::RSASHA256
,
86 .isDeterministic
= true,
88 #if OPENSSL_VERSION_MAJOR >= 3
89 // OpenSSL 3.0.0 uses a generic key interface which stores the key PKCS#8-encoded.
90 .pem
= "-----BEGIN PRIVATE KEY-----\n"
91 "MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAqtunSiHnYq4XRLBe\n"
92 "hKAw1Glxb+48oIpAC7w3Jhpj570bb2uHt6orWGqnuyRtK8oqUi2ABoV0PFm8+IPg\n"
93 "DMEdCQIDAQABAkAyIi2eJQCeBfMx5oZ1aAOr8Bym+UK04JwWVW3hMlEqR+nwM1FL\n"
94 "EjEbnc02U4WSnVbTSIsepgLYasfWqQqBP2X5AiEA3sZmM+5FKFy5xaRt0n2ZQOZ2\n"
95 "C+CoKzVil6/al9LmYVsCIQDEVw1ZIhbq/x0MvYlDWTEUOb/xFV5RKzUE1dee8KME\n"
96 "awIgWuUwhjfN1+4djlrMxHmisixWNfpwI1Eg7Ss/UXsnrMkCIQC98ypqzVw2xdGo\n"
97 "/cXKboPY+XYFG5NAG/kTUH9muZA9OQIgQ10z43cA3hkwOkKsj5T0W5jrX97LBwZo\n"
99 "-----END PRIVATE KEY-----\n"
101 .pem
= "-----BEGIN RSA PRIVATE KEY-----\n"
102 "MIIBOgIBAAJBAKrbp0oh52KuF0SwXoSgMNRpcW/uPKCKQAu8NyYaY+e9G29rh7eq\n"
103 "K1hqp7skbSvKKlItgAaFdDxZvPiD4AzBHQkCAwEAAQJAMiItniUAngXzMeaGdWgD\n"
104 "q/AcpvlCtOCcFlVt4TJRKkfp8DNRSxIxG53NNlOFkp1W00iLHqYC2GrH1qkKgT9l\n"
105 "+QIhAN7GZjPuRShcucWkbdJ9mUDmdgvgqCs1Ypev2pfS5mFbAiEAxFcNWSIW6v8d\n"
106 "DL2JQ1kxFDm/8RVeUSs1BNXXnvCjBGsCIFrlMIY3zdfuHY5azMR5orIsVjX6cCNR\n"
107 "IO0rP1F7J6zJAiEAvfMqas1cNsXRqP3Fym6D2Pl2BRuTQBv5E1B/ZrmQPTkCIENd\n"
108 "M+N3AN4ZMDpCrI+U9FuY61/eywcGaGOZSIwwmuPj\n"
109 "-----END RSA PRIVATE KEY-----\n"
114 /* ECDSA-P256-SHA256 from
115 * https://github.com/CZ-NIC/knot/blob/master/src/dnssec/tests/sample_keys.h
118 static const SignerParams ecdsaSha256
= SignerParams
120 .iscMap
= "Algorithm: 13\n"
121 "PrivateKey: iyLIPdk3DOIxVmmSYlmTstbtUPiVlEyDX46psyCwNVQ=\n",
123 .dsSHA1
= "5345 13 1 "
124 "954103ac7c43810ce9f414e80f30ab1cbe49b236",
126 .dsSHA256
= "5345 13 2 "
127 "bac2107036e735b50f85006ce409a19a3438cab272e70769ebda032239a3d0ca",
129 .dsSHA384
= "5345 13 4 "
130 "a0ac6790483872be72a258314200a88ab75cdd70f66a18a0"
131 "9f0f414c074df0989fdb1df0e67d82d4312cda67b93a76c1",
133 /* from https://github.com/CZ-NIC/knot/blob/master/src/dnssec/tests/sign.c */
135 0xa2, 0x95, 0x76, 0xb5, 0xf5, 0x7e, 0xbd, 0xdd, 0xf5, 0x62, 0xa2, 0xc3, 0xa4,
136 0x8d, 0xd4, 0x53, 0x5c, 0xba, 0x29, 0x71, 0x8c, 0xcc, 0x28, 0x7b, 0x58, 0xf3,
137 0x1e, 0x4e, 0x58, 0xe2, 0x36, 0x7e, 0xa0, 0x1a, 0xb6, 0xe6, 0x29, 0x71, 0x1b,
138 0xd3, 0x8c, 0x88, 0xc3, 0xee, 0x12, 0x0e, 0x69, 0x70, 0x55, 0x99, 0xec, 0xd5,
139 0xf6, 0x4f, 0x4b, 0xe2, 0x41, 0xd9, 0x10, 0x7e, 0x67, 0xe5, 0xad, 0x2f
142 .zoneRepresentation
= "256 3 13 "
143 "8uD7C4THTM/w7uhryRSToeE/jKT78/p853RX0L5EwrZ"
144 "rSLBubLPiBw7gbvUP6SsIga5ZQ4CSAxNmYA/gZsuXzA==",
149 .rfcB64Signature
= "",
155 .algorithm
= DNSSECKeeper::ECDSA256
,
156 .isDeterministic
= false,
158 #if OPENSSL_VERSION_MAJOR >= 3
159 // OpenSSL 3.0.0 uses a generic key interface which stores the key PKCS#8-encoded.
160 .pem
= "-----BEGIN PRIVATE KEY-----\n"
161 "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgiyLIPdk3DOIxVmmS\n"
162 "YlmTstbtUPiVlEyDX46psyCwNVShRANCAATy4PsLhMdMz/Du6GvJFJOh4T+MpPvz\n"
163 "+nzndFfQvkTCtmtIsG5ss+IHDuBu9Q/pKwiBrllDgJIDE2ZgD+Bmy5fM\n"
164 "-----END PRIVATE KEY-----\n"
166 .pem
= "-----BEGIN EC PRIVATE KEY-----\n"
167 "MHcCAQEEIIsiyD3ZNwziMVZpkmJZk7LW7VD4lZRMg1+OqbMgsDVUoAoGCCqGSM49\n"
168 "AwEHoUQDQgAE8uD7C4THTM/w7uhryRSToeE/jKT78/p853RX0L5EwrZrSLBubLPi\n"
169 "Bw7gbvUP6SsIga5ZQ4CSAxNmYA/gZsuXzA==\n"
170 "-----END EC PRIVATE KEY-----\n"
175 /* Ed25519 from https://github.com/CZ-NIC/knot/blob/master/src/dnssec/tests/sample_keys.h,
176 * also from rfc8080 section 6.1
179 static const SignerParams ed25519
= SignerParams
{
180 .iscMap
= "Algorithm: 15\n"
181 "PrivateKey: ODIyNjAzODQ2MjgwODAxMjI2NDUxOTAyMDQxNDIyNjI=\n",
183 .dsSHA1
= "3612 15 1 "
184 "501249721e1f09a79d30d5c6c4dca1dc1da4ed5d",
186 .dsSHA256
= "3612 15 2 "
187 "1b1c8766b2a96566ff196f77c0c4194af86aaa109c5346ff60231a27d2b07ac0",
189 .dsSHA384
= "3612 15 4 "
190 "d11831153af4985efbd0ae792c967eb4aff3c35488db95f7"
191 "e2f85dcec74ae8f59f9a72641798c91c67c675db1d710c18",
193 /* from https://github.com/CZ-NIC/knot/blob/master/src/dnssec/tests/sign.c */
195 0x0a, 0x9e, 0x51, 0x5f, 0x16, 0x89, 0x49, 0x27, 0x0e, 0x98, 0x34, 0xd3, 0x48,
196 0xef, 0x5a, 0x6e, 0x85, 0x2f, 0x7c, 0xd6, 0xd7, 0xc8, 0xd0, 0xf4, 0x2c, 0x68,
197 0x8c, 0x1f, 0xf7, 0xdf, 0xeb, 0x7c, 0x25, 0xd6, 0x1a, 0x76, 0x3e, 0xaf, 0x28,
198 0x1f, 0x1d, 0x08, 0x10, 0x20, 0x1c, 0x01, 0x77, 0x1b, 0x5a, 0x48, 0xd6, 0xe5,
199 0x1c, 0xf9, 0xe3, 0xe0, 0x70, 0x34, 0x5e, 0x02, 0x49, 0xfb, 0x9e, 0x05
202 .zoneRepresentation
= "256 3 15 l02Woi0iS8Aa25FQkUd9RMzZHJpBoRQwAQEX1SxZJA4=",
206 // vector extracted from https://gitlab.labs.nic.cz/labs/ietf/blob/master/dnskey.py (rev
207 // 476d6ded) by printing signature_data
208 .rfcMsgDump
= "00 0f 0f 02 00 00 0e 10 55 d4 fc 60 55 b9 4c e0 0e 1d 07 65 78 "
209 "61 6d 70 6c 65 03 63 6f 6d 00 07 65 78 61 6d 70 6c 65 03 63 6f "
210 "6d 00 00 0f 00 01 00 00 0e 10 00 14 00 0a 04 6d 61 69 6c 07 65 "
211 "78 61 6d 70 6c 65 03 63 6f 6d 00 ",
213 // vector verified from dnskey.py as above, and confirmed with
214 // https://www.rfc-editor.org/errata_search.php?rfc=8080&eid=4935
215 .rfcB64Signature
= "oL9krJun7xfBOIWcGHi7mag5/hdZrKWw15jPGrHpjQeR"
216 "AvTdszaPD+QLs3fx8A4M3e23mRZ9VrbpMngwcrqNAg==",
222 .algorithm
= DNSSECKeeper::ED25519
,
223 .isDeterministic
= true,
225 .pem
= "-----BEGIN PRIVATE KEY-----\n"
226 "MC4CAQAwBQYDK2VwBCIEIDgyMjYwMzg0NjI4MDgwMTIyNjQ1MTkwMjA0MTQyMjYy\n"
227 "-----END PRIVATE KEY-----\n"
234 static const SignerParams ed448
= SignerParams
{
235 .iscMap
= "Private-key-format: v1.2\n"
236 "Algorithm: 16 (ED448)\n"
237 "PrivateKey: xZ+5Cgm463xugtkY5B0Jx6erFTXp13rYegst0qRtNsOYnaVpMx0Z/c5EiA9x8wWbDDct/U3FhYWA\n",
239 .dsSHA1
= "9712 16 1 "
240 "2873e800eb2d784cdd1802f884b3c540b573eaa0",
242 .dsSHA256
= "9712 16 2 "
243 "9aa27306f8a04a0a6fae8affd65d6f35875dcb134c05bd7c7b61bd0dc44009cd",
245 .dsSHA384
= "9712 16 4 "
246 "3876e5d892d3f31725f9964a332f9b9afd791171833480f2"
247 "e71af78efb985cde9900ba95315287123a5908ca8f334369",
250 0xb5, 0xcc, 0x21, 0x5a, 0x52, 0x21, 0x60, 0xa3, 0xb8, 0xd9, 0x3a, 0xd7, 0x05,
251 0xdd, 0x4a, 0x32, 0x96, 0xce, 0x08, 0xde, 0x74, 0x5f, 0xdb, 0xde, 0x54, 0x95,
252 0x97, 0x93, 0x6f, 0x3a, 0x4a, 0x34, 0x41, 0x14, 0xba, 0x99, 0x86, 0x0d, 0xe2,
253 0x99, 0xf1, 0x14, 0x6a, 0x1b, 0x7a, 0xfa, 0xef, 0xab, 0x62, 0xd2, 0x71, 0x85,
254 0xae, 0xd1, 0x84, 0x80, 0x00, 0x50, 0x03, 0x9e, 0x73, 0x53, 0xe8, 0x9e, 0x19,
255 0xb8, 0xc0, 0xdb, 0xd4, 0xf0, 0x1e, 0x44, 0x4c, 0xb7, 0x32, 0x07, 0xda, 0x0b,
256 0x64, 0x22, 0xa8, 0x63, 0xaa, 0x7a, 0x12, 0x73, 0xc9, 0x29, 0xfd, 0x50, 0x85,
257 0x0f, 0x43, 0x72, 0x77, 0x86, 0xec, 0x88, 0x1a, 0x96, 0x95, 0x4a, 0x01, 0xfe,
258 0xf2, 0xe6, 0x77, 0x4a, 0x2e, 0x43, 0xdd, 0x60, 0x29, 0x00,
261 .zoneRepresentation
= "256 3 16 "
262 "3kgROaDjrh0H2iuixWBrc8g2EpBBLCdGzHmn+"
263 "G2MpTPhpj/OiBVHHSfPodx1FYYUcJKm1MDpJtIA",
267 // vector extracted from https://gitlab.labs.nic.cz/labs/ietf/blob/master/dnskey.py (rev
268 // 476d6ded) by printing signature_data
269 .rfcMsgDump
= "00 0f 10 02 00 00 0e 10 55 d4 fc 60 55 b9 4c e0 25 f1 07 65 78 "
270 "61 6d 70 6c 65 03 63 6f 6d 00 07 65 78 61 6d 70 6c 65 03 63 6f "
271 "6d 00 00 0f 00 01 00 00 0e 10 00 14 00 0a 04 6d 61 69 6c 07 65 "
272 "78 61 6d 70 6c 65 03 63 6f 6d 00 ",
274 // vector verified from dnskey.py as above, and confirmed with
275 // https://www.rfc-editor.org/errata_search.php?rfc=8080&eid=4935
276 .rfcB64Signature
= "3cPAHkmlnxcDHMyg7vFC34l0blBhuG1qpwLmjInI8w1CMB29FkEA"
277 "IJUA0amxWndkmnBZ6SKiwZSAxGILn/NBtOXft0+Gj7FSvOKxE/07"
278 "+4RQvE581N3Aj/JtIyaiYVdnYtyMWbSNyGEY2213WKsJlwEA",
284 .algorithm
= DNSSECKeeper::ED448
,
285 .isDeterministic
= true,
287 .pem
= "-----BEGIN PRIVATE KEY-----\n"
288 "MEcCAQAwBQYDK2VxBDsEOcWfuQoJuOt8boLZGOQdCcenqxU16dd62HoLLdKkbTbD\n"
289 "mJ2laTMdGf3ORIgPcfMFmww3Lf1NxYWFgA==\n"
290 "-----END PRIVATE KEY-----\n"
298 BOOST_TEST_MESSAGE("All available/supported algorithms:");
299 auto pairs
= DNSCryptoKeyEngine::listAllAlgosWithBackend();
300 for (auto const& pair
: pairs
) {
301 BOOST_TEST_MESSAGE(" " + std::to_string(pair
.first
) + ": " + pair
.second
);
304 BOOST_TEST_MESSAGE("Setting up signer params:");
306 addSignerParams(DNSSECKeeper::RSASHA256
, "RSA SHA256", rsaSha256SignerParams
);
308 #ifdef HAVE_LIBCRYPTO_ECDSA
309 addSignerParams(DNSSECKeeper::ECDSA256
, "ECDSA SHA256", ecdsaSha256
);
312 // We need to have HAVE_LIBCRYPTO_ED25519 for the PEM reader/writer.
313 #if defined(HAVE_LIBCRYPTO_ED25519)
314 addSignerParams(DNSSECKeeper::ED25519
, "ED25519", ed25519
);
317 #if defined(HAVE_LIBDECAF) || defined(HAVE_LIBCRYPTO_ED448)
318 addSignerParams(DNSSECKeeper::ED448
, "ED448", ed448
);
322 void addSignerParams(const uint8_t algorithm
, const std::string
& name
, const SignerParams
& params
)
324 BOOST_TEST_MESSAGE(" " + std::to_string(algorithm
) + ": " + name
+ " (" + params
.name
+ ")");
325 signerParams
.insert_or_assign(algorithm
, params
);
328 const std::string message
{"Very good, young padawan."};
329 std::unordered_map
<uint8_t, struct SignerParams
> signerParams
;
332 static void checkRR(const SignerParams
& signer
)
334 DNSKEYRecordContent drc
;
335 auto dcke
= std::shared_ptr
<DNSCryptoKeyEngine
>(DNSCryptoKeyEngine::makeFromISCString(drc
, signer
.iscMap
));
336 DNSSECPrivateKey dpk
;
337 dpk
.setKey(dcke
, signer
.rfcFlags
);
340 /* values taken from rfc8080 for ed25519 and ed448, rfc5933 for gost */
341 DNSName
qname(dpk
.getAlgorithm() == DNSSECKeeper::ECCGOST
? "www.example.net." : "example.com.");
345 RRSIGRecordContent rrc
;
346 uint32_t expire
= 1440021600;
347 uint32_t inception
= 1438207200;
349 if (dpk
.getAlgorithm() == DNSSECKeeper::ECCGOST
) {
350 rrc
.d_signer
= DNSName("example.net.");
351 inception
= 946684800;
353 rrs
.insert(DNSRecordContent::mastermake(QType::A
, QClass::IN
, "192.0.2.1"));
356 rrc
.d_signer
= qname
;
357 rrs
.insert(DNSRecordContent::mastermake(QType::MX
, QClass::IN
, "10 mail.example.com."));
360 rrc
.d_originalttl
= 3600;
361 rrc
.d_sigexpire
= expire
;
362 rrc
.d_siginception
= inception
;
363 rrc
.d_type
= (*rrs
.cbegin())->getType();
364 rrc
.d_labels
= qname
.countLabels();
365 rrc
.d_tag
= dpk
.getTag();
366 rrc
.d_algorithm
= dpk
.getAlgorithm();
368 string msg
= getMessageForRRSET(qname
, rrc
, rrs
, false);
370 BOOST_CHECK_EQUAL(makeHexDump(msg
), signer
.rfcMsgDump
);
372 string signature
= dcke
->sign(msg
);
374 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg): Boost stuff.
375 BOOST_CHECK(dcke
->verify(msg
, signature
));
377 if (signer
.isDeterministic
) {
378 string b64
= Base64Encode(signature
);
379 BOOST_CHECK_EQUAL(b64
, signer
.rfcB64Signature
);
383 B64Decode(signer
.rfcB64Signature
, raw
);
384 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg): Boost stuff.
385 BOOST_CHECK(dcke
->verify(msg
, raw
));
389 static void test_generic_signer(std::shared_ptr
<DNSCryptoKeyEngine
> dcke
, DNSKEYRecordContent
& drc
, const SignerParams
& signer
, const std::string
& message
)
391 BOOST_CHECK_EQUAL(dcke
->getAlgorithm(), signer
.algorithm
);
392 BOOST_CHECK_EQUAL(dcke
->getBits(), signer
.bits
);
394 vector
<string
> errorMessages
{};
395 BOOST_CHECK_EQUAL(dcke
->checkKey(errorMessages
), true);
396 if (!errorMessages
.empty()) {
397 BOOST_TEST_MESSAGE("Errors from " + dcke
->getName() + " checkKey()");
398 for (auto& errorMessage
: errorMessages
) {
399 BOOST_TEST_MESSAGE(" " + errorMessage
);
403 BOOST_CHECK_EQUAL(drc
.d_algorithm
, signer
.algorithm
);
405 DNSSECPrivateKey dpk
;
406 dpk
.setKey(dcke
, signer
.flags
);
407 drc
= dpk
.getDNSKEY();
409 BOOST_CHECK_EQUAL(drc
.d_algorithm
, signer
.algorithm
);
410 BOOST_CHECK_EQUAL(drc
.d_protocol
, 3);
411 BOOST_CHECK_EQUAL(drc
.getZoneRepresentation(), signer
.zoneRepresentation
);
413 DNSName
name(signer
.name
);
414 auto ds1
= makeDSFromDNSKey(name
, drc
, DNSSECKeeper::DIGEST_SHA1
);
415 if (!signer
.dsSHA1
.empty()) {
416 BOOST_CHECK_EQUAL(ds1
.getZoneRepresentation(), signer
.dsSHA1
);
419 auto ds2
= makeDSFromDNSKey(name
, drc
, DNSSECKeeper::DIGEST_SHA256
);
420 if (!signer
.dsSHA256
.empty()) {
421 BOOST_CHECK_EQUAL(ds2
.getZoneRepresentation(), signer
.dsSHA256
);
424 auto ds4
= makeDSFromDNSKey(name
, drc
, DNSSECKeeper::DIGEST_SHA384
);
425 if (!signer
.dsSHA384
.empty()) {
426 BOOST_CHECK_EQUAL(ds4
.getZoneRepresentation(), signer
.dsSHA384
);
429 auto signature
= dcke
->sign(message
);
430 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg): Boost stuff.
431 BOOST_CHECK(dcke
->verify(message
, signature
));
433 auto signerSignature
= std::string(signer
.signature
.begin(), signer
.signature
.end());
434 if (signer
.isDeterministic
) {
435 auto signatureBase64
= Base64Encode(signature
);
436 auto signerSignatureBase64
= Base64Encode(signerSignature
);
437 BOOST_CHECK_EQUAL(signatureBase64
, signerSignatureBase64
);
440 /* since the signing process is not deterministic, we can't directly compare our signature
441 with the one we have. Still the one we have should also validate correctly. */
442 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg): Boost stuff.
443 BOOST_CHECK(dcke
->verify(message
, signerSignature
));
446 if (!signer
.rfcMsgDump
.empty() && !signer
.rfcB64Signature
.empty()) {
451 // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables,readability-identifier-length): Boost stuff.
452 BOOST_FIXTURE_TEST_CASE(test_generic_signers
, Fixture
)
454 for (const auto& algoSignerPair
: signerParams
) {
455 auto signer
= algoSignerPair
.second
;
457 DNSKEYRecordContent drc
;
458 auto dcke
= std::shared_ptr
<DNSCryptoKeyEngine
>(DNSCryptoKeyEngine::makeFromISCString(drc
, signer
.iscMap
));
459 test_generic_signer(dcke
, drc
, signer
, message
);
461 DNSKEYRecordContent pemDRC
;
462 shared_ptr
<DNSCryptoKeyEngine
> pemKey
{DNSCryptoKeyEngine::makeFromPEMString(pemDRC
, signer
.algorithm
, signer
.pem
)};
464 BOOST_CHECK_EQUAL(pemKey
->convertToISC(), dcke
->convertToISC());
466 test_generic_signer(pemKey
, pemDRC
, signer
, message
);
468 auto dckePEMOutput
= dcke
->convertToPEMString();
469 BOOST_CHECK_EQUAL(dckePEMOutput
, signer
.pem
);
471 auto pemKeyOutput
= pemKey
->convertToPEMString();
472 BOOST_CHECK_EQUAL(pemKeyOutput
, signer
.pem
);
476 // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables,readability-identifier-length): Boost stuff.
477 BOOST_AUTO_TEST_CASE(test_hash_qname_with_salt
)
480 // rfc5155 appendix A
481 const unsigned char salt
[] = {0xaa, 0xbb, 0xcc, 0xdd};
482 const unsigned int iterations
{12};
483 const std::vector
<std::pair
<std::string
, std::string
>> namesToHashes
= {
484 {"example", "0p9mhaveqvm6t7vbl5lop2u3t2rp3tom"},
485 {"a.example", "35mthgpgcu1qg68fab165klnsnk3dpvl"},
486 {"ai.example", "gjeqe526plbf1g8mklp59enfd789njgi"},
487 {"ns1.example", "2t7b4g4vsa5smi47k61mv5bv1a22bojr"},
488 {"ns2.example", "q04jkcevqvmu85r014c7dkba38o0ji5r"},
489 {"w.example", "k8udemvp1j2f7eg6jebps17vp3n8i58h"},
490 {"*.w.example", "r53bq7cc2uvmubfu5ocmm6pers9tk9en"},
491 {"x.w.example", "b4um86eghhds6nea196smvmlo4ors995"},
492 {"y.w.example", "ji6neoaepv8b5o6k4ev33abha8ht9fgc"},
493 {"x.y.w.example", "2vptu5timamqttgl4luu9kg21e0aor3s"},
494 {"xx.example", "t644ebqk9bibcna874givr6joj62mlhv"},
495 {"2t7b4g4vsa5smi47k61mv5bv1a22bojr.example", "kohar7mbb8dc2ce8a9qvl8hon4k53uhi"},
498 for (const auto& [name
, expectedHash
] : namesToHashes
) {
499 auto hash
= hashQNameWithSalt(std::string(reinterpret_cast<const char*>(salt
), sizeof(salt
)), iterations
, DNSName(name
));
500 BOOST_CHECK_EQUAL(toBase32Hex(hash
), expectedHash
);
505 /* no additional iterations, very short salt */
506 const unsigned char salt
[] = {0xFF};
507 const unsigned int iterations
{0};
508 const std::vector
<std::pair
<std::string
, std::string
>> namesToHashes
= {
509 {"example", "s9dp8o2l6jgqgg26ecobtjooe7p019cs"},
512 for (const auto& [name
, expectedHash
] : namesToHashes
) {
513 auto hash
= hashQNameWithSalt(std::string(reinterpret_cast<const char*>(salt
), sizeof(salt
)), iterations
, DNSName(name
));
514 BOOST_CHECK_EQUAL(toBase32Hex(hash
), expectedHash
);
519 /* only one iteration */
520 const unsigned char salt
[] = {0xaa, 0xbb, 0xcc, 0xdd};
521 const unsigned int iterations
{1};
522 const std::vector
<std::pair
<std::string
, std::string
>> namesToHashes
= {
523 {"example", "ulddquehrj5jpf50ga76vgqr1oq40133"},
526 for (const auto& [name
, expectedHash
] : namesToHashes
) {
527 auto hash
= hashQNameWithSalt(std::string(reinterpret_cast<const char*>(salt
), sizeof(salt
)), iterations
, DNSName(name
));
528 BOOST_CHECK_EQUAL(toBase32Hex(hash
), expectedHash
);
533 /* 65535 iterations, long salt */
534 unsigned char salt
[255];
535 for (unsigned char idx
= 0; idx
< 255; idx
++) {
538 const unsigned int iterations
{65535};
539 const std::vector
<std::pair
<std::string
, std::string
>> namesToHashes
= {
540 {"example", "no95j4cfile8avstr7bn4aj9he18trri"},
543 for (const auto& [name
, expectedHash
] : namesToHashes
) {
544 auto hash
= hashQNameWithSalt(std::string(reinterpret_cast<const char*>(salt
), sizeof(salt
)), iterations
, DNSName(name
));
545 BOOST_CHECK_EQUAL(toBase32Hex(hash
), expectedHash
);
550 // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables): Boost stuff.
551 BOOST_AUTO_TEST_SUITE_END()