[dns-operations] calculating DNSSEC keytags in awk

Lutz Donnerhacke lutz at iks-jena.de
Fri Dec 16 23:19:43 UTC 2011


In iks.lists.dns-operations, you wrote:
> I realise I'm probably the only person in the world who would ever
> want to do such a thing

No, you are not that alone.

> It seems to generate the right keytags for the zones I have been
> playing with.

Fine!

#! /usr/bin/perl

package dnskey2ds;

use strict;
use warnings;

use Digest;
use MIME::Base64;

BEGIN {
  use Exporter	 ();
  use vars	 qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);

  $VERSION     = 1.00;
  @ISA	       = qw(Exporter);
  @EXPORT      = qw(&generate_ds);
  %EXPORT_TAGS = ( );	  # eg:	TAG => [ qw!name1 name2! ],

  # your exported package globals go here,
  # as well as any optionally exported functions
  @EXPORT_OK   = qw(&generate_ds);
  
}

use vars @EXPORT_OK;
my $sha1 = Digest->new("SHA-1");

sub generate_ds($$) {
  my $fqdn = shift;
  my ($flags, $prot, $algo, $key) = split(/\s+/, shift, 4);
  my $rdata = join("", map {decode_base64 $_} (split /\s+/, $key));

  local $_;
  $sha1->reset();
  
  $fqdn =~ s/\.$//;
  foreach (split (/\./,$fqdn)) { $sha1->add(pack("c/a*",$_)); }
  $sha1->add(pack("c/a*",""));

  my $wire = pack("ncc", $flags, 3, $algo) . $rdata;
  $sha1->add($wire);
  
  my $keytag;
  if($algo == 1) {
    $keytag = 0xffff & unpack("n", substr($wire,-3,2)) ;
  } else {
    my ($sum, $i);
    for($sum = $i = 0; $i < length $wire; $i++) {
      $_ = unpack("C", substr($wire,$i,1));
      $sum += ($i & 1) ? $_ : $_ << 8;
    }
    $keytag = 0xffff & ($sum + ($sum >> 16));
  }
  
  my $comment = "";
  if($algo == 3) {
    $_ = $rdata;
    my $len = 8*(64 + 8*unpack("C", substr($_,0,1)));
    $comment = "; Modulus = $len bit";
  } elsif($algo == 5 || $algo == 1) {
    $_ = $rdata;
    my ($len, $exponent);
    $len = unpack("C", substr($_,0,1));
    $_ = substr($_,1);
    unless($len) {
      $len = unpack("n", substr($_,0,2));
      $_ = substr($_,2);
    }
    if($len == 1) {
      $exponent = unpack("C", substr($_,0,1));
    } elsif($len == 2) {
      $exponent = unpack("n", substr($_,0,2));
    } elsif($len == 3) {
      $exponent = unpack("n", substr($_,0,2)) * 256
                + unpack("C", substr($_,2,1));
    } elsif($len == 4) {
      $exponent = unpack("N", substr($_,0,4));
    } elsif($len == 5) {
      $exponent = unpack("N", substr($_,0,4)) * 256
                + unpack("C", substr($_,4,1));
    }
    $_ = substr($_,$len);
    $_ = 8*(length $_);
    $comment = "; Modulus = $_ bit";
    if($exponent) {
      $comment .= ", Exponent = $exponent";
    } else {
      $comment .= ", Exponent = $len byte";
    }
  }
  return "$keytag $algo 1 ${\$sha1->hexdigest()} $comment";
}

1;



More information about the dns-operations mailing list