Построение части RDATA DNSKEY RR
Я нахожусь в процессе завершения плагина Регистратора домена для биллинговой системы (которая также управляет инициализацией домена в этом случае), и последний бит связан с реализацией поддержки DNSSEC.
Биллинговая система отправляет следующие данные, связанные с SAMPLE DNSSEC, в мой плагин PHP:
'dnsSecInfo' =>
array (
0 =>
array (
'keyAlg' => 5,
'digestAlg' => 1,
'digest' => '1d181b34061ee98088b7a9e6db6e41a130674df0',
'key' => 'AwEAAaqZeENizOE6uvpDtIfQBB26YebvRdZA/ZjXjKLZdMmMK641sBIvho+yrTveIYclM+8lEVHiq64MY8R2G1IPmKDKXG26rM7NVE0Qx1KL2wRVbRrduRdBmKgJo3XQ3niueviKYXXmeVIO3EhrJsCq272Tm3DaDvng/M7uw1vDnanR2pYNcxI08fZOA6PLGDoUWlDNLGAHHkCvfdWUktVt1DA0GtL/qE/WUgxK6hJyeaXXb0+yq3qCMZh48WgluMFib54D0GN3PI3ZZvBMblAZHmFGqgyVwtPKEimXm/VREe2QtZy3cRgPbfOuiQi8gRhzO+/If8Wi9YnyLovjdsSjRsE=',
),
),
RFC 4034 имеет следующее:
2.1. DNSKEY RDATA Wire Format
The RDATA for a DNSKEY RR consists of a 2 octet Flags Field, a 1
octet Protocol Field, a 1 octet Algorithm Field, and the Public Key
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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Flags | Protocol | Algorithm |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
/ /
/ Public Key /
/ /
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Приложение B того же протокола:
The input is the wire
format of the RDATA portion of the DNSKEY RR.
.....
unsigned int
keytag (
unsigned char key[], /* the RDATA part of the DNSKEY RR */
unsigned int keysize /* the RDLENGTH */
)
{
unsigned long ac; /* assumed to be 32 bits or larger */
int i; /* loop index */
for ( ac = 0, i = 0; i < keysize; ++i )
ac += (i & 1) ? key[i] : key[i] << 8;
ac += (ac >> 16) & 0xFFFF;
return ac & 0xFFFF;
}
Реестр, в котором регистрируется домен, занимает 4 обязательных поля:
- Keytag
- Алгоритм (считается равным keyAlg во входных данных плагина)
- Тип дайджеста (я считаю, что он называется digestAlg во входных данных плагина)
- Дайджест (так же, как дайджест, вероятно)
Другие необязательные поля: флаги, протокол, алгоритм, открытый ключ (который является "ключом" в плагине...)
Теперь я заблудился... Как мне реализовать вышеописанную функцию C в PHP?
- Как мне построить "DNSKEY RDATA", который является
key
массив символов? (Угадаю, что октеты Flags являются значениями по умолчанию, например, 0, 256 или 257, пока не уверены), тогда октет протокола - это значение keyAlg 5 в этом примере, за которым следует октет алгоритма, который всегда равен 3, и, наконец, октет ключа - это ключ, Это предположение правильно??) - Является ли массив символов ключа [] RDATA двоичным массивом? или аськи чарс? (имеется в виду, что после создания мне не нужно сначала преобразовывать его в двоичные биты?)
- Что такое
& 0xFFFF
цель в алгоритме? Что такое эквивалент PHP? Я склонен думать, что это почти то же самое, так как PHP основан на C в синтаксисе... но без правильных примеров ввода / вывода будет трудно убедиться, что я все понял правильно...
1 ответ
Ваш вопрос не очень понятен. Вы строите систему регистратора или что-то, что соединяется с регистратором? Также ваш заголовок говорит о создании DNSKEY RDATA, но тогда весь ваш вопрос касается вычисления keyid/keytag, который в любом случае не публикуется с записью DNSKEY (только публикуется с записями RRSIG, но такими инструментами, как dig
можно пересчитать его, чтобы отобразить его как комментарий, чтобы помочь вам при просмотре записей DNSKEY).
В любом случае вам не нужно иметь дело с форматом передачи данных DNSSEC. В первом случае (система регистратора) вы взаимодействуете с реестром, как правило, с EPP, который имеет специальное расширение для данных DNSSEC, называемое secDNS. См. RFC5910
Теперь что касается самого DNSSEC. Он использует криптографию, поэтому лучше не пытаться переделывать вещи вручную. Кажется, PHP имеет Net_DNS2
это могло бы помочь.
Но то, что я не понимаю, это то, почему вы должны испортить ценности. Если вы являетесь регистратором, вы передаете в реестр значения, которые дали вам ваши клиенты; Вы можете немного проверить их синтаксис, но, кроме того, вы просто передаете их. Если вы отправляете данные регистратору в качестве клиента, вы снова откуда-то получили эти данные, я не понимаю, почему вы должны действовать в соответствии с ними.
Теперь вы говорите о реестре, так что пока я представлю, что вы регистратор. Начните с чтения RFC5910. Вы увидите, что существует два интерфейса и фактически три случая, в порядке от наиболее часто используемого сейчас и до менее частого:
-
dsData
интерфейс, в котором вы, как регистратор, даете реестру запись DS в основном для публикации в реестре; эти данные (на самом деле 4 поля, вы перечислите их в своем первом наборе) составлены из ключа, который вы или хостинговая компания опубликуете в доменном файле зоны как запись DNSKEY. -
keyData
интерфейс, опять же с 4 полями, но не такой, как у 4 предыдущих (есть в вашем втором наборе или структуре PHP в верхней части вашего поста), где вы фактически отправляете ключу реестра (его публичную часть), из которого реестр будет вычислять саму запись DS - и смешанный случай, когда это в основном
dsData
сkeyData
внутри, что означает, что вы отправляете как DS для публикации, так и связанный ключ, причем этот ключ бесполезен, но реестр может повторить вычисление DS для проверки, исходя из ключа.
Если вы прочитаете RFC, у вас будут объяснения по 2 наборам из 4 полей и их значения.
Для некоторых из них вы можете использовать только несколько отдельных значений:
- значение алгоритма может быть только одно из https://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml
- значение алгоритма хеширования может быть только одно из https://www.iana.org/assignments/ds-rr-types/ds-rr-types.xhtml
Что касается ваших конкретных вопросов, которые, кажется, вы пытаетесь вычислить keyID/keytag из содержимого ключа (удивительно, что было обнаружено, что этот алгоритм имеет недостатки, но в любом случае), как я уже говорил ранее, вы не должны пытаться повторить это самостоятельно. Если возможно, попытайтесь найти библиотеку PHP, которая сделает это за вас, или, по крайней мере, используйте существующие инструменты, но это зависит от того, как генерируются ваши ключи, откуда вы их получаете и т. Д. См., Например, этот инструмент: https://linux.die.net/man/8/dnssec-keygen
В противном случае у вас есть этот код: https://www.v13.gr/blog/?p=239 Он написан на Python, но вы можете извлечь версию PHP из него. Помните, что метка ключа зависит только от содержимого ключа, где значение хэша DS зависит как от ключа, так и от имени домена (поэтому, даже если вы используете один и тот же ключ для разных доменных имен, значение DS будет отличаться).
Так что для вашего 1) + 2) примерно 4 поля, необходимые для keyData
интерфейс:
- flag: либо 256, либо 257 в зависимости от того, используется ли ключ в качестве KSK или ZSK; в качестве регистратора, передающего ключевые значения в реестры, это должны быть только KSK, поэтому значение 257.
- протокол: всегда значение 3, см. 2.1.2. из RFC4034
- Алгоритм: из Приложения 1 того же RFC, который в основном является первой ссылкой из двух вышеупомянутых
iana.org
- входом алгоритма является значение DNSKEY RDATA, как написано в разделе 2.2: "Поле открытого ключа ДОЛЖНО быть представлено в виде кодировки Base64 открытого ключа.", так что это список символов.
Что касается 3): делать & 0xFFFF
означает брать 16-битные младшие разряды (обычно самые правые 16-битные, когда вы их записываете), потому что &
является логическим И, и 0xFFFF равен 2^16 - 1 (65535), то есть 16 битов установлены на значение 1. В противном случае, если конечное значение превышает 65535, мы сохраняем только его часть с этой операцией, так как тэг ключа определяется как 16-битное значение.
Кстати, вы можете использовать dnssec-keygen
Команда для создания ключей и их ключей, чтобы проверить свой собственный алгоритм.
dnssec-keygen -a RSASHA256 -b 2048 test1
будет производить:
Generating key pair.......+++ ............................+++
Ktest1.+008+05433
В сгенерированном имени файла 008
это алгоритм (от RSASHA256) и 05433
вычисляется keyId (keytag). Если вы посмотрите на файл вычисляется в окончании .key
у вас есть полная запись DNSKEY с ключом, закодированным как Base64, согласно спецификации (которая является вводом алгоритма для вычисления keyid).
Я надеюсь, что вы найдете хотя бы некоторые полезные идеи в вышеприведенном материале, но я боюсь, что не понял ваш вопрос достаточно хорошо, чтобы быть более конкретным.