return drc;
}
+DNSKEYRecordContent getRSAKeyFromPEMString(rsa_context* rsa, const std::string& raw)
+{
+ vector<string> integers;
+ decodeDERIntegerSequence(raw, integers);
+ cerr<<"Got "<<integers.size()<<" integers"<<endl;
+ map<int, mpi*> places;
+
+ rsa_init(rsa, RSA_PKCS_V15, 0, NULL, NULL );
+
+ places[1]=&rsa->N;
+ places[2]=&rsa->E;
+ places[3]=&rsa->D;
+ places[4]=&rsa->P;
+ places[5]=&rsa->Q;
+ places[6]=&rsa->DP;
+ places[7]=&rsa->DQ;
+ places[8]=&rsa->QP;
+
+ DNSKEYRecordContent drc;
+ string modulus, exponent;
+
+ for(int n = 0; n < 9 ; ++n) {
+ if(places.count(n)) {
+ if(places[n]) {
+ mpi_read_binary(places[n], (const unsigned char*)integers[n].c_str(), integers[n].length());
+ if(n==1)
+ modulus=integers[n];
+ if(n==2)
+ exponent=integers[n];
+ }
+ }
+ }
+ rsa->len = ( mpi_msb( &rsa->N ) + 7 ) >> 3; // no clue what this does
+
+ if(exponent.length() < 255)
+ drc.d_key.assign(1, (char) (unsigned int) exponent.length());
+ else {
+ drc.d_key.assign(1, 0);
+ uint16_t len=htons(exponent.length());
+ drc.d_key.append((char*)&len, 2);
+ }
+ drc.d_key.append(exponent);
+ drc.d_key.append(modulus);
+ drc.d_protocol=3;
+
+ return drc;
+}
void makeRSAPublicKeyFromDNS(rsa_context* rc, const DNSKEYRecordContent& dkrc)
{
return makeDNSKEYFromRSAKey(&d_key.getConstContext(), d_algorithm, d_flags);
}
+
+class DEREater
+{
+public:
+ DEREater(const std::string& str) : d_str(str), d_pos(0)
+ {}
+
+ struct eof{};
+
+ uint8_t getByte()
+ {
+ if(d_pos >= d_str.length()) {
+ throw eof();
+ }
+ return (uint8_t) d_str[d_pos++];
+ }
+
+ uint32_t getLength()
+ {
+ uint8_t first = getByte();
+ if(first < 0x80) {
+ return first;
+ }
+ first &= ~0x80;
+
+ uint32_t len=0;
+ for(int n=0; n < first; ++n) {
+ len *= 0x100;
+ len += getByte();
+ }
+ return len;
+ }
+
+ std::string getBytes(unsigned int len)
+ {
+ std::string ret;
+ for(unsigned int n=0; n < len; ++n)
+ ret.append(1, (char)getByte());
+ return ret;
+ }
+
+ std::string::size_type getOffset()
+ {
+ return d_pos;
+ }
+private:
+ const std::string& d_str;
+ std::string::size_type d_pos;
+};
+
+void decodeDERIntegerSequence(const std::string& input, vector<string>& output)
+{
+ output.clear();
+ DEREater de(input);
+ if(de.getByte() != 0x30)
+ throw runtime_error("Not a DER sequence");
+
+ unsigned int seqlen=de.getLength();
+ unsigned int startseq=de.getOffset();
+ unsigned int len;
+ string ret;
+ try {
+ for(;;) {
+ uint8_t kind = de.getByte();
+ if(kind != 0x02)
+ throw runtime_error("DER Sequence contained non-INTEGER component: "+lexical_cast<string>((unsigned int)kind) );
+ len = de.getLength();
+ ret = de.getBytes(len);
+ output.push_back(ret);
+ }
+ }
+ catch(DEREater::eof& eof)
+ {
+ if(de.getOffset() - startseq != seqlen)
+ throw runtime_error("DER Sequence ended before end of data");
+ }
+
+}
DNSKEYRecordContent getRSAKeyFromISC(rsa_context* rsa, const char* fname);
DNSKEYRecordContent getRSAKeyFromISCString(rsa_context* rsa, const std::string& content);
+DNSKEYRecordContent getRSAKeyFromPEMString(rsa_context* rsa, const std::string& content);
void makeRSAPublicKeyFromDNS(rsa_context* rc, const DNSKEYRecordContent& dkrc);
bool sharedDNSSECCompare(const boost::shared_ptr<DNSRecordContent>& a, const shared_ptr<DNSRecordContent>& b);
string getHashForRRSET(const std::string& qname, const RRSIGRecordContent& rrc, std::vector<boost::shared_ptr<DNSRecordContent> >& signRecords);
vector<shared_ptr<DNSRecordContent> >& toSign, vector<RRSIGRecordContent> &rrc, bool ksk);
std::string hashQNameWithSalt(unsigned int times, const std::string& salt, const std::string& qname);
+void decodeDERIntegerSequence(const std::string& input, vector<string>& output);
#endif
</listitem>
</varlistentry>
<varlistentry>
- <term>export-zone-dnskey ZONE KEY-ID</term>
+ <term>export-zone-key ZONE KEY-ID</term>
<listitem>
<para>
Export to standard output full (private) key with key id KEY-ID within zone called ZONE. The format
</listitem>
</varlistentry>
<varlistentry>
- <term>import-zone-dnskey ZONE filename [ksk|zsk]</term>
+ <term>import-zone-key ZONE filename [ksk|zsk]</term>
<listitem>
<para>
Import from 'filename' a full (private) key for zone called ZONE. The format
</para>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term>import-zone-key-pem ZONE filename algorithm [ksk|zsk]</term>
+ <listitem>
+ <para>
+ Import from 'filename' a full (private) key in PEM format for zone called ZONE, and
+ assign it an algorithm number. KSK or ZSK specifies the flags this
+ key should have on import. The format used is compatible with 'openssl genrsa',
+ which is also called PEM.
+ </para>
+ </listitem>
+ </varlistentry>
<varlistentry>
<term>rectify-zone ZONE</term>
<listitem>
<listitem><para>Olaf Kolkman (NLNetLabs)</para></listitem>
<listitem><para>Wouter Wijngaards (NLNetLabs)</para></listitem>
<listitem><para>Marco Davids (SIDN)</para></listitem>
- <listitem><para>Marcus Travaille (SIDN)</para></listitem>
+ <listitem><para>Markus Travaille (SIDN)</para></listitem>
<listitem><para>Antoin Verschuren (SIDN)</para></listitem>
<listitem><para>Olafur Guðmundsson (IETF)</para></listitem>
<listitem><para>Dan Kaminsky (Recursion Ventures)</para></listitem>
<listitem><para>Johannes Kuehrer (Austrian World4You GmbH)</para></listitem>
<listitem><para>Marc van de Geijn (bHosted.nl)</para></listitem>
<listitem><para>Stefan Arentz</para></listitem>
+ <listitem><para>Martin van Hensbergen (Fox-IT)</para></listitem>
<listitem><para>.. this list is far from complete yet .. </para></listitem>
</itemizedlist>
#include "dnssecinfra.hh"
#include "statbag.hh"
#include "base32.hh"
+#include "base64.hh"
#include <boost/foreach.hpp>
#include <boost/program_options.hpp>
#include "dnsbackend.hh"
DNSSECPrivateKey dpk=dk.getKeyById(zone, id);
cout << dpk.d_key.convertToISC(dpk.d_algorithm) <<endl;
}
+ else if(cmds[0]=="import-zone-key-pem") {
+ if(cmds.size() < 4) {
+ cerr<<"Syntax: pdnssec import-zone-key zone-name filename.pem algorithm [zsk|ksk]"<<endl;
+ exit(1);
+ }
+ string zone=cmds[1];
+ string fname=cmds[2];
+ string line;
+ ifstream ifs(fname.c_str());
+ string tmp, interim, raw;
+ while(getline(ifs, line)) {
+ if(line[0]=='-')
+ continue;
+ trim(line);
+ interim += line;
+ }
+ B64Decode(interim, raw);
+ DNSSECPrivateKey dpk;
+ getRSAKeyFromPEMString(&dpk.d_key.getContext(), raw);
+
+ dpk.d_algorithm = atoi(cmds[3].c_str());
+
+ if(dpk.d_algorithm == 7)
+ dpk.d_algorithm = 5;
+
+ cerr<<(int)dpk.d_algorithm<<endl;
+
+ if(cmds.size() > 4) {
+ if(pdns_iequals(cmds[4], "ZSK"))
+ dpk.d_flags = 256;
+ else if(pdns_iequals(cmds[4], "KSK"))
+ dpk.d_flags = 257;
+ else {
+ cerr<<"Unknown key flag '"<<cmds[4]<<"'\n";
+ exit(1);
+ }
+ }
+ else
+ dpk.d_flags = 257; // ksk
+
+ dk.addKey(zone, dpk);
+
+ }
else if(cmds[0]=="import-zone-key") {
if(cmds.size() < 3) {
cerr<<"Syntax: pdnssec import-zone-key zone-name filename [zsk|ksk]"<<endl;