Skip to content

Commit

Permalink
dnssec-oracle
Browse files Browse the repository at this point in the history
  • Loading branch information
TateB committed May 28, 2024
1 parent 8c58736 commit ee67417
Show file tree
Hide file tree
Showing 14 changed files with 1,361 additions and 4 deletions.
Binary file modified bun.lockb
Binary file not shown.
File renamed without changes.
File renamed without changes.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"type": "module",
"scripts": {
"compile": "NODE_OPTIONS=\"--experimental-loader ts-node/esm/transpile-only\" hardhat compile",
"test": "NODE_OPTIONS=\"--experimental-loader ts-node/esm/transpile-only\" TS_NODE_PREFER_TS_EXTS=true hardhat test ./test/wrapper/TestTestUnwrap.ts",
"test": "NODE_OPTIONS=\"--experimental-loader ts-node/esm/transpile-only\" TS_NODE_PREFER_TS_EXTS=true hardhat test ./test/dnssec-oracle/TestDNSSEC.ts",
"test:parallel": "NODE_OPTIONS=\"--experimental-loader ts-node/esm/transpile-only\" TS_NODE_PREFER_TS_EXTS=true hardhat test ./test/**/Test*.ts --parallel",
"test:local": "hardhat --network localhost test",
"test:deploy": "hardhat --network hardhat deploy",
Expand All @@ -27,7 +27,7 @@
],
"main": "index.js",
"devDependencies": {
"@ensdomains/dnsprovejs": "^0.3.7",
"@ensdomains/dnsprovejs": "^0.5.1",
"@ensdomains/hardhat-chai-matchers-viem": "^0.0.5",
"@ensdomains/test-utils": "^1.3.0",
"@nomicfoundation/hardhat-toolbox-viem": "^3.0.0",
Expand Down
33 changes: 33 additions & 0 deletions test/dnssec-oracle/TestAlgorithms.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { expect } from 'chai'
import hre from 'hardhat'
import { algorithms } from './fixtures/algorithms.js'

algorithms.forEach(([algo, vector]) => {
async function fixture() {
const algorithm = await hre.viem.deployContract(
algo as 'RSASHA1Algorithm',
[],
)
return { algorithm }
}

describe(algo, () => {
it('should return true for valid signatures', async () => {
const { algorithm } = await fixture()

await expect(
algorithm.read.verify([vector[0], vector[1], vector[2]]),
).resolves.toBe(true)
})

it('should return false for invalid signatures', async () => {
const { algorithm } = await fixture()

const invalidVector1 = `${vector[1]}00` as const

await expect(
algorithm.read.verify([vector[0], invalidVector1, vector[2]]),
).resolves.toBe(false)
})
})
})
846 changes: 846 additions & 0 deletions test/dnssec-oracle/TestDNSSEC.ts

Large diffs are not rendered by default.

56 changes: 56 additions & 0 deletions test/dnssec-oracle/TestDigests.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { expect } from 'chai'
import hre from 'hardhat'
import { stringToHex } from 'viem'
import { digests } from './fixtures/digests.js'

digests.forEach((testcase) => {
async function fixture() {
const digest = await hre.viem.deployContract(
testcase.digest as 'SHA256Digest',
[],
)
return { digest }
}

describe(testcase.digest, () => {
it('should return true for valid hashes', async () => {
const { digest } = await fixture()

await Promise.all(
testcase.valids.map(async ([text, hash]) =>
expect(digest.read.verify([stringToHex(text), hash])).resolves.toBe(
true,
),
),
)
})

it('should return false for invalid hashes', async () => {
const { digest } = await fixture()

await Promise.all(
testcase.invalids.map(async ([text, hash]) =>
expect(digest.read.verify([stringToHex(text), hash])).resolves.toBe(
false,
),
),
)
})

it('should throw an error for hashes of the wrong form', async () => {
const { digest } = await fixture()

const expectedError = `Invalid ${testcase.digest
.split('Digest')[0]
.toLowerCase()} hash length`

await Promise.all(
testcase.errors.map(async ([text, hash]) =>
expect(digest)
.read('verify', [stringToHex(text), hash])
.toBeRevertedWithString(expectedError),
),
)
})
})
})
43 changes: 43 additions & 0 deletions test/dnssec-oracle/TestSolidityTests.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import hre from 'hardhat'

const contracts = [
'contracts/test/TestBytesUtils.sol:TestBytesUtils',
'contracts/test/TestRRUtils.sol:TestRRUtils',
] as const

contracts.forEach((contract) => {
async function fixture() {
const publicClient = await hre.viem.getPublicClient()
const testContract = await hre.viem.deployContract(
contract as (typeof contracts)[0],
[],
)
return { publicClient, testContract }
}

const testContract = hre.artifacts.readArtifactSync(
contract as (typeof contracts)[0],
)
type Contract = typeof testContract
type TestFunction = Extract<
Contract['abi'][number],
{ name: `test${string}` }
>
const tests = testContract.abi.filter((a): a is TestFunction =>
a.name.startsWith('test'),
)

describe(contract.split(':')[1], () => {
tests.forEach((a) => {
it(a.name, async () => {
const { publicClient, testContract } = await fixture()
await publicClient.readContract({
abi: testContract.abi,
address: testContract.address,
args: [],
functionName: a.name,
})
})
})
})
})
92 changes: 92 additions & 0 deletions test/dnssec-oracle/fixtures/algorithms.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
export const algorithms = [
[
'RSASHA1Algorithm',
// This test vector generated from the zone using the following Python script:
// import dns.rrset
//
// dnskey = dns.rrset.from_text("org.", 900, "IN", "DNSKEY", "256 3 7 AwEAAXxsMmN/JgpEE9Y4uFNRJm7Q9GBwmEYUCsCxuKlgBU9WrQEFRrvAeMamUBeX4SE8s3V/TEk/TgGmPPp0pMkKD7mseluK6Ard2HZ6O3nPAzL4i8py/UDRUmYNSCxwfdfjUWRmcB9H+NKWMsJoDhAkLFqg5HS7f0j4Vb99Wac24Fk7")
//
// soa = dns.rrset.from_text("org.", 900, "IN", "SOA", "a0.org.afilias-nst.info. noc.afilias-nst.info. 2012953483 1800 900 604800 86400")
// buf = StringIO()
// soa.to_wire(buf)
//
// rrsig = dns.rrset.from_text("www.example.net.", 900, "IN", "RRSIG", "SOA 7 1 900 20180511092623 20180420082623 1862 org. NNyzNfXm72KiOuKvkd/s57kw4bYTX0xh4QBBca36MbYOl7SoqojQOfrUQmVj6/khTAOh2Ywx/S/2CKRQEhavsdBLKT29TlD5ahyzDHQu1hwvS6ZAqXgaPqeiXJiJodEUFkeCRWpp43iuqwh55mz6EeGqpX7vUpQ3DCDgfa3lo18=")
//
// signature = rrsig[0].signature
// rrsig[0].signature = ''
// signdata = rrsig[0].to_digestable() + buf.getvalue()
//
// print ('0x' + dnskey[0].to_digestable().encode('hex'), '0x' + signdata.encode('hex'), signature.encode('hex'))
[
// org. 705 IN DNSKEY 256 3 7 AwEAAXxsMmN/JgpEE9Y4uFNRJm7Q9GBwmEYUCsCxuKlgBU9WrQEFRrvA eMamUBeX4SE8s3V/TEk/TgGmPPp0pMkKD7mseluK6Ard2HZ6O3nPAzL4 i8py/UDRUmYNSCxwfdfjUWRmcB9H+NKWMsJoDhAkLFqg5HS7f0j4Vb99 Wac24Fk7
'0x01000307030100017c6c32637f260a4413d638b85351266ed0f460709846140ac0b1b8a960054f56ad010546bbc078c6a6501797e1213cb3757f4c493f4e01a63cfa74a4c90a0fb9ac7a5b8ae80addd8767a3b79cf0332f88bca72fd40d152660d482c707dd7e3516466701f47f8d29632c2680e10242c5aa0e474bb7f48f855bf7d59a736e0593b',
// org. 39 IN SOA a0.org.afilias-nst.info. noc.afilias-nst.info. 2012953483 1800 900 604800 86400
'0x00060701000003845af561bf5ad9a42f0746036f726700036f72670000060001000003840043026130036f72670b6166696c6961732d6e737404696e666f00036e6f630b6166696c6961732d6e737404696e666f0077fb3b8b000007080000038400093a8000015180',
// org. 39 IN RRSIG SOA 7 1 900 20180511092623 20180420082623 1862 org. NNyzNfXm72KiOuKvkd/s57kw4bYTX0xh4QBBca36MbYOl7SoqojQOfrU QmVj6/khTAOh2Ywx/S/2CKRQEhavsdBLKT29TlD5ahyzDHQu1hwvS6ZA qXgaPqeiXJiJodEUFkeCRWpp43iuqwh55mz6EeGqpX7vUpQ3DCDgfa3l o18=
'0x34dcb335f5e6ef62a23ae2af91dfece7b930e1b6135f4c61e1004171adfa31b60e97b4a8aa88d039fad4426563ebf9214c03a1d98c31fd2ff608a4501216afb1d04b293dbd4e50f96a1cb30c742ed61c2f4ba640a9781a3ea7a25c9889a1d114164782456a69e378aeab0879e66cfa11e1aaa57eef5294370c20e07dade5a35f',
],
],
[
'RSASHA256Algorithm',
// This test vector generated from the example in RFC5702 using the following Python script:
// import dns.rrset
//
// dnskey = dns.rrset.from_text("example.net.", 3600, "IN", "DNSKEY", "256 3 8 AwEAAcFcGsaxxdgiuuGmCkVImy4h99CqT7jwY3pexPGcnUFtR2Fh36BponcwtkZ4cAgtvd4Qs8PkxUdp6p/DlUmObdk=")
//
// a = dns.rrset.from_text("www.example.net.", 3600, "IN", "A", "192.0.2.91")
// buf = StringIO()
// a.to_wire(buf)
//
// rrsig = dns.rrset.from_text("www.example.net.", 3600, "IN", "RRSIG", "A 8 3 3600 20300101000000 20000101000000 9033 example.net. kRCOH6u7l0QGy9qpC9l1sLncJcOKFLJ7GhiUOibu4teYp5VE9RncriShZNz85mwlMgNEacFYK/lPtPiVYP4bwg==")
// signature = rrsig[0].signature
// rrsig[0].signature = ''
// signdata = rrsig[0].to_digestable() + buf.getvalue()
//
// print ('0x' + dnskey[0].to_digestable().encode('hex'), '0x' + signdata.encode('hex'), signature.encode('hex'))
[
// example.net. 3600 IN DNSKEY (256 3 8 AwEAAcFcGsaxxdgiuuGmCkVI
// my4h99CqT7jwY3pexPGcnUFtR2Fh36BponcwtkZ4cAgtvd4Qs8P
// kxUdp6p/DlUmObdk= );{id = 9033 (zsk), size = 512b}
'0x0100030803010001c15c1ac6b1c5d822bae1a60a45489b2e21f7d0aa4fb8f0637a5ec4f19c9d416d476161dfa069a27730b6467870082dbdde10b3c3e4c54769ea9fc395498e6dd9',
// www.example.net. 3600 IN A 192.0.2.91
'0x0001080300000e1070dbd880386d43802349076578616d706c65036e65740003777777076578616d706c65036e6574000001000100000e100004c000025b',
// www.example.net. 3600 IN RRSIG (A 8 3 3600 20300101000000
// 20000101000000 9033 example.net. kRCOH6u7l0QGy9qpC9
// l1sLncJcOKFLJ7GhiUOibu4teYp5VE9RncriShZNz85mwlMgNEa
// cFYK/lPtPiVYP4bwg==);{id = 9033}
'0x91108e1fabbb974406cbdaa90bd975b0b9dc25c38a14b27b1a18943a26eee2d798a79544f519dcae24a164dcfce66c2532034469c1582bf94fb4f89560fe1bc2',
],
],
[
'P256SHA256Algorithm',
// This test vector generated from the example in RFC6605 using the following Python script:
// from StringIO import StringIO
// import dns.rrset
//
// dnskey = dns.rrset.from_text("example.net.", 3600, "IN", "DNSKEY", "257 3 13 GojIhhXUN/u4v54ZQqGSnyhWJwaubCvTmeexv7bR6edbkrSqQpF64cYbcB7wNcP+e+MAnLr+Wi9xMWyQLc8NAA==")
//
// a = dns.rrset.from_text("www.example.net.", 3600, "IN", "A", "192.0.2.1")
// buf = StringIO()
// a.to_wire(buf)
//
// rrsig = dns.rrset.from_text("www.example.net.", 3600, "IN", "RRSIG", "A 13 3 3600 20100909100439 20100812100439 55648 example.net. qx6wLYqmh+l9oCKTN6qIc+bw6ya+KJ8oMz0YP107epXAyGmt+3SNruPFKG7tZoLBLlUzGGus7ZwmwWep666VCw==")
// signature = rrsig[0].signature
// rrsig[0].signature = ''
// signdata = rrsig[0].to_digestable() + buf.getvalue()
//
// print ('0x' + dnskey[0].to_digestable().encode('hex'), '0x' + signdata.encode('hex'), signature.encode('hex'))
[
// example.net. 3600 IN DNSKEY 257 3 13 (
// GojIhhXUN/u4v54ZQqGSnyhWJwaubCvTmeexv7bR6edb
// krSqQpF64cYbcB7wNcP+e+MAnLr+Wi9xMWyQLc8NAA== )
'0x0101030d1a88c88615d437fbb8bf9e1942a1929f28562706ae6c2bd399e7b1bfb6d1e9e75b92b4aa42917ae1c61b701ef035c3fe7be3009cbafe5a2f71316c902dcf0d00',
// www.example.net. 3600 IN A 192.0.2.1
'0x00010d0300000e104c88b1374c63c737d960076578616d706c65036e65740003777777076578616d706c65036e6574000001000100000e100004c0000201',
// www.example.net. 3600 IN RRSIG A 13 3 3600 (
// 20100909100439 20100812100439 55648 example.net.
// qx6wLYqmh+l9oCKTN6qIc+bw6ya+KJ8oMz0YP107epXA
// yGmt+3SNruPFKG7tZoLBLlUzGGus7ZwmwWep666VCw== )
'0xab1eb02d8aa687e97da0229337aa8873e6f0eb26be289f28333d183f5d3b7a95c0c869adfb748daee3c5286eed6682c12e5533186baced9c26c167a9ebae950b',
],
],
] as const
40 changes: 40 additions & 0 deletions test/dnssec-oracle/fixtures/digests.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
export const digests = [
{
digest: 'SHA256Digest',
valids: [
[
'',
'0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855',
], // valid 1
[
'foo',
'0x2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae',
], // valid 2
],
invalids: [
[
'',
'0x1111111111111111111111111111111111111111111111111111111111111111',
], // invalid
],
errors: [
[
'foo',
'0x2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae00',
], // junk at end of digest
],
},
{
digest: 'SHA1Digest',
valids: [
['', '0xda39a3ee5e6b4b0d3255bfef95601890afd80709'], // valid 1
['foo', '0x0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33'], // valid 2
],
invalids: [
['', '0x1111111111111111111111111111111111111111'], // invalid
],
errors: [
['foo', '0x0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a3300'], // junk at end of digest
],
},
] as const
53 changes: 53 additions & 0 deletions test/fixtures/anchors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import packet from 'dns-packet'

export const realEntries = [
{
name: '.',
type: 'DS',
class: 'IN',
ttl: 3600,
data: {
keyTag: 19036,
algorithm: 8,
digestType: 2,
digest: new Buffer(
'49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5',
'hex',
),
},
},
{
name: '.',
type: 'DS',
klass: 'IN',
ttl: 3600,
data: {
keyTag: 20326,
algorithm: 8,
digestType: 2,
digest: new Buffer(
'E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC683457104237C7F8EC8D',
'hex',
),
},
},
] as const

export const dummyEntry = {
name: '.',
type: 'DS',
class: 'IN',
ttl: 3600,
data: {
keyTag: 1278, // Empty body, flags == 0x0101, algorithm = 253, body = 0x0000
algorithm: 253,
digestType: 253,
digest: new Buffer('', 'hex'),
},
} as const

export const testEntries = [...realEntries, dummyEntry] as const

export const encodedAnchors = `0x${testEntries
.map((entry) => packet.answer.encode(entry).toString('hex'))
.join('')}` as const
Loading

0 comments on commit ee67417

Please sign in to comment.