Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 57 additions & 26 deletions bin/bns-prove
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ const Ownership = require('../lib/ownership');
const util = require('../lib/util');
const wire = require('../lib/wire');

// bns-prove --test -K ./test/prove-util weakkeytld "hello, world!"
const {fakeOwnership, FakeStub} = require('../test/prove-util/fakeownership');

const {
keyFlags,
classes,
Expand All @@ -36,6 +39,7 @@ let lifespan = 365 * 24 * 60 * 60;
let dir = '.';
let name = null;
let txt = null;
let test = false;

for (let i = 2; i < process.argv.length; i++) {
const arg = process.argv[i];
Expand Down Expand Up @@ -65,7 +69,7 @@ for (let i = 2; i < process.argv.length; i++) {
}

case '-t': {
lifespan = util.parseU32(lifespan);
lifespan = util.parseU32(next);
i += 1;
break;
}
Expand All @@ -80,6 +84,11 @@ for (let i = 2; i < process.argv.length; i++) {
break;
}

case '--test': {
test = true;
break;
}

case '-h':
case '--help':
case '-?':
Expand All @@ -88,7 +97,6 @@ for (let i = 2; i < process.argv.length; i++) {
process.exit(0);
break;
}

default: {
if (!name) {
if (!util.isName(arg))
Expand All @@ -109,9 +117,8 @@ if (!txt)
throw new Error('No text provided.');

(async () => {
const ctx = new Ownership();

ctx.Resolver = Resolver;
const ctx = test ? fakeOwnership : new Ownership();
ctx.Resolver = test ? FakeStub : Resolver;
ctx.secure = secure;

const proof = await ctx.prove(name, true);
Expand All @@ -123,51 +130,75 @@ if (!txt)

zone.claim.length = 0;

for (const key of zone.keys) {
if (key.type !== types.DNSKEY)
let pub, priv;
for (pub of zone.keys) {
if (pub.type !== types.DNSKEY)
continue;

const kd = key.data;
const kd = pub.data;

if (!(kd.flags & keyFlags.ZONE))
continue;

if (kd.flags & keyFlags.SEP)
continue;

if (kd.flags & keyFlags.REVOKE)
continue;

if (!ctx.verifyKey(key, hardened))
if (!ctx.verifyKey(pub, hardened))
continue;

const priv = await dnssec.readPrivateAsync(dir, key);
console.log('Searching for key: ', pub.data.keyTag());
priv = await dnssec.readPrivateAsync(dir, pub);

if (!priv)
continue;

const rr = new Record();
const rd = new TXTRecord();

rr.name = name;
rr.type = types.TXT;
rr.class = classes.IN;
rr.ttl = 3600;
rr.data = rd;
// If we found a KSK, check it for SHA1 and upgrade to SHA256
if (kd.flags & keyFlags.SEP) {
if (ctx.isSHA1(pub.data.algorithm)) {
console.log(`Upgrading key algorithm for key ID ${pub.data.keyTag()}`);

rd.txt.push(txt);
// Create new DNSKEY RRset with old key and new key
const upgradedPub = dnssec.upgradeDNSKEY(pub);
zone.keys.length = 0;
zone.keys.push(pub);
zone.keys.push(upgradedPub);

const sig = dnssec.sign(key, priv, [rr], lifespan);
// Sign DNSKEY RRset with new key only
zone.keys.push(
dnssec.sign(upgradedPub, priv, [pub, upgradedPub], lifespan)
);

zone.claim.push(rr);
zone.claim.push(sig);
// Throw out old key for the remainder of the process
pub = upgradedPub;
}
} else {
// We found a ZSK we can use if we can't find a KSK
continue;
}

// Stop searching, we have a key we can use.
break;
}

if (zone.claim.length === 0)
if (!priv)
throw new Error('Could not find suitable key to sign with.');

const rr = new Record();
const rd = new TXTRecord();

rr.name = name;
rr.type = types.TXT;
rr.class = classes.IN;
rr.ttl = 3600;
rr.data = rd;

rd.txt.push(txt);

const sig = dnssec.sign(pub, priv, [rr], lifespan);

zone.claim.push(rr);
zone.claim.push(sig);

if (hex)
process.stdout.write(proof.toHex() + '\n');
else if (base64)
Expand Down
15 changes: 15 additions & 0 deletions lib/dnssec.js
Original file line number Diff line number Diff line change
Expand Up @@ -705,6 +705,21 @@ dnssec.stripSignatures = function stripSignatures(msg) {
return msg;
};

dnssec.upgradeDNSKEY = function upgradeDNSKEY(ksk) {
assert(ksk instanceof Record);
assert(ksk.type === types.DNSKEY);
const key = ksk.deepClone();
switch(key.data.algorithm) {
case algs.RSASHA1:
case algs.RSASHA1NSEC3SHA1:
key.data.algorithm = algs.RSASHA256;
break;
default:
throw new Error('Algorithm is not SHA1.');
}
return key;
};

/*
* Helpers
*/
Expand Down
105 changes: 105 additions & 0 deletions test/proof-key-upgrade-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/* eslint-env mocha */
/* eslint prefer-arrow-callback: "off" */

'use strict';

const assert = require('bsert');
const path = require('path');
const {fakeOwnership, FakeStub} = require('./prove-util/fakeownership');
const dnssec = require('../lib/dnssec');
const {types, keyFlags} = require('../lib/wire');

describe('Ownership Proof Key Upgrade', function () {
const ownership = fakeOwnership;

it('should fail by default to generate insecure proof', async () => {
// They don't even count as actual RRSIGs
await assert.rejects(
ownership._prove(new FakeStub(), 'weakkeytld.', false),
{message: 'No RRSIG(TXT) records for weakkeytld.'}
);

// Sanity check
const res = new FakeStub().lookup('weakkeytld.', types.TXT);
assert(res.answer[1].type === types.RRSIG);
assert(ownership.isSHA1(res.answer[1].data.algorithm));
});

it('should generate insecure proof when forced', async () => {
try {
ownership.secure = false;
const fakeStub = new FakeStub();

const proof = await ownership._prove(
fakeStub,
'weakkeytld.',
false
);
assert(ownership.isSane(proof));
assert(ownership.verifySignatures(proof));

// Sanity checks
const claim = proof.zones[proof.zones.length - 1].claim;
const claimSig = claim[claim.length - 1];
// Signed with SHA1
assert(ownership.isSHA1(claimSig.data.algorithm));
// Signed with ZSK, not KSK
const keyTag = claimSig.data.keyTag;
const dnskeys = await fakeStub.lookup('weakkeytld.', types.DNSKEY);
let foundKey = false;
for (const rr of dnskeys.answer) {
if (rr.type === types.DNSKEY && rr.data.keyTag() === keyTag) {
foundKey = true;
assert(rr.data.flags & keyFlags.ZONE);
assert(!(rr.data.flags & keyFlags.SEP));
}
}
assert(foundKey);
} finally {
ownership.secure = true;
}
});

it('should upgrade weak key algorithm', async () => {
let proof, target;
try {
ownership.secure = false; // needed to get proof template
proof = await ownership._prove(new FakeStub(), 'weakkeytld.', true);
target = proof.zones[1];
const key = target.keys[1];
const txtRR = proof.zones[1].claim[0];

assert(key.type === types.DNSKEY);
assert(key.data.flags & keyFlags.SEP);
assert(txtRR.type === types.TXT);

// Kweakkeytld.+005+08014.key
const priv = await dnssec.readPrivateAsync(
path.join(__dirname, 'prove-util'),
key
);

// Here's the sneaky magic: create a duplicate key with better algorithm.
const key256 = dnssec.upgradeDNSKEY(key);

// Sign DNSKEY RRset now including both old and new keys.
const keySig = dnssec.sign(key256, priv, [key256, key], 24 * 60 * 60);
target.keys[0] = key;
target.keys[1] = key256;
target.keys[2] = keySig;

// Now sign the claim TXT with the new key
const txtSig = dnssec.sign(key256, priv, [txtRR], 24 * 60 * 60);
target.claim[1] = txtSig;
} finally {
ownership.secure = true; // default, and required by HNS consensus rules
}

assert(ownership.isSane(proof));
assert(ownership.verifySignatures(proof));

// Sanity check
assert(target.claim[1].type === types.RRSIG);
assert(!ownership.isSHA1(target.claim[1].data.algorithm));
});
});
5 changes: 5 additions & 0 deletions test/prove-util/K.+015+63077.key
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
; This is a key-signing key, keyid 63077, for .
; Created: 20220503145307 (Tue May 3 10:53:07 2022)
; Publish: 20220503145307 (Tue May 3 10:53:07 2022)
; Activate: 20220503145307 (Tue May 3 10:53:07 2022)
. IN DNSKEY 257 3 15 6GIGM0kYoQgXi3eWvx7AaPnAl/jXgino35a7TZVRR5s=
6 changes: 6 additions & 0 deletions test/prove-util/K.+015+63077.private
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Private-key-format: v1.3
Algorithm: 15 (ED25519)
PrivateKey: ZTN43rFvzpPBChiu1kkr0OtZeuLt2ClcEJ2P5awVej8=
Created: 20220503145307
Publish: 20220503145307
Activate: 20220503145307
5 changes: 5 additions & 0 deletions test/prove-util/K.+015+64078.key
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
; This is a zone-signing key, keyid 64078, for .
; Created: 20220503145259 (Tue May 3 10:52:59 2022)
; Publish: 20220503145259 (Tue May 3 10:52:59 2022)
; Activate: 20220503145259 (Tue May 3 10:52:59 2022)
. IN DNSKEY 256 3 15 dicBi2zCKiwhkLn51roAZW77uv5WYGlRU39jlpsZ+Rk=
6 changes: 6 additions & 0 deletions test/prove-util/K.+015+64078.private
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Private-key-format: v1.3
Algorithm: 15 (ED25519)
PrivateKey: lA87yC4HN9Y8hOOw5egO8kPGleY5+/2O7Fo5/NRG6N8=
Created: 20220503145259
Publish: 20220503145259
Activate: 20220503145259
5 changes: 5 additions & 0 deletions test/prove-util/Kweakkeytld.+005+08014.key
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
; This is a key-signing key, keyid 8014, for weakkeytld.
; Created: 20220503145332 (Tue May 3 10:53:32 2022)
; Publish: 20220503145332 (Tue May 3 10:53:32 2022)
; Activate: 20220503145332 (Tue May 3 10:53:32 2022)
weakkeytld. IN DNSKEY 257 3 5 AwEAAaetfppm5u8sT+tIXeSyjHSoLgv2GEMi03eG8JkpjLfhYnwCRN2W WqGmIxd8zMHmJw7fPjiWMr+Or1TuLfGibQOnEPSEiazO31hR/awAavA5 NtjBlcVey0OR9Hmiib5LrhNUOc7JDrTjj8vR8SsOV18Lw2gp0v5B62RV oiDIfRpc3nHvLs3OZ3teUCJoeirnGEWf/AhXz5ms8HlyTLPyZU9jT44k UQUWtAkRR5/FmizeV0oznDMqOBEq9vQ9+tp72PqQ91AopaIZo66bTJ/r Js2IZIYiBH/7Hjc00K1g3BPMWyi8LKBA0QxiJGDDrpjfayCfGhSH/lJT NWBnfxu0Nk8=
13 changes: 13 additions & 0 deletions test/prove-util/Kweakkeytld.+005+08014.private
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Private-key-format: v1.3
Algorithm: 5 (RSASHA1)
Modulus: p61+mmbm7yxP60hd5LKMdKguC/YYQyLTd4bwmSmMt+FifAJE3ZZaoaYjF3zMweYnDt8+OJYyv46vVO4t8aJtA6cQ9ISJrM7fWFH9rABq8Dk22MGVxV7LQ5H0eaKJvkuuE1Q5zskOtOOPy9HxKw5XXwvDaCnS/kHrZFWiIMh9Glzece8uzc5ne15QImh6KucYRZ/8CFfPmazweXJMs/JlT2NPjiRRBRa0CRFHn8WaLN5XSjOcMyo4ESr29D362nvY+pD3UCilohmjrptMn+smzYhkhiIEf/seNzTQrWDcE8xbKLwsoEDRDGIkYMOumN9rIJ8aFIf+UlM1YGd/G7Q2Tw==
PublicExponent: AQAB
PrivateExponent: pDDBXhQRYnZzs6LjPkSQQNNGc7QBQgxiIhLimjgTcSOkOmZGZO0LxmpWxnMQVXY3HNsBpIt/GhBwI6wvFQPF1+PKOIVoAu13ypZO3hRyotSDnnDBZclTJNFRIaJFWy/kP00kZhZ+7iY+8oibrVuXtpxgNiluUEbgZxlrbsqjpiFfo3pk/x240TheL99EZ4dhVW9lRC8F/qi3zDPCy9mXbeaYqxtkC4lEXnbyJe/yioKdQ4qt09F4w4hR0ZoNtQY/3pyCHwdUIei7dyQJGQ0+Xp7vnjWCDYyHcIGvgj/AE75A+f2M0QGbJxdaf3ZLuN/N2YUafHZp6Jp1KIgC91n0sQ==
Prime1: 3NatHII1ysavP+v58RfGbVu3lvdZy5q9qhRUQJj8uUmtMphbXUjsRvNVDObzb7P7oH1/7d65jJF3aXYHnx5GYX4DkC5CM6TUDfLO/lP1U7YzmondhUDFWDYIyHOcle7XrnVql4e4g1f8elPH6QcFZW4tztyKbOfv2+o2T1J5K5U=
Prime2: wl/+vZl6PzhefBoy3193BXrvQNrBKhHRBPgcixsHqG8g8L7Ymdb3tVhz3yS2FJHmpfTvzNAfZonOOg5hgf6vLiV/4G+9HvhYgw6PHoa4GUTVkuwruzk/eJxgpiYIBDrGbfEuLe8fklbbf18Z3oNjjKkq/zYKSr1aYf6ZwJxhgVM=
Exponent1: AdKv2SVmBkd/mNp81LWqiKqSKGfgUOL1H9tNGr9ojqsCCAHj9zAr6yYFFLcvWUO2FwwSK0eEZpmoz7EOvQyF7jYZF26aU0zQB1FyzfypcMh3QpZSws/XETRY/DagG0i+dQ05FQkkx8jJJ8VbSBwrujufmy6M4ftEKp+TVTJMF8U=
Exponent2: pOu6QrjURovXb0jzXR+s5xN1qPty5fUT+jliTozypHEV6+6h7XW92zpfpjeJ3k4k+y6lwIvd+Kx4ND47cYbcsDTVGWL1fi+NOjXCLU51KcuDwxNrz4E1X2qffpnKN3x/HI2EdyjrCslzl9DjLC8i6hgnCT+a3+tlorvZTNniyU0=
Coefficient: KutUYQnvVtF7j4+Ac6wovqjaqQRF2j6+//HNrNzXlwyAgRLkcyQ1FIzMA7vE+aQenWLztvwPU7XKUkRnOTwJtkiAZuIJUVwbWR2F5xiBUpfiOiKCYhmpJi5qOhe7t1vf3aoqhOOtXrjQyMxibjiy749ec1tbU9BPfeZPaxTjsKY=
Created: 20220503145332
Publish: 20220503145332
Activate: 20220503145332
5 changes: 5 additions & 0 deletions test/prove-util/Kweakkeytld.+005+11037.key
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
; This is a zone-signing key, keyid 11037, for weakkeytld.
; Created: 20220503145326 (Tue May 3 10:53:26 2022)
; Publish: 20220503145326 (Tue May 3 10:53:26 2022)
; Activate: 20220503145326 (Tue May 3 10:53:26 2022)
weakkeytld. IN DNSKEY 256 3 5 AwEAAb1lMEgqXLg5CIcnHyDoUKPEBysVLcCQK4c79wvZVTkuVif0Q7+e RUfNVAdeekucx+jlhvRJW7eDtDUjbhMDD9IWJSlIofAQoP6iw1KtG/lZ yDnbQ5pqR/BDQxOUVkLwE2RrSi6FlFTkCngNlitxSqoc5oXeuDg17jm/ KCH+Np/Yw9dNEhB5Iq46yttIgBfDwLWckXCmwUegBUacWsfzo/tYgFN/ B8Mw9QFdOIL83rhz5hDBgB4go/EDyUZqrqnpsUGO6d3bGA/0jG3a67lc EB0B41xXdoPgh7A0rjNd2kp/tuttRQP7MVkbCjiJSCFMz1MGeb/OA7eI dUWPQBsa8JM=
13 changes: 13 additions & 0 deletions test/prove-util/Kweakkeytld.+005+11037.private
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Private-key-format: v1.3
Algorithm: 5 (RSASHA1)
Modulus: vWUwSCpcuDkIhycfIOhQo8QHKxUtwJArhzv3C9lVOS5WJ/RDv55FR81UB156S5zH6OWG9Elbt4O0NSNuEwMP0hYlKUih8BCg/qLDUq0b+VnIOdtDmmpH8ENDE5RWQvATZGtKLoWUVOQKeA2WK3FKqhzmhd64ODXuOb8oIf42n9jD100SEHkirjrK20iAF8PAtZyRcKbBR6AFRpxax/Oj+1iAU38HwzD1AV04gvzeuHPmEMGAHiCj8QPJRmquqemxQY7p3dsYD/SMbdrruVwQHQHjXFd2g+CHsDSuM13aSn+2621FA/sxWRsKOIlIIUzPUwZ5v84Dt4h1RY9AGxrwkw==
PublicExponent: AQAB
PrivateExponent: O3WsLcvW5iNJsRywIiWtQ2zEj1sLzRu1/rPtwHOP1O7eL5b5OgxXVc55pgKcRGbJQC3nK4RoXfnkNpaT9TYN3ngDXK2n4XVnBepVhfxA/wyX1somtDDPuvdy9I+qcUNr4yfn1ykqw2gAfWZOkf70YOnH2ZltnoAX9Vs1H07vGUlq9ASDvHsMsgKJgn4e5FD015hmitglPjLRucf7sld3G+Ui/Oiz+U+GvovYry1Yx/IYf1yrlSFFEyIkPLJMEcwGuMHXPTe/bGCZp9oPivuqr7lK22TNeGldxx3d4Gw0U5ACYTfrHi1O/lkqA/C1e7l7Sb/w1YmxN2dgVIRfGRVNiQ==
Prime1: 5l7QURvppZuL1CRmB59IsdVGHjcyZhUJZ/cBe3ae2ey+ZZyYGJR3tJZzc3au6hCqJMDiIBbcflz2N+Yl71L8CuoMijaPlEEE5RQg+N7OK++CzDpfrG4luH6uJX+RR9HgAvD9/V71+pipuMQ3DVhhTBN1xd1wFe5J/BTIql/Pb4c=
Prime2: 0ndcl+7jtUyGVUzeWO+6vForZeh76FneK8ezltZcsmy2XLuPMVm0nCdYHhKDSKl+hggA+39JS5wAPNH/L34+p7A0DKzYKruDcVhpN9ur5M6y7h1ICzey/kTgsNzIccaYb/2kHjkaZqV3P6XumVc/aS3ISZvWZepIiuKBSUF0gZU=
Exponent1: EWAPWD7BtaLwvfRs2aBS7E7Ithi1rWtixTulGfnNa2Rmy+Uut5PjH3TFimzmLnNJUfJWW9M9mC5Mx9SNAesBZZVXkskgtS7ePqTxA7RSWo/7DopMkwXPxIWRfvSLMZ6Lxc0FaynRZbBEBNKP0GrdE87X8C+Od6j8XY33wJnvXFs=
Exponent2: Bcb/BLCrEYP7QAYvKFPUVW1IObDrDdLBtYPy2xYhT0iKrPr9EEa9HXg7BABQGEOG1JkNpdm1olyy6Ph+v8gAYkwE8cAg4vNoxUi/AqiGDG7cHIszOhOaVz5+yHwXCICCGLjms2mv3td18YpVhWIOvI1kLRkZBo0q1p0nHWKtlw0=
Coefficient: tUK/ZP/YmmwQ3/3WeLMvkxHXIsxlkPiakz/ko1uNJxHPFZKNAVcy7m3X+bo/FtNSlwb1/d+P8Vkfkj4vtkqCLGlvKI7DFgTYK54Lo8sHyluNo0jsXeOfxy1XDWElpod1aRCQfTjxU/A5HSCls/EdGLdjiQ8fJbUxoZbo1XewOgM=
Created: 20220503145326
Publish: 20220503145326
Activate: 20220503145326
41 changes: 41 additions & 0 deletions test/prove-util/fakeownership.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
'use strict';

const path = require('path');
const Ownership = require('../../lib/ownership');
const {Record, Message} = require('../../lib/wire');
const Zone = require('../../lib/zone');

const KSK = Record.fromString(
'. IN DS 63077 15 2 ' +
'433633AAAE8780F7EA8C46D403195A3BB58992D64B7C79E61EAB4D7EC336D077'
);
const ROOT_ZONE = Zone.fromFile(
'.',
path.join(__dirname, 'root.zone.signed')
);
const WEAKKEYTLD_ZONE = Zone.fromFile(
'weakkeytld.',
path.join(__dirname, 'weakkeytld.zone.signed')
);

class FakeStub {
open() {}
close() {}
lookup (name, type) {
const msg = new Message();

msg.answer = ROOT_ZONE.get(name, type);
if (!msg.answer.length)
msg.answer = WEAKKEYTLD_ZONE.get(name, type);

return msg;
}
}

const fakeOwnership = new Ownership();
fakeOwnership.anchors = [KSK];
fakeOwnership.rootAnchors = fakeOwnership.anchors;
fakeOwnership.Resolver = FakeStub;

exports.fakeOwnership = fakeOwnership;
exports.FakeStub = FakeStub;
Loading