MailSharp / MailSharp.DNS / Records / RecordRRSIG.cs
Code · 78 lines · 3128 bytes
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78/*
https://www.rfc-editor.org/rfc/rfc4034.html

RRSIG RDATA Wire Format

   The RDATA for an RRSIG RR consists of a 2 octet Type Covered field, a
   1 octet Algorithm field, a 1 octet Labels field, a 4 octet Original
   TTL field, a 4 octet Signature Expiration field, a 4 octet Signature
   Inception field, a 2 octet Key tag, the Signer's Name field, and the
   Signature field.

                        1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |        Type Covered           |  Algorithm    |     Labels    |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                         Original TTL                          |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                      Signature Expiration                     |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                      Signature Inception                      |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |            Key Tag            |                               /
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+         Signer's Name         /
   /                                                               /
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   /                                                               /
   /                            Signature                          /
   /                                                               /
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 */

using MailSharp.DNS.Records;

namespace MailSharp.DNS.Records;

public record RecordRRSIG : DnsRecord
{
	public DnsType TypeCovered { get; init; }
	public byte Algorithm { get; init; }
	public byte Labels { get; init; }
	public uint OriginalTtl { get; init; }
	public DateTime Expiration { get; init; }  // UTC
	public DateTime Inception { get; init; }    // UTC
	public ushort KeyTag { get; init; }
	public string SignerName { get; init; } = string.Empty;
	public byte[] Signature { get; init; } = [];

	public RecordRRSIG(RecordReader rr) : base(rr)
	{
		ushort rdLength = rr.ReadUInt16(-2);

		TypeCovered = (DnsType)rr.ReadUInt16();
		Algorithm = rr.ReadByte();
		Labels = rr.ReadByte();
		OriginalTtl = rr.ReadUInt32();
		Expiration = DateTimeOffset.FromUnixTimeSeconds(rr.ReadUInt32()).UtcDateTime;
		Inception = DateTimeOffset.FromUnixTimeSeconds(rr.ReadUInt32()).UtcDateTime;
		KeyTag = rr.ReadUInt16();
		SignerName = rr.ReadDomainName();

		Signature = rr.ReadBytes(rdLength - rr.Position);
	}

	public override string ToString()
	{
		// Tijdstempels in YYYYMMDDHHmmSS formaat (UTC), precies zoals BIND/dig
		string exp = Expiration.ToString("yyyyMMddHHmmss");
		string inc = Inception.ToString("yyyyMMddHHmmss");

		string sigBase64 = Signature.Length == 0
			? "."
			: Convert.ToBase64String(Signature);

		return $"{TypeCovered} {Algorithm} {Labels} {OriginalTtl} {exp} {inc} {KeyTag} {SignerName} {sigBase64}";
	}

}