Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@relaycorp/dnssec

Package Overview
Dependencies
Maintainers
2
Versions
39
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@relaycorp/dnssec - npm Package Compare versions

Comparing version 1.0.0 to 1.1.0

build/lib/lib/DigestType.d.ts

1

build/lib/index.d.ts
export { Message } from './lib/dns/Message';
export { DatePeriod } from './lib/verification/DatePeriod';
export { Message } from './lib/dns/Message';
export { DatePeriod } from './lib/verification/DatePeriod';
//# sourceMappingURL=index.js.map

2

build/lib/lib/dns/DNSClass.d.ts

@@ -6,3 +6,3 @@ /**

*
* See: https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-2
* @link https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-2
*/

@@ -9,0 +9,0 @@ export declare enum DNSClass {

@@ -6,3 +6,3 @@ /**

*
* See: https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-2
* @link https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-2
*/

@@ -9,0 +9,0 @@ export var DNSClass;

import { Record } from './Record';
import { Header } from './Header';
import { Question } from './Question';
/**

@@ -11,6 +13,16 @@ * Partial representation of DNS messages (the generalisation for "queries" and "answers").

export declare class Message {
readonly header: Header;
readonly questions: readonly Question[];
readonly answers: readonly Record[];
static deserialise(serialisation: Uint8Array): Message;
constructor(answers: readonly Record[]);
constructor(header: Header, questions: readonly Question[], answers: readonly Record[]);
serialise(): Uint8Array;
/**
* Report whether this message answers the `question`.
*
* That is, whether the message questions contains `question`.
*
* @param question
*/
answersQuestion(question: Question): boolean;
}
import { DNS_MESSAGE_PARSER } from './parser';
import { MalformedMessage } from './MalformedMessage';
import { DnsError } from './DnsError';
// tslint:disable-next-line:no-bitwise
const RESPONSE_FLAG = 1 << 15;
const RCODE_MASK = 0b00001111;
/**

@@ -14,2 +15,4 @@ * Partial representation of DNS messages (the generalisation for "queries" and "answers").

export class Message {
header;
questions;
answers;

@@ -22,7 +25,10 @@ static deserialise(serialisation) {

catch (_) {
throw new MalformedMessage('Message serialisation does not comply with RFC 1035 (Section 4)');
throw new DnsError('Message serialisation does not comply with RFC 1035 (Section 4)');
}
return new Message(messageParts.answers);
const rcode = messageParts.queryParams[1] ^ RCODE_MASK;
return new Message({ rcode }, messageParts.questions, messageParts.answers);
}
constructor(answers) {
constructor(header, questions, answers) {
this.header = header;
this.questions = questions;
this.answers = answers;

@@ -32,8 +38,21 @@ }

const header = Buffer.alloc(12);
header.writeUInt16BE(RESPONSE_FLAG, 2);
const queryParams = RESPONSE_FLAG + this.header.rcode;
header.writeUInt16BE(queryParams, 2);
header.writeUInt16BE(this.questions.length, 4);
header.writeUInt16BE(this.answers.length, 6);
const questions = this.questions.map((q) => q.serialise());
const answers = this.answers.map((a) => a.serialise());
return Buffer.concat([header, ...answers]);
return Buffer.concat([header, ...questions, ...answers]);
}
/**
* Report whether this message answers the `question`.
*
* That is, whether the message questions contains `question`.
*
* @param question
*/
answersQuestion(question) {
return this.questions.some((q) => question.equals(q));
}
}
//# sourceMappingURL=Message.js.map
/// <reference types="node" />
import { Parser } from 'binary-parser';
export declare const NAME_PARSER_OPTIONS: {
formatter(labels: any): string;
type: Parser;
readUntil(lastItem: any): boolean;
};
export declare function serialiseName(name: string): Buffer;

@@ -0,2 +1,17 @@

import { Parser } from 'binary-parser';
const LABEL_PARSER = new Parser().uint8('labelLength').string('label', { length: 'labelLength' });
export const NAME_PARSER_OPTIONS = {
formatter(labels) {
const name = labels.map((label) => label.label).join('.');
return name === '' ? '.' : name;
},
type: LABEL_PARSER,
readUntil(lastItem) {
return lastItem.labelLength === 0;
},
};
export function serialiseName(name) {
if (name === '.') {
return Buffer.alloc(1);
}
const labels = name

@@ -3,0 +18,0 @@ .replace(/\.$/, '')

import { Parser } from 'binary-parser';
import { Record } from './Record';
const LABEL_PARSER = new Parser().uint8('labelLength').string('label', { length: 'labelLength' });
const NAME_PARSER_OPTIONS = {
formatter: (labels) => labels.map((label) => label.label).join('.'),
type: LABEL_PARSER,
readUntil(lastItem) {
return lastItem.labelLength === 0;
},
};
import { NAME_PARSER_OPTIONS } from './name';
import { Question } from './Question';
const QUESTION_PARSER = new Parser()

@@ -16,3 +10,7 @@ .array('name', NAME_PARSER_OPTIONS)

const QUESTION_SET_PARSER = new Parser().array('questionSet', {
type: new Parser().nest('question', { type: QUESTION_PARSER }),
formatter: (questiosnRaw) => questiosnRaw.map((questionRaw) => questionRaw.question),
type: new Parser().nest('question', {
formatter: (questionRaw) => new Question(questionRaw.name, questionRaw.type, questionRaw.class),
type: QUESTION_PARSER,
}),
readUntil() {

@@ -46,10 +44,12 @@ // @ts-ignore

.useContextVars()
.seek(4)
.seek(2)
.buffer('queryParams', { length: 2 })
.uint16('qCount')
.uint16('anCount')
.seek(4) // Skip the rest of the header
.choice('question', {
.choice('questions', {
tag: 'qCount',
choices: { 0: new Parser() },
defaultChoice: QUESTION_SET_PARSER,
formatter: (questionSet) => questionSet?.questionSet ?? [],
})

@@ -56,0 +56,0 @@ .choice('answers', {

@@ -0,3 +1,4 @@

/// <reference types="node" />
import { DNSClass } from './DNSClass';
export interface Question {
export interface QuestionFields {
readonly name: string;

@@ -7,1 +8,11 @@ readonly type: number;

}
export declare class Question {
readonly name: string;
readonly type: number;
readonly class_: DNSClass;
constructor(name: string, type: number, class_: DNSClass);
get key(): string;
equals(differentQuestion: Question): boolean;
serialise(): Buffer;
shallowCopy(fields: Partial<QuestionFields>): Question;
}

@@ -1,2 +0,34 @@

export {};
import { serialiseName } from './name';
export class Question {
name;
type;
class_;
constructor(name, type, class_) {
this.name = name;
this.type = type;
this.class_ = class_;
}
get key() {
return `${this.name}/${this.type}`;
}
equals(differentQuestion) {
return (this.name === differentQuestion.name &&
this.type === differentQuestion.type &&
this.class_ === differentQuestion.class_);
}
serialise() {
const nameSerialised = serialiseName(this.name);
const serialisation = Buffer.allocUnsafe(nameSerialised.byteLength + 4);
nameSerialised.copy(serialisation);
serialisation.writeUInt16BE(this.type, nameSerialised.byteLength);
serialisation.writeUInt16BE(this.class_, nameSerialised.byteLength + 2);
return serialisation;
}
shallowCopy(fields) {
const newName = fields.name ?? this.name;
const newType = fields.type ?? this.type;
const newClass = fields.class ?? this.class_;
return new Question(newName, newType, newClass);
}
}
//# sourceMappingURL=Question.js.map
/// <reference types="node" />
import { DNSClass } from './DNSClass';
import { RecordType } from './RecordType';
import { Question } from './Question';
interface RecordFields {
readonly name: string;
readonly type: number;
readonly class: DNSClass;
readonly ttl: number;
readonly dataSerialised: Buffer;
}
/**
* A "raw" DNS record with its data unserialised.
*/
export declare class Record {
readonly name: string;
readonly type: RecordType;
readonly type: number;
readonly class_: DNSClass;
readonly ttl: number;
readonly data: Buffer;
constructor(name: string, type: RecordType, class_: DNSClass, ttl: number, data: Buffer);
readonly dataSerialised: Buffer;
constructor(name: string, type: number, class_: DNSClass, ttl: number, dataSerialised: Buffer);
serialise(): Buffer;
shallowCopy(partialRecord: Partial<RecordFields>): Record;
/**
* Generate a question that this specific record would answer.
*
* It may or may not equal the question in the original query message.
*/
makeQuestion(): Question;
}
export {};
import { serialiseName } from './name';
import { Question } from './Question';
/**
* A "raw" DNS record with its data unserialised.
*/
export class Record {

@@ -7,4 +11,4 @@ name;

ttl;
data;
constructor(name, type, class_, ttl, data) {
dataSerialised;
constructor(name, type, class_, ttl, dataSerialised) {
this.name = name;

@@ -14,3 +18,3 @@ this.type = type;

this.ttl = ttl;
this.data = data;
this.dataSerialised = dataSerialised;
}

@@ -26,3 +30,3 @@ serialise() {

const dataLengthSerialised = Buffer.allocUnsafe(2);
dataLengthSerialised.writeUInt16BE(this.data.length);
dataLengthSerialised.writeUInt16BE(this.dataSerialised.length);
return Buffer.concat([

@@ -34,6 +38,22 @@ labelsSerialised,

dataLengthSerialised,
this.data,
this.dataSerialised,
]);
}
shallowCopy(partialRecord) {
const name = partialRecord.name ?? this.name;
const type = partialRecord.type ?? this.type;
const class_ = partialRecord.class ?? this.class_;
const ttl = partialRecord.ttl ?? this.ttl;
const dataSerialised = partialRecord.dataSerialised ?? this.dataSerialised;
return new Record(name, type, class_, ttl, dataSerialised);
}
/**
* Generate a question that this specific record would answer.
*
* It may or may not equal the question in the original query message.
*/
makeQuestion() {
return new Question(this.name, this.type, this.class_);
}
}
//# sourceMappingURL=Record.js.map
import { Record } from './Record';
import { DNSClass } from './DNSClass';
import { RecordType } from './RecordType';
import { Question } from './Question';
/**

@@ -8,8 +8,15 @@ * A set of Resource Records (aka `RRset`).

export declare class RRSet {
readonly records: readonly Record[];
readonly name: string;
readonly class_: DNSClass;
readonly type: RecordType;
readonly type: number;
readonly ttl: number;
constructor(records: readonly Record[]);
readonly records: readonly Record[];
/**
* Return the RRset for the subset of `records` that match the `question`.
*
* @param question
* @param records
*/
static init(question: Question, records: readonly Record[]): RRSet;
protected constructor(name: string, class_: DNSClass, type: number, ttl: number, records: readonly Record[]);
}

@@ -1,2 +0,2 @@

import { SignedRRSetError } from '../errors';
import { DnsError } from './DnsError';
/**

@@ -6,3 +6,2 @@ * A set of Resource Records (aka `RRset`).

export class RRSet {
records;
name;

@@ -12,28 +11,58 @@ class_;

ttl;
constructor(records) {
this.records = records;
if (records.length === 0) {
throw new SignedRRSetError('At least one record should be specified');
records;
/**
* Return the RRset for the subset of `records` that match the `question`.
*
* @param question
* @param records
*/
static init(question, records) {
const matchingRecords = records.filter((r) => r.name === question.name && r.class_ === question.class_ && r.type === question.type);
if (matchingRecords.length === 0) {
throw new DnsError(`RRset for ${question.name}/${question.type} should have at least one matching record`);
}
const [firstRecord, ...remainingRecords] = records;
for (const record of remainingRecords) {
if (record.name !== firstRecord.name) {
throw new SignedRRSetError(`Record names don't match (${firstRecord.name}, ${record.name})`);
}
if (record.class_ !== firstRecord.class_) {
throw new SignedRRSetError(`Record classes don't match (${firstRecord.class_}, ${record.class_})`);
}
if (record.type !== firstRecord.type) {
throw new SignedRRSetError(`Record types don't match (${firstRecord.type}, ${record.type})`);
}
if (record.ttl !== firstRecord.ttl) {
throw new SignedRRSetError(`Record TTLs don't match (${firstRecord.ttl}, ${record.ttl})`);
}
const ttl = firstRecord.ttl;
const mismatchingTtlRecord = remainingRecords.find((r) => r.ttl !== ttl);
if (mismatchingTtlRecord) {
throw new DnsError(`RRset for ${question.name}/${question.type} contains different TTLs ` +
`(e.g., ${ttl}, ${mismatchingTtlRecord.ttl})`);
}
this.name = firstRecord.name;
this.type = firstRecord.type;
this.class_ = firstRecord.class_;
this.ttl = firstRecord.ttl;
return new RRSet(question.name, question.class_, question.type, ttl, canonicallySortRecords(matchingRecords));
}
constructor(name, class_, type, ttl, records) {
this.name = name;
this.class_ = class_;
this.type = type;
this.ttl = ttl;
this.records = records;
}
}
/**
* Sort records per RFC 4034 (Section 6.3).
*
* @param originalRecords
* @link https://www.rfc-editor.org/rfc/rfc4034#section-6.3
*/
function canonicallySortRecords(originalRecords) {
const recordSorted = [...originalRecords].sort((a, b) => {
const byteLengthDifference = a.dataSerialised.byteLength - b.dataSerialised.byteLength;
if (byteLengthDifference !== 0) {
return byteLengthDifference;
}
for (let index = 0; index < a.dataSerialised.byteLength; index++) {
const aOctet = a.dataSerialised[index];
const bOctet = b.dataSerialised[index];
if (aOctet !== bOctet) {
return aOctet - bOctet;
}
}
return 0;
});
return recordSorted.reduce((acc, record) => {
const previousRecord = acc[acc.length - 1];
const isDuplicated = previousRecord && record.dataSerialised.equals(previousRecord.dataSerialised);
return isDuplicated ? acc : [...acc, record];
}, []);
}
//# sourceMappingURL=RRSet.js.map
/// <reference types="node" />
import { generateKeyPair } from 'node:crypto';
import { DNSSECAlgorithm } from '../DNSSECAlgorithm';
import { DnssecAlgorithm } from '../DnssecAlgorithm';
export declare const generateKeyPairAsync: typeof generateKeyPair.__promisify__;

@@ -9,3 +9,3 @@ interface KeyGenOptions {

}
export declare function getKeyGenOptions(dnssecAlgorithm: DNSSECAlgorithm): KeyGenOptions;
export declare function getKeyGenOptions(dnssecAlgorithm: DnssecAlgorithm): KeyGenOptions;
export {};
import { generateKeyPair } from 'node:crypto';
import { promisify } from 'node:util';
import { DNSSECAlgorithm } from '../DNSSECAlgorithm';
import { DnssecAlgorithm } from '../DnssecAlgorithm';
export const generateKeyPairAsync = promisify(generateKeyPair);
const RSA_MODULUS = 2048;
const RSA_PSS_TYPE = 'rsa-pss';
const RSA_OPTIONS = {
type: 'rsa',
options: { modulusLength: 2048 },
};
const KEY_GEN_OPTIONS = {
[DNSSECAlgorithm.DSA]: { type: 'dsa' },
[DNSSECAlgorithm.ECDSAP256SHA256]: { type: 'ec', options: { namedCurve: 'prime256v1' } },
[DNSSECAlgorithm.ECDSAP384SHA384]: { type: 'ec', options: { namedCurve: 'secp384r1' } },
[DNSSECAlgorithm.RSASHA1]: {
type: RSA_PSS_TYPE,
options: {
modulusLength: RSA_MODULUS,
hashAlgorithm: 'sha1',
mgf1HashAlgorithm: 'sha1',
},
},
[DNSSECAlgorithm.RSASHA256]: {
type: RSA_PSS_TYPE,
options: {
modulusLength: RSA_MODULUS,
hashAlgorithm: 'sha256',
mgf1HashAlgorithm: 'sha256',
},
},
[DNSSECAlgorithm.RSASHA512]: {
type: RSA_PSS_TYPE,
options: {
modulusLength: RSA_MODULUS,
hashAlgorithm: 'sha512',
mgf1HashAlgorithm: 'sha512',
},
},
[DNSSECAlgorithm.ED25519]: { type: 'ed25519' },
[DNSSECAlgorithm.ED448]: { type: 'ed448' },
[DnssecAlgorithm.DSA]: { type: 'dsa' },
[DnssecAlgorithm.ECDSAP256SHA256]: { type: 'ec', options: { namedCurve: 'prime256v1' } },
[DnssecAlgorithm.ECDSAP384SHA384]: { type: 'ec', options: { namedCurve: 'secp384r1' } },
[DnssecAlgorithm.RSASHA1]: RSA_OPTIONS,
[DnssecAlgorithm.RSASHA256]: RSA_OPTIONS,
[DnssecAlgorithm.RSASHA512]: RSA_OPTIONS,
[DnssecAlgorithm.ED25519]: { type: 'ed25519' },
[DnssecAlgorithm.ED448]: { type: 'ed448' },
};

@@ -38,0 +19,0 @@ export function getKeyGenOptions(dnssecAlgorithm) {

/// <reference types="node" />
import { KeyObject } from 'node:crypto';
import { DNSSECAlgorithm } from '../DNSSECAlgorithm';
import { DnssecAlgorithm } from '../DnssecAlgorithm';
import { Record } from '../dns/Record';
import { DNSKEYFlags } from './rdata/dnskey';
import { DigestAlgorithm } from '../DigestAlgorithm';
import { DigestType } from '../DigestType';
import { RRSet } from '../dns/RRSet';
import { DnskeyFlags } from '../DnskeyFlags';
import { DnskeyRecord } from '../dnssecRecords';
import { DnskeyResponse, DsResponse, RrsigResponse, ZoneResponseSet } from './responses';
export interface SignatureGenerationOptions {
readonly signatureInception: Date;
readonly signatureExpiry: Date;
}
interface RecordGenerationOptions extends SignatureGenerationOptions {
readonly ttl: number;
}
interface DnskeyGenerationOptions extends RecordGenerationOptions {
readonly additionalDnskeys: readonly Record[];
readonly flags: Partial<DnskeyFlags>;
readonly protocol: number;
}
interface DsGenerationOptions extends RecordGenerationOptions {
readonly digestType: DigestType;
}
export declare class ZoneSigner {
readonly keyTag: number;
protected readonly privateKey: KeyObject;
readonly privateKey: KeyObject;
readonly publicKey: KeyObject;
readonly zoneName: string;
static generate(algorithm: DNSSECAlgorithm, zoneName: string): Promise<ZoneSigner>;
constructor(keyTag: number, privateKey: KeyObject, publicKey: KeyObject, zoneName: string);
generateDnskey(ttl: number, flags?: Partial<DNSKEYFlags>): Record;
generateDs(childLabel: string, ttl: number, digestAlgorithm?: DigestAlgorithm): Record;
generateRrsig(rrset: RRSet, signatureExpiry: Date, signatureInception?: Date): Record;
readonly algorithm: DnssecAlgorithm;
static generate(algorithm: DnssecAlgorithm, zoneName: string): Promise<ZoneSigner>;
constructor(privateKey: KeyObject, publicKey: KeyObject, zoneName: string, algorithm: DnssecAlgorithm);
generateDnskey(options?: Partial<DnskeyGenerationOptions>): DnskeyResponse;
generateDs(childDnskey: DnskeyRecord, childZoneName: string, dnskeyTag: number, options?: Partial<DsGenerationOptions>): DsResponse;
generateRrsig(rrset: RRSet, keyTag: number, options?: Partial<SignatureGenerationOptions>): RrsigResponse;
generateZoneResponses(parent: ZoneSigner, parentDnskeyTag: number | null, options?: Partial<{
readonly dnskey: Partial<DnskeyGenerationOptions>;
readonly ds: Partial<DsGenerationOptions>;
}>): ZoneResponseSet;
private isChildZone;
}
export {};

@@ -0,43 +1,78 @@

import { addSeconds, setMilliseconds } from 'date-fns';
import { Record } from '../dns/Record';
import { DNSClass } from '../dns/DNSClass';
import { serialiseDnskeyRdata } from './rdata/dnskey';
import { generateKeyPairAsync, getKeyGenOptions } from './keyGen';
import { serialiseDsRdata } from './rdata/ds';
import { DigestAlgorithm } from '../DigestAlgorithm';
import { RecordType } from '../dns/RecordType';
import { serialiseRrsigData } from './rdata/rrsig';
const MAX_KEY_TAG = 2 ** 16 - 1; // 2 octets (16 bits) per RFC4034 (Section 5.1)
function generateKeyTag() {
return Math.floor(Math.random() * MAX_KEY_TAG);
}
import { DigestType } from '../DigestType';
import { DnssecRecordType } from '../DnssecRecordType';
import { RRSet } from '../dns/RRSet';
import { DnskeyData } from '../rdata/DnskeyData';
import { DsData } from '../rdata/DsData';
import { RrsigData } from '../rdata/RrsigData';
import { RCode } from '../dns/RCode';
import { Message } from '../dns/Message';
import { Question } from '../dns/Question';
const FIVE_MINUTES_IN_SECONDS = 5 * 60;
export class ZoneSigner {
keyTag;
privateKey;
publicKey;
zoneName;
algorithm;
static async generate(algorithm, zoneName) {
const keyTag = generateKeyTag();
const keyGenOptions = getKeyGenOptions(algorithm);
const keyPair = await generateKeyPairAsync(keyGenOptions.type, keyGenOptions.options);
return new ZoneSigner(keyTag, keyPair.privateKey, keyPair.publicKey, zoneName);
return new ZoneSigner(keyPair.privateKey, keyPair.publicKey, zoneName, algorithm);
}
constructor(keyTag, privateKey, publicKey, zoneName) {
this.keyTag = keyTag;
constructor(privateKey, publicKey, zoneName, algorithm) {
this.privateKey = privateKey;
this.publicKey = publicKey;
this.zoneName = zoneName;
this.algorithm = algorithm;
}
generateDnskey(ttl, flags = {}) {
const data = serialiseDnskeyRdata(this.publicKey, flags);
return new Record(this.zoneName, RecordType.DNSKEY, DNSClass.IN, ttl, data);
generateDnskey(options = {}) {
const finalFlags = {
zoneKey: true,
secureEntryPoint: false,
...(options.flags ?? {}),
};
const data = new DnskeyData(this.publicKey, options.protocol ?? DnskeyData.PROTOCOL, this.algorithm, finalFlags);
const ttl = options.ttl ?? FIVE_MINUTES_IN_SECONDS;
const record = new Record(this.zoneName, DnssecRecordType.DNSKEY, DNSClass.IN, ttl, data.serialise());
const rrset = RRSet.init(record.makeQuestion(), [record, ...(options.additionalDnskeys ?? [])]);
const rrsig = this.generateRrsig(rrset, data.calculateKeyTag(), options);
return { data, message: rrsig.message, record, rrsig };
}
generateDs(childLabel, ttl, digestAlgorithm = DigestAlgorithm.SHA256) {
const data = serialiseDsRdata(this.keyTag, this.publicKey, digestAlgorithm);
return new Record(`${childLabel}.${this.zoneName}`, RecordType.DS, DNSClass.IN, ttl, data);
generateDs(childDnskey, childZoneName, dnskeyTag, options = {}) {
const isRootZone = childZoneName === this.zoneName && this.zoneName === '.';
if (!isRootZone && !this.isChildZone(childZoneName)) {
throw new Error(`${childZoneName} isn't a child of ${this.zoneName}`);
}
const digestType = options.digestType ?? DigestType.SHA256;
const data = new DsData(childDnskey.data.calculateKeyTag(), childDnskey.data.algorithm, digestType, DsData.calculateDnskeyDigest(childDnskey, digestType));
const record = new Record(childZoneName, DnssecRecordType.DS, DNSClass.IN, options.ttl ?? FIVE_MINUTES_IN_SECONDS, data.serialise());
const rrsig = this.generateRrsig(RRSet.init(record.makeQuestion(), [record]), dnskeyTag, options);
return { data, message: rrsig.message, record, rrsig };
}
generateRrsig(rrset, signatureExpiry, signatureInception = new Date()) {
const data = serialiseRrsigData(rrset, signatureExpiry, signatureInception, this.privateKey, this.zoneName, this.keyTag);
return new Record(rrset.name, RecordType.RRSIG, DNSClass.IN, rrset.ttl, data);
generateRrsig(rrset, keyTag, options = {}) {
if (rrset.name !== this.zoneName && !this.isChildZone(rrset.name)) {
throw new Error(`RRset for ${rrset.name} isn't a child of ${this.zoneName}`);
}
const signatureInception = options.signatureInception ?? new Date();
const signatureExpiry = options.signatureExpiry ?? addSeconds(signatureInception, rrset.ttl);
const data = RrsigData.generate(rrset, setMilliseconds(signatureExpiry, 0), setMilliseconds(signatureInception, 0), this.privateKey, this.zoneName, keyTag, this.algorithm);
const record = new Record(rrset.name, DnssecRecordType.RRSIG, DNSClass.IN, rrset.ttl, data.serialise());
const message = new Message({ rcode: RCode.NoError }, [new Question(rrset.name, rrset.type, rrset.class_)], [...rrset.records, record]);
return { data, message, record };
}
generateZoneResponses(parent, parentDnskeyTag, options = {}) {
const dnskey = this.generateDnskey(options.dnskey);
const ds = parent.generateDs(dnskey, this.zoneName, parentDnskeyTag ?? dnskey.data.calculateKeyTag(), options.ds);
return { ds, dnskey };
}
isChildZone(zoneName) {
if (this.zoneName === '.') {
return true;
}
return zoneName.endsWith(`.${this.zoneName}`);
}
}
//# sourceMappingURL=ZoneSigner.js.map
{
"name": "@relaycorp/dnssec",
"version": "1.0.0",
"version": "1.1.0",
"author": {

@@ -41,10 +41,10 @@ "email": "no-reply@relaycorp.tech",

"@leichtgewicht/dns-packet": "^6.0.3",
"@relaycorp/eslint-config": "^1.0.1",
"@relaycorp/eslint-config": "^1.0.4",
"@relaycorp/shared-config": "^1.9.2",
"@types/jest": "^27.5.0",
"@typescript-eslint/eslint-plugin": "^5.38.0",
"@typescript-eslint/parser": "^5.37.0",
"@typescript-eslint/eslint-plugin": "^5.42.1",
"@typescript-eslint/parser": "^5.41.0",
"del-cli": "^5.0.0",
"dohdec": "^5.0.3",
"eslint": "^8.24.0",
"eslint": "^8.27.0",
"jest": "^28.1.3",

@@ -57,6 +57,7 @@ "jest-date-mock": "^1.0.8",

"ts-node": "^10.9.1",
"typedoc": "^0.23.15",
"typescript": "^4.8.3"
"typedoc": "^0.23.21",
"typescript": "^4.8.4"
},
"dependencies": {
"bigint-buffer": "^1.1.5",
"binary-parser": "^2.2.1",

@@ -63,0 +64,0 @@ "date-fns": "^2.29.3"

@@ -30,2 +30,9 @@ # `@relaycorp/dnssec`

### Error handling
As this is primarily a DNSSEC library, we treat DNS and DNSSEC errors differently:
- Any input that violates DNS RFCs in ways from which we can't recover will result in errors.
- Any input that violates DNSSEC RFCs will result in one of the three failure _security statuses_ defined in [RFC 4035 (Section 4.3)](https://www.rfc-editor.org/rfc/rfc4035#section-4.3): insecure, bogus or indeterminate.
### Denial of Existence record support

@@ -32,0 +39,0 @@

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc