#!/usr/bin/perl use 5.008; use strict; use warnings; use Digest::SHA qw[]; use MIME::Base64 qw[]; use Net::DNS qw[]; use URI qw[]; my $webid = URI->new(shift @ARGV or die "Please provide a URI.\n"); my $proxy = join '.', Digest::SHA::sha1_hex("$webid"), $webid->host; my $dns = Net::DNS::Resolver->new; my $query = $dns->query($proxy, 'TXT'); my (%data, $source); if ($query) { foreach my $rr ($query->answer) { next unless $rr->type eq 'TXT'; # double-check next unless $rr->name eq $proxy; # double-check my ($txt) = ($rr->rdatastr =~ /^"(.+)"$/); # Allow the proxy record to contain non-WebID TXT data too! next unless $txt =~ /^webid\s/; foreach my $part (split /\s+/, $txt) { my ($key, $value) = split /=/, $part, 2; # split on first '=' $data{$key} = $value; } } # RFC 4501 URI $source = sprintf("dns://%s/%s?TYPE=TXT", $query->answerfrom, $proxy); } if (exists $data{webid} && exists $data{e} && exists $data{n}) { use bytes; # i.e. treat strings as octet sequences my %hex; foreach my $number (qw(e n)) { my $bin = MIME::Base64::decode_base64( $data{$number} ); $hex{$number} = ''; while (length $bin) { $hex{$number} .= sprintf('%02X', ord($bin)); $bin = substr($bin, 1); } } printf(<<'TURTLE', $webid, $hex{'e'}, $hex{'n'}, $source); @prefix foaf: . @prefix cert: . @prefix rsa: . [] a rsa:RSAPublicKey ; cert:identity <%1$s> ; rsa:public_exponent "%2$s"^^cert:hex ; rsa:modulus "%3$s"^^cert:hex . <%1$s> a foaf:Agent ; foaf:page <%4$s> . TURTLE } else { die "Could not process WebID <$webid> via DNS\n"; }