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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
/*
*******************************************************************************
\file qr.h
\brief Quotient rings
\project bee2 [cryptographic library]
\created 2013.08.09
\version 2015.09.01
\copyright The Bee2 authors
\license Licensed under the Apache License, Version 2.0 (see LICENSE.txt).
*******************************************************************************
*/
/*!
*******************************************************************************
\file qr.h
\brief Кольца вычетов
*******************************************************************************
*/
#ifndef __BEE2_QR_H
#define __BEE2_QR_H
#include "bee2/defs.h"
#include "bee2/core/obj.h"
#ifdef __cplusplus
extern "C" {
#endif
/*!
*******************************************************************************
\file qr.h
Пусть R -- кольцо, I -- его идеал. Кольцом вычетов называется кольцо R / I,
в котором сложение и умножение элементов выполняется по модулю I:
(a + I) + (b + I) = (a + b) + I,
(a + I) * (b + I) = (a * b) + I.
В интересующих нас случаях кольцо R является коммутативным, а идеал I --
главным, т.е. порожденным единственным элементом mod \in R:
I = (mod) = {mod * a: a \in R}.
В этих случаях приведение по модулю I состоит в редукции (определении вычета)
по модулю mod.
Кольцо вычетов описывается структурой типа qr_o.
Структура qr_o проектировалась с прицелом на поддержку следующих колец:
- R = Z, mod = n --- произвольное натуральное
[кольцо вычетов целых чисел ZZ_n];
- R = Z, mod = p -- простое число
[простое поле GF(p)];
- R = GF(2)[x], mod = f(x) --- неприводимый многочлен степени e
[поле GF(2^e)].
В этих кольцах может применяться умножение Монтгомери, умножение в нормальном
базисе и другие ускоренные мультипликативные операции. Особенные операции
требуют особенного описания кольца и особенного представления его элементов.
В связи с этим вводится структура qr_o, которая задает:
- описание кольца вычетов;
- описание элементов кольца;
- интерфейсы арифметических операций в кольце.
Идеал I описывается модулем mod. Для ускорения редукции по модулю mod
могут использоваться параметры params. Параметры params могут рассчитываться
по mod при создании кольца, могут дублировать mod, или заменять его.
Параметры params имеют самостоятельное значение и могут использоваться
не только для редукции.
Элемент кольца представляется массивом из n машинных слов. Размерность n
определяется при построении кольца и сохраняется в его описании.
Нулевому элементу всегда соответствует нулевой массив.
Мультипликативные единицы могут отличаться. Мультипликативная единица
unity инициализируется при построении кольца.
Размерность модуля mod жестко не регламентируется. Эта размерность
определяется в функциях работы с элементами кольца по params и (или) n.
В кольцах чисел mod задается n словами. Если mod = 2^{B_PER_W * (n - 1)},
то последнее слово mod равняется 1, а последние слова элементов поля
всегда равняются 0. В кольцах многочленов mod задается n или n + 1 словом
(в зависимости от выполнения равенства deg(mod) == B_PER_W * n).
Элементы кольца экспортируются в строки октетов и импортируются
из этих строк. Длина строки no определяется при построении кольца и сохраняется
в его описании. Для экспорта / импорта элементов кольца используются
функции типов qr_to_i, qr_from_i. Способ определения длины строки указывается
при описании колец конкретных типов. Нулевому элементу обязательно
соответствует нулевая строка.
Аддитивные операции в кольце, как правило, не меняются при различных его
описаниях. Тем не менее, в структуру qr_o включены функции интерфейсов
qr_add_i, qr_sub_i и qr_neg_i, которые определяют аддитивные операции.
Мультипликативные операции в кольце задаются интерфейсами qr_mul_i и
qr_sqr_i.
Некоторые элементы кольца допускают мультипликативное обращение и,
следовательно, определенные пары элементов можно делить друг на друга.
Обращение и деление поддерживается интерфейсами qr_inv_i, qr_div_i.
Описание кольца организовано как объект, и можно применять функции,
описанные в заголовочном файле obj.h.
Кольцо должно создаваться специальной функцией qrCreate(), которая является
аналогом конструктора. В эту функцию должен передаваться указатель r
на структуру типа qr_o. По этому указателю будет размещаться описание
(состояние) кольца. По адресу r может быть зарезервировано больше памяти,
чем sizeof(qr_o). Дело в том, что значения mod, unity, params могут размещаться
в поле descr открытого размера. Функция qrCreate() должна сопровождаться
функцией qrCreate_keep(), которая поддерживает расчет длины состояния
(в октетах).
Функция qrCreate_keep() должна оценивать длину состояния сверху.
Оценка может быть неточной. Точная длина состояния фиксируется при
непосредственном выполнении qrCreate() и сохраняется в поле keep описания
кольца.
В функцию qrCreate() должен передаваться указатель на память для стека.
Функция qrCreate() должна сопровождаться функцией qrCreate_deep(), которая
выполняет расчет глубины стека. При расчете глубины следует предполагать,
что в qrCreate() явно или неявно вызываются все функции кольца. Получив
результат работы qrCreate_deep(), внешние программы могут определить,
сколько вспомогательной памяти потребуется при всевозможных способах
работы с кольцом.
В описании qrCreate() должны быть даны оценки сверху для размерностей n и no.
Эти оценки могут использоваться высокоуровневыми функциями при подготовке
памяти для размещения элементов кольца.
Оценка глубины стека, определяемая функцией qrCreate_deep(), может быть
неточной. Точная глубина фиксируется при непосредственном выполнении qrCreate()
и сохраняется в поле deep описания кольца.
\pre Все указатели действительны.
\pre Буферы элементов кольца или их кодовых представлений не пересекаются
с буферами, поддерживающими описание кольца.
\warning В интерфейсах мультипликативных функций не предполагается, что буфер
результата либо не пересекается, либо совпадает с буферами входных элементов.
\safe todo
*******************************************************************************
*/
struct qr_o;
/*! \brief Импорт элемента кольца вычетов
По кодовому представлению [r->no]a строится элемент [r->n]b
кольца вычетов r.
\pre Описание кольца r работоспособно.
\pre Буферы a и b либо не пересекаются, либо указатели a и b совпадают.
\expect Описание кольца r корректно.
\return TRUE, если кодовое представление корректно и импорт успешно
выполнен, и FALSE в противном случае.
*/
typedef bool_t (*qr_from_i)(
word b[], /*!< [out] элемент кольца */
const octet a[], /*!< [in] кодовое представление элемента кольца */
const struct qr_o* r, /*!< [in] описание кольца */
void* stack /*!< [in] вспомогательная память */
);
/*! \brief Экспорт элемента кольца вычетов
Строится кодовое представление [r->no]b элемента [r->n]a кольца вычетов r.
\pre Описание кольца r работоспособно.
\pre Буферы a и b либо не пересекаются, либо указатели a и b совпадают.
\expect Описание кольца r корректно.
*/
typedef void (*qr_to_i)(
octet b[], /*!< [out] кодовое представление элемента кольца */
const word a[], /*!< [in] элемент кольца */
const struct qr_o* r, /*!< [in] описание кольца */
void* stack /*!< [in] вспомогательная память */
);
/*! \brief Сложение в кольце вычетов
Определяется сумма [r->n]c элементов [r->n]a и [r->n]b кольца вычетов r:
\code
c <- a + b.
\endcode
\pre Описание кольца r работоспособно.
\pre Буфер c либо не пересекается, либо совпадает с каждым из буферов a, b.
\pre Элементы a и b принадлежат r.
\expect Описание кольца r корректно.
*/
typedef void (*qr_add_i)(
word c[], /*!< [out] сумма */
const word a[], /*!< [in] первое слагаемое */
const word b[], /*!< [in] второе слагаемое */
const struct qr_o* r /*!< [in] описание кольца */
);
/*! \brief Вычитание в кольце вычетов
Определяется разность [r->n]c элементов [r->n]a и [r->n]b кольца вычетов r:
\code
c <- a - b.
\endcode
\pre Описание кольца r работоспособно.
\pre Буфер c либо не пересекается, либо совпадает с каждым из буферов a, b.
\pre Элементы a и b принадлежат r.
\expect Описание кольца r корректно.
*/
typedef void (*qr_sub_i)(
word c[], /*!< [out] разность */
const word a[], /*!< [in] уменьшаемое */
const word b[], /*!< [in] вычитаемое */
const struct qr_o* r /*!< [in] описание кольца */
);
/*! \brief Аддитивное обращение в кольце вычетов
Определяется элемент [r->n]b кольца r, аддитивно обратный к [r->n]a:
\code
b <- -a.
\endcode
\pre Описание кольца r работоспособно.
\pre Буфер b либо не пересекается, либо совпадает с буфером a.
\pre Элемент a принадлежит r.
\expect Описание кольца r корректно.
*/
typedef void (*qr_neg_i)(
word b[], /*!< [out] обратный элемент */
const word a[], /*!< [in] обращаемый элемент */
const struct qr_o* r /*!< [in] описание кольца */
);
/*! \brief Умножение в кольце вычетов
Определяется произведение [r->n]c элементов [r->n]a и [r->n]b
кольца вычетов r:
\code
с <- a * b.
\endcode
\pre Описание кольца r работоспособно.
\pre Элементы a и b принадлежат r.
\expect Описание кольца r корректно.
*/
typedef void (*qr_mul_i)(
word c[], /*!< [out] произведение */
const word a[], /*!< [in] первый множитель */
const word b[], /*!< [in] второй множитель */
const struct qr_o* r, /*!< [in] описание кольца */
void* stack /*!< [in] вспомогательная память */
);
/*! \brief Возведение в квадрат в кольце вычетов
Определяется квадрат [r->n]b элемента [r->n]a кольца r:
\code
с <- a * a.
\endcode
\pre Описание кольца r работоспособно.
\pre Элемент a принадлежит r.
\expect Описание кольца r корректно.
*/
typedef void (*qr_sqr_i)(
word b[], /*!< [out] квадрат */
const word a[], /*!< [in] множитель */
const struct qr_o* r, /*!< [in] описание кольца */
void* stack /*!< [in] вспомогательная память */
);
/*! \brief Мультипликативное обращение в кольце вычетов
Определяется элемент [r->n]b кольца r, мультипликативно обратный
к элементу [r->n]a:
\code
b <- a^{-1}.
\endcode
\pre Описание кольца r работоспособно.
\pre Элемент a принадлежит r.
\expect Описание кольца r корректно.
\expect Элемент a обратим. Если a не обратим, то b может быть любым.
*/
typedef void (*qr_inv_i)(
word b[], /*!< [out] обратный элемент */
const word a[], /*!< [in] обращаемый элемент */
const struct qr_o* r, /*!< [in] описание кольца */
void* stack /*!< [in] вспомогательная память */
);
/*! \brief Деление в кольце вычетов
Определяется частное [r->n]b от деления элемента [r->n]divident
на элемент [r->n]a в кольце вычетов r:
\code
b <- divident * a^{-1}.
\endcode
\pre Описание кольца r работоспособно.
\pre Элементы divident и a принадлежат r.
\expect Описание кольца r корректно.
\expect Элемент a обратим. Если a не обратим, то b может быть любым.
*/
typedef void (*qr_div_i)(
word b[], /*!< [out] частное */
const word divident[], /*!< [in] делимое */
const word a[], /*!< [in] делитель */
const struct qr_o* r, /*!< [in] описание кольца */
void* stack /*!< [in] вспомогательная память */
);
/*! \brief Описание кольца вычетов
Описывается кольцо вычетов, правила представления его элементов и функции,
реализующие операции в кольце.
\remark В таблицу указателей описания кольца как объекта входят поля
mod, unity, params.
*/
typedef struct qr_o
{
obj_hdr_t hdr; /*!< заголовок */
// ptr_table {
word* mod; /*!< модуль */
word* unity; /*!< мультипликативная единица */
void* params; /*!< дополнительные параметры */
// }
size_t n; /*!< размерность */
size_t no; /*!< длина кодового представления */
qr_from_i from; /*!< функция импорта */
qr_to_i to; /*!< функция экспорта */
qr_add_i add; /*!< функция сложения */
qr_sub_i sub; /*!< функция вычитания */
qr_neg_i neg; /*!< функция аддитивного обращения */
qr_mul_i mul; /*!< функция умножения */
qr_sqr_i sqr; /*!< функция возведения в квадрат */
qr_inv_i inv; /*!< функция мультипликативного обращения */
qr_div_i div; /*!< функция деления */
size_t deep; /*!< максимальная глубина стека функций */
octet descr[]; /*!< память для размещения данных */
} qr_o;
/*
*******************************************************************************
Псевдонимы
*******************************************************************************
*/
#define qrIsZero(a, r)\
wwIsZero(a, (r)->n)
#define qrSetZero(a, r)\
wwSetZero(a, (r)->n)
#define qrIsUnity(a, r)\
wwEq(a, (r)->unity, (r)->n)
#define qrSetUnity(a, r)\
wwCopy(a, (r)->unity, (r)->n)
#define qrCopy(b, a, r)\
wwCopy(b, a, (r)->n)
#define qrCmp(b, a, r)\
wwCmp(b, a, (r)->n)
#define qrFrom(b, a, r, stack)\
(r)->from(b, a, r, stack)
#define qrTo(b, a, r, stack)\
(r)->to(b, a, r, stack)
#define qrAdd(c, a, b, r)\
(r)->add(c, a, b, r)
#define qrAddUnity(b, a, r)\
(r)->add(b, a, (r)->unity, r)
#define qrSub(c, a, b, r)\
(r)->sub(c, a, b, r)
#define qrSubUnity(a, r)\
(r)->sub(a, a, (r)->unity, r)
#define qrNeg(b, a, r)\
(r)->neg(b, a, r)
#define qrMul(c, a, b, r, stack)\
(r)->mul(c, a, b, r, stack)
#define qrSqr(b, a, r, stack)\
(r)->sqr(b, a, r, stack)
#define qrInv(b, a, r, stack)\
(r)->inv(b, a, r, stack)
#define qrDiv(b, divident, a, r, stack)\
(r)->div(b, divident, a, r, stack)
/*
*******************************************************************************
Управление описанием кольца
*******************************************************************************
*/
/*! \brief Описание кольца вычетов работоспособно?
Проверяется работоспособность описания r кольца вычетов. Проверяются
следующие условия:
- объект r работоспособен;
- objKeep(r) >= sizeof(qr_o);
- objPCount(r) == 3 && objOCount(r) == 0;
- указатель r->unity корректен;
- r->n > 0 && r->no > 0;
- указатели r->from, r->to, ..., r->div корректны.
\return Признак работоспособности.
*/
bool_t qrIsOperable(
const qr_o* r /*!< [in] описание кольца */
);
/*
*******************************************************************************
Макрооперации в кольце
*******************************************************************************
*/
/*! \brief Возведение в степень в кольце вычетов
В кольце вычетов r определяется элемент [r->n]c, который является [m]b-ой
степенью элемента [r->n]a:
\code
c <- a^b.
\endcode
\pre Описание кольца r работоспособно.
\pre Элемент a принадлежит r.
\expect Описание кольца r корректно.
\remark При b == 0 возвращается r->unity.
\deep{stack} qrPower_deep(r->n, m, r->deep).
*/
void qrPower(
word c[], /*!< [out] степень */
const word a[], /*!< [in] основание */
const word b[], /*!< [in] показатель */
size_t m, /*!< [in] длина b в машинных словах */
const qr_o* r, /*!< [in] описание кольца */
void* stack /*!< [in] вспомогательная память */
);
size_t qrPower_deep(size_t n, size_t m, size_t r_deep);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* __BEE2_QR_H */