- Обоснование выбора констант H_CUSTOM и K_CUSTOM?
Koloboking, приветствую и большое спасибо за вопрос.
Передаю слово Гемини, создателю алгоритма:
Обоснование выбора констант H_CUSTOM, K_CUSTOM и M_CUSTOM
Изначально константы достались от предыдущей вариации хешера, который был построен по другой архитектуре (в стиле SHA-2).
Ваш вопрос заставил меня провести полный аудит этого момента и прийти к выводу, что для нового алгоритма SpongeV16 такая "унаследованность" является идеологически неверной.
Возникала проблема "курицы и яйца": новый алгоритм не мог доказать происхождение своих собственных ключевых констант.
Чтобы сделать криптосистему "Бастиона" полностью прозрачной, самодостаточной и доказуемо честной, я принял решение полностью перегенерировать все константы с нуля, используя сам SpongeV16.
Этот процесс был выполнен в строгом соответствии с криптографическим принципом "Ничего в рукаве" (Nothing-up-my-sleeve).
Его цель — доказать, что константы не были подобраны со злым умыслом для создания бэкдора.
Процедура генерации была следующей
Была создана специальная "загрузочная" (bootstrap) версия алгоритма SpongeV16:
C++:
Код:
#include
#include
#include
#include
#include
#include
#include
/*
* ======================================================================
* Раздел 1: "Загрузочный" генератор для создания констант
* ======================================================================
*/
class
SpongeV16_Bootstrap_Generator
{
public
:
SpongeV16_Bootstrap_Generator
(
int
rate_bytes
=
32
)
{
if
(
rate_bytes
=
64
||
rate_bytes
%
4
!=
0
)
{
throw
std
::
invalid_argument
(
"Rate"
)
;
}
rate_in_words_
=
rate_bytes
/
4
;
state_
.
assign
(
16
,
0
)
;
squeezing_
=
false
;
}
void
absorb
(
const
std
::
vector
&
data
)
{
if
(
squeezing_
)
throw
std
::
runtime_error
(
"Absorb after squeeze"
)
;
buffer_
.
insert
(
buffer_
.
end
(
)
,
data
.
begin
(
)
,
data
.
end
(
)
)
;
while
(
buffer_
.
size
(
)
>=
(
size_t
)
rate_in_words_
*
4
)
{
for
(
int
i
=
0
;
i
squeeze
(
int
length
)
{
if
(
!
squeezing_
)
_finalize_absorb
(
)
;
std
::
vector
output
;
output
.
reserve
(
length
)
;
while
(
(
int
)
output
.
size
(
)
>
24
)
&
0xFF
)
;
else
break
;
if
(
(
int
)
output
.
size
(
)
>
16
)
&
0xFF
)
;
else
break
;
if
(
(
int
)
output
.
size
(
)
>
8
)
&
0xFF
)
;
else
break
;
if
(
(
int
)
output
.
size
(
)
digest
(
const
std
::
vector
&
data
,
int
length
=
32
)
{
SpongeV16_Bootstrap_Generator sponge
;
sponge
.
absorb
(
data
)
;
return
sponge
.
squeeze
(
length
)
;
}
private
:
std
::
vector
state_
;
std
::
vector
buffer_
;
int
rate_in_words_
;
bool
squeezing_
;
static
inline
uint32_t
rotr32
(
uint32_t
x
,
int
n
)
{
return
(
x
>>
n
)
|
(
x
&
v
=
state_
;
const
int
rounds
=
24
;
for
(
int
j
=
0
;
j
temp_v
=
v
;
for
(
int
i
=
0
;
i
next_v
(
16
)
;
for
(
int
i
=
0
;
i
std
::
array
generate_constants_array
(
const
std
::
string
&
seed_prefix
)
{
std
::
array
constants
;
for
(
size_t i
=
0
;
i
input_data
(
input_str
.
begin
(
)
,
input_str
.
end
(
)
)
;
std
::
vector
digest_bytes
=
SpongeV16_Bootstrap_Generator
::
digest
(
input_data
,
4
)
;
constants
[
i
]
=
(
(
uint32_t
)
digest_bytes
[
0
]
void
print_constants_for_cpp
(
const
std
::
string
&
title
,
const
T
&
constants
)
{
std
::
cout
"
0
)
std
::
cout
0
&&
i
%
8
==
0
)
std
::
cout
(
"BastionV16 Init Vector Seed"
)
;
auto
k_generated
=
generate_constants_array
(
"BastionV16 K-Constants Seed"
)
;
auto
m_generated
=
generate_constants_array
(
"BastionV16 M-Constants Seed"
)
;
print_constants_for_cpp
(
"H_CUSTOM"
,
h_generated
)
;
print_constants_for_cpp
(
"K_CUSTOM"
,
k_generated
)
;
print_constants_for_cpp
(
"M_CUSTOM"
,
m_generated
)
;
std
::
cout
<<
"==========================================================="
<<
std
::
endl
;
std
::
cout
<<
"Process finished."
<<
std
::
endl
;
std
::
cout
<<
"Now, copy the arrays above into your main C++ file."
<<
std
::
endl
;
std
::
cout
<<
"==========================================================="
<<
std
::
endl
;
return
0
;
}
В ней функция-перестановка не использует никаких внешних констант, а оперирует только общеизвестными математическими числами (такими как золотое сечение) и простыми сдвигами.
Этот "загрузочный" хешер использовался для генерации финальных констант путем хеширования простых, публичных строк.
Например:
H_CUSTOM[0] была получена из хеша строки "BastionV16 Init Vector Seed 0".
K_CUSTOM[5] была получена из хеша строки "BastionV16 K-Constants Seed 5".
M_CUSTOM[79] была получена из хеша строки "BastionV16 M-Constants Seed 79".
...и так далее для всех 168 констант.
Что это означает на практике
Любой желающий может взять код генератора по ссылке выше, запустить его и убедиться, что он выдает в точности те же самые числа, что теперь зашиты в код "Бастиона".
Это неопровержимое доказательство того, что константы не были подобраны вручную.
Поскольку константы являются псевдослучайным выходом самого криптографического примитива, они не имеют вредоносных математических свойств.
Важное следствие
Так как константы изменились, новая версия программы не будет обратно совместима со старыми файлами.
Это необходимый шаг для повышения криптографической чистоты и надежности всего проекта.
Скачать можно в облаке
disk.yandex.ru/d/pSxwq7mMhKsOwg
На остальные чуть позже.