class Dnsruby::RR::DNSKEY
RFC4034, section 2 DNSSEC uses public key cryptography to sign and authenticate DNS
resource record sets (RRsets). The public keys are stored in DNSKEY
resource records and are used in the DNSSEC authentication process described in [RFC4035]: A zone signs its authoritative RRsets by using a private key and stores the corresponding public key in a DNSKEY
RR
. A resolver can then use the public key to validate signatures covering the RRsets in the zone, and thus to authenticate them.
Constants
- REVOKED_KEY
Key is revoked
- SEP_KEY
Key is a secure entry point key
- ZONE_KEY
Key is a zone key
Attributes
The algorithm used for this key See Dnsruby::Algorithms
for permitted values
The public key
The length (in bits) of the key - NOT key.length
Public Instance Methods
# File lib/dnsruby/resource/DNSKEY.rb, line 71 def algorithm=(a) if (a.instance_of?String) if (a.to_i > 0) a = a.to_i end end begin alg = Algorithms.new(a) @algorithm = alg rescue ArgumentError => e raise DecodeError.new(e) end get_new_key_tag end
# File lib/dnsruby/resource/DNSKEY.rb, line 353 def dsa_key t = @key[0] t = t.getbyte(0) if t.class == String pgy_len = t * 8 + 64 pos = 1 q = RR::get_num(@key[pos, 20]) pos += 20 p = RR::get_num(@key[pos, pgy_len]) pos += pgy_len g = RR::get_num(@key[pos, pgy_len]) pos += pgy_len y = RR::get_num(@key[pos, pgy_len]) pos += pgy_len @key_length = (pgy_len * 8) asn1 = OpenSSL::ASN1::Sequence.new( [ OpenSSL::ASN1::Sequence.new( [ OpenSSL::ASN1::ObjectId.new('DSA'), OpenSSL::ASN1::Sequence.new( [ OpenSSL::ASN1::Integer.new(p), OpenSSL::ASN1::Integer.new(q), OpenSSL::ASN1::Integer.new(g) ] ) ] ), OpenSSL::ASN1::BitString.new(OpenSSL::ASN1::Integer.new(y).to_der) ] ) pkey = OpenSSL::PKey::DSA.new(asn1.to_der) end
RFC6605, section 4 ECDSA public keys consist of a single value, called “Q” in FIPS 186-3. In DNSSEC keys, Q is a simple bit string that represents the uncompressed form of a curve point, “x | y”.
# File lib/dnsruby/resource/DNSKEY.rb, line 393 def ec_key(curve = 'prime256v1') group = OpenSSL::PKey::EC::Group.new(curve) pkey = OpenSSL::PKey::EC.new(group) # DNSSEC pub does not have first octet that determines whether it's uncompressed # or compressed form, but it's required by OpenSSL to parse EC point correctly public_key_with_prefix = "\x04" + @key.to_s pkey = OpenSSL::PKey::EC.new(group, public_key_with_prefix) pkey end
# File lib/dnsruby/resource/DNSKEY.rb, line 125 def flags=(f) # Only three values allowed - # Zone Key flag (bit 7) # Secure Entry Point flag (bit 15) # Revoked bit (bit 8) - RFC 5011 if ((f & ~ZONE_KEY & ~SEP_KEY & ~REVOKED_KEY) > 0) TheLog.info("DNSKEY: Only zone key, secure entry point and revoked flags allowed for DNSKEY" + " (RFC4034 section 2.1.1) : #{f} entered as input") end @flags = f get_new_key_tag end
# File lib/dnsruby/resource/DNSKEY.rb, line 165 def from_string(input) if (input.length > 0) @make_new_key_tag = false data = input.split(" ") self.flags=(data[0].to_i) self.protocol=(data[1].to_i) self.algorithm=(data[2]) # key can include whitespace - include all text # until we come to " )" at the end, and then gsub # the white space out # Also, brackets may or may not be present # Not to mention comments! ";" buf = "" index = 3 end_index = data.length - 1 if (data[index]=="(") end_index = data.length - 2 index = 4 end (index..end_index).each {|i| if (comment_index = data[i].index(";")) buf += data[i].slice(0, comment_index) # @TODO@ We lose the comments here - we should really keep them for when we write back to string format? break else buf += data[i] end } self.key=(buf) @make_new_key_tag = true get_new_key_tag end end
# File lib/dnsruby/resource/DNSKEY.rb, line 252 def generate_key_tag(rdata, algorithm) tag=0 if (algorithm == Algorithms.RSAMD5) # The key tag for algorithm 1 (RSA/MD5) is defined differently from the # key tag for all other algorithms, for historical reasons. d1 = rdata[rdata.length - 3] & 0xFF d2 = rdata[rdata.length - 2] & 0xFF tag = (d1 << 8) + d2 else tag = 0 last = 0 0.step(rdata.length - 1, 2) {|i| last = i d1 = rdata[i] d2 = rdata[i + 1] || 0 # odd number of bytes possible d1 = d1.getbyte(0) if d1.class == String # Ruby 1.9 d2 = d2.getbyte(0) if d2.class == String # Ruby 1.9 d1 = d1 & 0xFF d2 = d2 & 0xFF tag += ((d1 << 8) + d2) } last+=2 if (last < rdata.length) d1 = rdata[last] if (d1.class == String) # Ruby 1.9 d1 = d1.getbyte(0) end d1 = d1 & 0xFF tag += (d1 << 8) end tag += ((tag >> 16) & 0xFFFF) end tag=tag&0xFFFF return tag end
# File lib/dnsruby/resource/DNSKEY.rb, line 233 def get_new_key_tag if (@make_new_key_tag) rdata = MessageEncoder.new {|msg| encode_rdata(msg) }.to_s tag = generate_key_tag(rdata, @algorithm) @key_tag = tag end end
# File lib/dnsruby/resource/DNSKEY.rb, line 53 def init_defaults @make_new_key_tag = false self.protocol=3 self.flags=ZONE_KEY @algorithm=Algorithms.RSASHA1 @public_key = nil @key_tag = nil @make_new_key_tag = true end
# File lib/dnsruby/resource/DNSKEY.rb, line 293 def key=(key_text) begin key_text.gsub!(/\n/, "") key_text.gsub!(/ /, "") @key=Base64.decode64(key_text) public_key get_new_key_tag rescue Exception => e Dnsruby.log.error(e) raise ArgumentError.new("Key #{key_text} invalid") end end
Return the tag for this key
# File lib/dnsruby/resource/DNSKEY.rb, line 244 def key_tag if (!@key_tag) @make_new_key_tag = true get_new_key_tag end return @key_tag end
Return the the key tag this key would have had before it was revoked If the key is not revoked, then the current key_tag
will be returned
# File lib/dnsruby/resource/DNSKEY.rb, line 224 def key_tag_pre_revoked if (!revoked?) return key_tag end new_key = clone new_key.revoked = false return new_key.key_tag end
# File lib/dnsruby/resource/DNSKEY.rb, line 63 def protocol=(p) if (p!=3) raise DecodeError.new("DNSKEY protocol field set to #{p}, contrary to RFC4034 section 2.1.2") else @protocol = p end get_new_key_tag end
# File lib/dnsruby/resource/DNSKEY.rb, line 306 def public_key if (!@public_key) if [Algorithms.RSASHA1, Algorithms.RSASHA256, Algorithms.RSASHA512, Algorithms.RSASHA1_NSEC3_SHA1].include?(@algorithm) @public_key = rsa_key elsif [Algorithms.DSA, Algorithms.DSA_NSEC3_SHA1].include?(@algorithm) @public_key = dsa_key elsif [Algorithms.ECDSAP256SHA256, Algorithms.ECDSAP384SHA384].include?(@algorithm) @public_key = ec_key(Algorithms.ECDSAP256SHA256 == @algorithm ? 'prime256v1' : 'secp384r1') end end # @TODO@ Support other key encodings! return @public_key end
# File lib/dnsruby/resource/DNSKEY.rb, line 86 def revoked=(on) if (on) @flags |= REVOKED_KEY else @flags &= (~REVOKED_KEY) end get_new_key_tag end
# File lib/dnsruby/resource/DNSKEY.rb, line 95 def revoked? return ((@flags & REVOKED_KEY) > 0) end
# File lib/dnsruby/resource/DNSKEY.rb, line 324 def rsa_key exponentLength = @key[0] if (exponentLength.class == String) exponentLength = exponentLength.getbyte(0) # Ruby 1.9 end pos = 1 if (exponentLength == 0) key1 = @key[1] if (key1.class == String) # Ruby 1.9 key1 = key1.getbyte(0) end exponentLength = (key1<<8) + key1 pos += 2 end exponent = RR::get_num(@key[pos, exponentLength]) pos += exponentLength modulus = RR::get_num(@key[pos, @key.length]) @key_length = (@key.length - pos) * 8 data_sequence = OpenSSL::ASN1::Sequence([ OpenSSL::ASN1::Integer(modulus), OpenSSL::ASN1::Integer(exponent) ]) asn1 = OpenSSL::ASN1::Sequence(data_sequence) pkey = OpenSSL::PKey::RSA.new(asn1.to_der) return pkey end
# File lib/dnsruby/resource/DNSKEY.rb, line 112 def sep_key=(on) if (on) @flags |= SEP_KEY else @flags &= (~SEP_KEY) end get_new_key_tag end
# File lib/dnsruby/resource/DNSKEY.rb, line 121 def sep_key? return ((@flags & SEP_KEY) > 0) end
# File lib/dnsruby/resource/DNSKEY.rb, line 99 def zone_key=(on) if (on) @flags |= ZONE_KEY else @flags &= (~ZONE_KEY) end get_new_key_tag end
# File lib/dnsruby/resource/DNSKEY.rb, line 108 def zone_key? return ((@flags & ZONE_KEY) > 0) end