new chapter in article
This commit is contained in:
@@ -103,7 +103,88 @@ H_b(R)\subseteq H_b(P).
|
||||
|
||||
Для каждого имени вычисляется 32-битный Jenkins one-at-a-time [\Ref{JENKINS}], после чего сохраняются только $b$ младших бит. Пусть $n$ различных имён независимо и равномерно отображаются в пространство из $N=2^b$ значений. Тогда математическое ожидание числа столкнувшихся пар равно
|
||||
|
||||
\[
|
||||
\mathbb{E}C=\binom{n}{2}\frac{1}{2^b}
|
||||
=\frac{n(n-1)}{2^{b+1}},
|
||||
\]
|
||||
а вероятность хотя бы одной коллизии имеет вид
|
||||
\[
|
||||
\P(C>0)=1-\prod_{i=0}^{n-1}\left(1-\frac{i}{2^b}\right)
|
||||
\approx 1-\exp\left(-\frac{n(n-1)}{2^{b+1}}\right).
|
||||
\]
|
||||
Эти выражения являются модельными: Jenkins OAAT не является случайным оракулом, поэтому окончательная оценка должна дополняться измерением коллизий на реальном корпусе символов.
|
||||
|
||||
Эвристическую верхнюю оценку ложного принятия при $k=|R\setminus P|$ отсутствующих символов можно записать как
|
||||
\[
|
||||
\Pr\bigl(H_b(R)\subseteq H_b(P)\mid R\nsubseteq P\bigr)
|
||||
\lesssim
|
||||
\left(\frac{|H_b(P)|}{2^b}\right)^k.
|
||||
\]
|
||||
Увеличение $b$ снижает вероятность ошибки, но увеличивает кодируемые значения и длину строки. Поэтому выбор \texttt{bpp} представляет собой компромисс между компактностью метаданных и риском коллизий; при формировании \texttt{set:}-строки для \texttt{Requires} набора используется точность, определённая по числу символов соответствующего \texttt{Provides}, а не по обычно намного меньшему числу требований.
|
||||
|
||||
\subsection{Кодирование Голомба--Райса}
|
||||
|
||||
После сортировки уникальных значений
|
||||
\[
|
||||
0\leq x_1<x_2<\dots<x_n<2^b
|
||||
\]
|
||||
они заменяются дельтами
|
||||
\[
|
||||
\delta_1=x_1,
|
||||
\qquad
|
||||
\delta_i=x_i-x_{i-1},\quad i=2,\dots,n.
|
||||
\]
|
||||
Для равномерных хешей средний промежуток имеет порядок $2^b/n$, поэтому дельты значительно меньше абсолютных значений и хорошо подходят для кодирования Голомба--Райса [\Ref{GOLOMB-RICE}].
|
||||
|
||||
В реализации модуль $M$ равен степени двойки $M=2^m$. Для каждой дельты вычисляются
|
||||
\[
|
||||
q_i=\left\lfloor\frac{\delta_i}{M}\right\rfloor,
|
||||
\qquad
|
||||
r_i=\delta_i\bmod M.
|
||||
\]
|
||||
Частное $q_i$ записывается унарно как $q_i$ нулей и завершающая единица, после которой следуют $m$ младших бит остатка $r_i$. Длина кода одного значения равна
|
||||
\[
|
||||
\ell_i=q_i+1+m.
|
||||
\]
|
||||
Параметр выбирается приближённо как
|
||||
\[
|
||||
m=b-\lfloor\log_2 n\rfloor-1
|
||||
\]
|
||||
и ограничивается диапазоном формата $7\leq m\leq31$. При принятой модели суммарная длина битового потока оценивается как
|
||||
\[
|
||||
B=\sum_{i=1}^{n}\ell_i
|
||||
=O\!\left(n\left(1+\log_2\frac{2^b}{n}\right)\right).
|
||||
\]
|
||||
|
||||
\subsection{Base62-представление}
|
||||
|
||||
Битовый поток нельзя непосредственно поместить в поле версии RPM: необходима строка из допустимых символов. Исходная реализация использует алфавит \texttt{0--9}, \texttt{a--z}, \texttt{A--Z}. Значения от 0 до 60 записываются обычным символом, а \texttt{Z} служит escape-символом и позволяет представить также шестибитные значения 61, 62 и 63. Их различают два старших бита следующего символа: \texttt{00}, \texttt{01} или \texttt{10}. Комбинация \texttt{11} не используется, поэтому escape-последовательности не могут образовать неоднозначную цепочку. Вследствие этого один символ несёт от пяти до шести бит, и длина текстовой части приближённо пропорциональна $B/6$.
|
||||
|
||||
Рассмотрим небольшой пример с $b=10$. Для пяти имён Jenkins OAAT после усечения даёт значения, приведённые в табл.~\Ref{ENCODING_EXAMPLE}.
|
||||
|
||||
\begin{table}[H]
|
||||
\begin{center}
|
||||
\caption{\label{ENCODING_EXAMPLE}Пример хеширования символов при $b=10$}
|
||||
\small
|
||||
\begin{tabular}{|l|r|r|}
|
||||
\hline
|
||||
Символ & 32-битный хеш & $h_{10}$ \\
|
||||
\hline
|
||||
\texttt{fclose} & \texttt{0x6743def6} & 758 \\
|
||||
\hline
|
||||
\texttt{fopen} & \texttt{0x0e984918} & 280 \\
|
||||
\hline
|
||||
\texttt{free} & \texttt{0xa5bbbac7} & 711 \\
|
||||
\hline
|
||||
\texttt{malloc} & \texttt{0x07c1b8ff} & 255 \\
|
||||
\hline
|
||||
\texttt{printf} & \texttt{0xfd1ad5cc} & 460 \\
|
||||
\hline
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
\end{table}
|
||||
|
||||
После сортировки получается массив $(255,280,460,711,758)$, а после вычисления разностей --- $(255,25,180,251,47)$. Для $n=5$ формула даёт $m=7$; полученный 43-битный поток преобразуется в payload \texttt{ZvpACXZy}. Параметрам $b=10$ и $m=7$ соответствуют заголовочные символы \texttt{d} и \texttt{a}, поэтому итоговая строка равна \texttt{set:daZvpACXZy}. Пример показывает, что строка содержит достаточно данных для восстановления упорядоченного множества усечённых хешей, но не исходных имён символов.
|
||||
|
||||
\References
|
||||
\begin{enumerate}
|
||||
@@ -116,4 +197,8 @@ ALT RPM source code, 2010--2012.
|
||||
|
||||
\item
|
||||
\Label{JENKINS}
|
||||
|
||||
\item
|
||||
\Label{GOLOMB-RICE}
|
||||
|
||||
\end{enumerate}
|
||||
|
||||
Reference in New Issue
Block a user