migration
2
semester-4/ОС/lb-2/README.md
Normal file
@ -0,0 +1,2 @@
|
||||
Викладач: Мельникова Р. В.
|
||||
Оцінка: 96
|
BIN
semester-4/ОС/lb-2/img/crypt.png
Normal file
After Width: | Height: | Size: 98 KiB |
BIN
semester-4/ОС/lb-2/img/dll_build.png
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
semester-4/ОС/lb-2/img/gen_pair.png
Normal file
After Width: | Height: | Size: 96 KiB |
BIN
semester-4/ОС/lb-2/img/header.png
Normal file
After Width: | Height: | Size: 311 KiB |
BIN
semester-4/ОС/lb-2/img/just.png
Normal file
After Width: | Height: | Size: 30 KiB |
BIN
semester-4/ОС/lb-2/img/main.png
Normal file
After Width: | Height: | Size: 786 KiB |
BIN
semester-4/ОС/lb-2/img/math.png
Normal file
After Width: | Height: | Size: 385 KiB |
692
semester-4/ОС/lb-2/lib.typ
Normal file
@ -0,0 +1,692 @@
|
||||
|
||||
// Academic aliases {{{1
|
||||
|
||||
/// subject abbreviations to full names
|
||||
#let subjects = (
|
||||
"БД": "Бази даних",
|
||||
"ОПНJ": "Основи програмування на Java",
|
||||
"ОС": "Операційні системи",
|
||||
"ПП": "Проектний практикум",
|
||||
"СПМ": "Скриптові мови програмування",
|
||||
"Ф": "Філософія",
|
||||
)
|
||||
|
||||
/// education program abbreviations to name & number
|
||||
#let edu_programs = (
|
||||
"ПЗПІ": (
|
||||
name: "Інженерія програмного забезпечення",
|
||||
number: 121, // TODO: ПЗПІ is "F2" now
|
||||
),
|
||||
)
|
||||
|
||||
// Template formatting functions {{{1
|
||||
|
||||
/// numberless heading
|
||||
#let nheading(title) = heading(depth: 1, numbering: none, title)
|
||||
|
||||
/// fill horizontal space with a box and not an empty space
|
||||
#let hfill(width) = box(width: width, repeat(" ")) // NOTE: This is a HAIR SPACE (U+200A), not a regular space
|
||||
|
||||
/// make underlined cell with filled value
|
||||
#let uline(align: center, content) = underline[
|
||||
#if align != left { hfill(1fr) }
|
||||
#content
|
||||
#if align != right { hfill(1fr) }
|
||||
]
|
||||
|
||||
/// bold text
|
||||
#let bold(content) = text(weight: "bold")[#content]
|
||||
|
||||
/// month name from its number
|
||||
#let month_gen(month) = (
|
||||
"січня",
|
||||
"лютого",
|
||||
"березня",
|
||||
"квітня",
|
||||
"травня",
|
||||
"червня",
|
||||
"липня",
|
||||
"серпня",
|
||||
"вересня",
|
||||
"жовтня",
|
||||
"листопада",
|
||||
"грудня",
|
||||
).at(month - 1)
|
||||
|
||||
// Helper functions {{{1
|
||||
|
||||
/// captioned image with label derived from path:
|
||||
/// - "image.png" = @image
|
||||
/// - "img/image.png" = @image
|
||||
/// - "img/foo/image.png" = @foo_image
|
||||
/// - "img/foo/foo_image.png" = @foo_image
|
||||
/// the caption will be modified based on a conditional positional value:
|
||||
/// - `none`: no change
|
||||
/// - some value: "`caption` (за даними `value`)"
|
||||
/// - no value: "`caption` (рисунок виконано самостійно)"
|
||||
/// additional named arguments will be passed to original `image` function
|
||||
#let img(path, caption, ..sink) = {
|
||||
let parts = path.split(".").first().split("/")
|
||||
|
||||
let label_string = if parts.len() <= 2 or parts.at(-1).starts-with(parts.at(-2)) {
|
||||
// ("image",), (_, "image") and (.., "img", "img_image")
|
||||
parts.last()
|
||||
} else {
|
||||
// (.., "img", "image") = "img_image"
|
||||
parts.at(-2) + "_" + parts.at(-1)
|
||||
}.replace(" ", "_")
|
||||
|
||||
let caption = if sink.pos().len() == 0 {
|
||||
caption + " (рисунок виконано самостійно)"
|
||||
} else if sink.pos().first() == none {
|
||||
caption
|
||||
} else {
|
||||
[#caption (за даними #sink.pos().first())]
|
||||
}
|
||||
|
||||
[#figure(image(path, ..sink.named()), caption: caption) #label(label_string)]
|
||||
}
|
||||
|
||||
// Styling {{{1
|
||||
/// NOTE: may be wrong
|
||||
#let ua_alpha_numbering = "абвгдежиклмнпрстуфхцшщюя".split("") // 0 = "", 1 = "а"
|
||||
|
||||
// general outlook {{{2
|
||||
// spacing between lines
|
||||
#let spacing = 0.95em
|
||||
|
||||
#let style(it) = {
|
||||
set page(
|
||||
paper: "a4",
|
||||
margin: (top: 20mm, right: 10mm, bottom: 20mm, left: 25mm),
|
||||
number-align: top + right,
|
||||
numbering: (..numbers) => {
|
||||
if numbers.pos().at(0) != 1 {
|
||||
numbering("1", numbers.pos().at(0))
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
set text(font: ("Times New Roman", "Liberation Serif"), size: 14pt, hyphenate: false, lang: "uk")
|
||||
set par(justify: true, first-line-indent: (amount: 1.25cm, all: true))
|
||||
set underline(evade: false)
|
||||
|
||||
// set 1.5 line spacing
|
||||
set block(spacing: spacing)
|
||||
set par(spacing: spacing)
|
||||
set par(leading: spacing)
|
||||
|
||||
// enums and lists {{{2
|
||||
set enum(numbering: i => { ua_alpha_numbering.at(i) + ")" }, indent: 1.25cm, body-indent: 0.5cm)
|
||||
show enum: it => {
|
||||
set enum(indent: 0em, numbering: "1)")
|
||||
it
|
||||
}
|
||||
|
||||
set list(indent: 1.35cm, body-indent: 0.5cm, marker: [--])
|
||||
|
||||
// figures {{{2
|
||||
show figure: it => {
|
||||
v(spacing * 2, weak: true)
|
||||
it
|
||||
v(spacing * 2, weak: true)
|
||||
}
|
||||
|
||||
set figure.caption(separator: [ -- ])
|
||||
show figure.where(kind: table): set figure.caption(position: top)
|
||||
show figure.caption.where(kind: table): set align(left)
|
||||
|
||||
// figure numbering
|
||||
show heading.where(level: 1): it => {
|
||||
counter(math.equation).update(0)
|
||||
counter(figure.where(kind: image)).update(0)
|
||||
counter(figure.where(kind: table)).update(0)
|
||||
counter(figure.where(kind: raw)).update(0)
|
||||
it
|
||||
}
|
||||
set math.equation(numbering: (..num) => numbering("(1.1)", counter(heading).get().at(0), num.pos().first()))
|
||||
set figure(numbering: (..num) => numbering("1.1", counter(heading).get().at(0), num.pos().first()))
|
||||
|
||||
// appearance of references to images and tables {{{2
|
||||
set ref(
|
||||
supplement: it => {
|
||||
if it == none or not it.has("kind") {
|
||||
it
|
||||
} else if it.kind == image {
|
||||
"див. рис."
|
||||
} else if it.kind == table {
|
||||
"див. таблицю"
|
||||
} else {
|
||||
it
|
||||
}
|
||||
},
|
||||
)
|
||||
show ref: it => {
|
||||
let el = it.element
|
||||
|
||||
if el == none or not el.has("kind") {
|
||||
return it
|
||||
}
|
||||
if el.kind != image and el.kind != table {
|
||||
return it
|
||||
}
|
||||
|
||||
[(#it)]
|
||||
}
|
||||
|
||||
// headings {{{2
|
||||
set heading(numbering: "1.1")
|
||||
|
||||
show heading.where(level: 1): it => {
|
||||
set align(center)
|
||||
set text(size: 14pt, weight: "semibold")
|
||||
|
||||
pagebreak(weak: true)
|
||||
upper(it)
|
||||
v(spacing * 2, weak: true)
|
||||
}
|
||||
show heading.where(level: 2): it => {
|
||||
set text(size: 14pt, weight: "regular")
|
||||
|
||||
v(spacing * 2, weak: true)
|
||||
block(width: 100%, spacing: 0em)[
|
||||
#h(1.25cm)
|
||||
#counter(heading).display(it.numbering)
|
||||
#it.body
|
||||
]
|
||||
v(spacing * 2, weak: true)
|
||||
}
|
||||
|
||||
show heading.where(level: 3): it => {
|
||||
set text(size: 14pt, weight: "regular")
|
||||
|
||||
v(spacing * 2, weak: true)
|
||||
block(width: 100%, spacing: 0em)[
|
||||
#h(1.25cm)
|
||||
#counter(heading).display(it.numbering)
|
||||
#it.body
|
||||
]
|
||||
v(spacing * 2, weak: true)
|
||||
}
|
||||
|
||||
it
|
||||
}
|
||||
|
||||
// Coursework template {{{1
|
||||
|
||||
/// DSTU 3008:2015 Template for NURE
|
||||
/// -> content
|
||||
/// - doc (content): Content to apply the template to.
|
||||
/// - title (str): Title of the document.
|
||||
/// - subject_shorthand (str): Subject short name.
|
||||
/// - department_gen (str): Department name in genitive form.
|
||||
/// - authors ((name: str, full_name_gen: str, variant: int, group: str, gender: str),): List of Authors dicts.
|
||||
/// - mentors ((name: str, gender: str, degree: str),): List of mentors dicts.
|
||||
/// - edu_program_shorthand (str): Education program shorthand.
|
||||
/// - task_list (done_date: datetime, initial_date: datetime, source: (content | str), content: (content | str), graphics: (content | str)): Task list object.
|
||||
/// - calendar_plan ( plan_table: (content | str), approval_date: datetime): Calendar plan object.
|
||||
/// - abstract (keywords: (str, ), text: (content | str)): Abstract object.
|
||||
/// - bib_path path: Path to the bibliography yaml file.
|
||||
/// - appendices (content): Content with appendices.
|
||||
#let cw-template(
|
||||
doc,
|
||||
title: "NONE",
|
||||
subject_shorthand: "NONE",
|
||||
department_gen: "Програмної інженерії",
|
||||
author: (),
|
||||
mentors: (),
|
||||
edu_program_shorthand: "ПЗПІ",
|
||||
task_list: (),
|
||||
calendar_plan: (),
|
||||
abstract: (),
|
||||
bib_path: "bibl.yml",
|
||||
appendices: (),
|
||||
) = {
|
||||
set document(title: title, author: author.name)
|
||||
|
||||
show: style
|
||||
|
||||
let bib-count = state("citation-counter", ())
|
||||
show cite: it => {
|
||||
it
|
||||
bib-count.update(((..c)) => (..c, it.key))
|
||||
}
|
||||
show bibliography: it => {
|
||||
set text(size: 0pt)
|
||||
it
|
||||
}
|
||||
|
||||
|
||||
let head_mentor = mentors.at(0)
|
||||
let edu_program = edu_programs.at(edu_program_shorthand)
|
||||
|
||||
// page 1 {{{2
|
||||
[
|
||||
#set align(center)
|
||||
МІНІСТЕРСТВО ОСВІТИ І НАУКИ УКРАЇНИ
|
||||
|
||||
ХАРКІВСЬКИЙ НАЦІОНАЛЬНИЙ УНІВЕРСИТЕТ РАДІОЕЛЕКТРОНІКИ
|
||||
|
||||
\
|
||||
|
||||
Кафедра Програмної інженерії
|
||||
|
||||
\
|
||||
|
||||
ПОЯСНЮВАЛЬНА ЗАПИСКА
|
||||
|
||||
ДО КУРСОВОЇ РОБОТИ
|
||||
|
||||
з дисципліни: "#subjects.at(subject_shorthand, default: "NONE")"
|
||||
|
||||
Тема роботи: "#title"
|
||||
|
||||
\ \ \
|
||||
|
||||
#columns(2, gutter: 4cm)[
|
||||
#set align(left)
|
||||
|
||||
#if author.gender == "m" { [Виконав\ ] } else { [Виконала\ ] } ст. гр. #author.group
|
||||
|
||||
\
|
||||
Керівник:\
|
||||
#head_mentor.degree
|
||||
|
||||
\
|
||||
Робота захищена на оцінку
|
||||
|
||||
\
|
||||
Комісія:\
|
||||
#for mentor in mentors {
|
||||
[#mentor.degree\
|
||||
]
|
||||
}
|
||||
|
||||
#colbreak()
|
||||
#set align(left)
|
||||
|
||||
\
|
||||
#author.name
|
||||
|
||||
\ \
|
||||
#head_mentor.name
|
||||
|
||||
\
|
||||
#underline(" " * 35)
|
||||
|
||||
\ \
|
||||
#for mentor in mentors {
|
||||
[#mentor.name\
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
#v(1fr)
|
||||
|
||||
Харків -- #task_list.done_date.display("[year]")
|
||||
|
||||
#pagebreak()
|
||||
]
|
||||
|
||||
// page 2 {{{2
|
||||
{
|
||||
uline[Харківський національний університет радіоелектроніки]
|
||||
|
||||
linebreak()
|
||||
linebreak()
|
||||
|
||||
grid(
|
||||
columns: (100pt, 1fr),
|
||||
bold[
|
||||
Кафедра
|
||||
Дисципліна
|
||||
Спеціальність
|
||||
],
|
||||
{
|
||||
uline(align: left, department_gen)
|
||||
linebreak()
|
||||
uline(align: left, subjects.at(subject_shorthand))
|
||||
linebreak()
|
||||
uline(align: left, [#edu_program.number #edu_program.name])
|
||||
},
|
||||
)
|
||||
grid(
|
||||
columns: (1fr, 1fr, 1fr),
|
||||
gutter: 0.3fr,
|
||||
[#bold[Курс] #uline(2)], [#bold[Група] #uline(author.group)], [#bold[Семестр] #uline(3)],
|
||||
)
|
||||
|
||||
linebreak()
|
||||
linebreak()
|
||||
linebreak()
|
||||
|
||||
align(center, bold[ЗАВДАННЯ \ на курсову роботу студента])
|
||||
|
||||
linebreak()
|
||||
|
||||
uline(align: left)[_#author.full_name_gen _]
|
||||
|
||||
linebreak()
|
||||
linebreak()
|
||||
|
||||
bold[\1. Тема роботи:]
|
||||
uline[#title.]
|
||||
|
||||
linebreak()
|
||||
|
||||
{
|
||||
bold[\2. Строк здачі закінченої роботи:]
|
||||
uline(task_list.done_date.display("[day].[month].[year]"))
|
||||
hfill(10fr)
|
||||
}
|
||||
|
||||
linebreak()
|
||||
|
||||
bold[\3. Вихідні дані для роботи:]
|
||||
uline(task_list.source)
|
||||
|
||||
linebreak()
|
||||
|
||||
bold[\4. Зміст розрахунково-пояснювальної записки:]
|
||||
uline(task_list.content)
|
||||
|
||||
linebreak()
|
||||
|
||||
bold[\5. Перелік графічного матеріалу:]
|
||||
uline(task_list.graphics)
|
||||
|
||||
linebreak()
|
||||
|
||||
{
|
||||
bold[\6. Дата видачі завдання:]
|
||||
uline(task_list.initial_date.display("[day].[month].[year]"))
|
||||
hfill(10fr)
|
||||
}
|
||||
|
||||
pagebreak()
|
||||
}
|
||||
|
||||
// page 3 {{{2
|
||||
{
|
||||
align(center, bold[КАЛЕНДАРНИЙ ПЛАН])
|
||||
set par(first-line-indent: 0pt)
|
||||
|
||||
linebreak()
|
||||
|
||||
calendar_plan.plan_table
|
||||
|
||||
linebreak()
|
||||
|
||||
grid(
|
||||
columns: (5fr, 5fr),
|
||||
grid(
|
||||
columns: (1fr, 2fr, 1fr),
|
||||
gutter: 0.2fr,
|
||||
[
|
||||
Студент \
|
||||
Керівник \
|
||||
#align(center)["#underline[#calendar_plan.approval_date.day()]"]
|
||||
],
|
||||
[
|
||||
#uline(align: center, []) \
|
||||
#uline(align: center, []) \
|
||||
#uline(align: center, month_gen(calendar_plan.approval_date.month()))
|
||||
],
|
||||
[
|
||||
\ \
|
||||
#underline[#calendar_plan.approval_date.year()] р.
|
||||
],
|
||||
),
|
||||
[
|
||||
#author.name, \
|
||||
#head_mentor.degree
|
||||
#head_mentor.name.
|
||||
],
|
||||
)
|
||||
|
||||
pagebreak()
|
||||
}
|
||||
|
||||
// page 4 {{{2
|
||||
[
|
||||
#align(center, bold[РЕФЕРАТ]) \
|
||||
|
||||
#context [
|
||||
#let pages = counter(page).final().at(0)
|
||||
#let images = query(figure.where(kind: image)).len()
|
||||
#let tables = query(figure.where(kind: table)).len()
|
||||
#let bibs = bib-count.final().dedup().len()
|
||||
/* TODO: why this stopped working?
|
||||
#let tables = counter(figure.where(kind: table)).final().at(0)
|
||||
#let images = counter(figure.where(kind: image)).final().at(0)*/
|
||||
|
||||
#let counters = ()
|
||||
|
||||
#if pages != 0 { counters.push[#pages с.] }
|
||||
#if tables != 0 { counters.push[#tables табл.] }
|
||||
#if images != 0 { counters.push[#images рис.] }
|
||||
#if bibs != 0 { counters.push[#bibs джерел] }
|
||||
|
||||
Пояснювальна записка до курсової роботи: #counters.join(", ").
|
||||
]
|
||||
|
||||
\
|
||||
|
||||
#{
|
||||
let keywords = abstract.keywords.map(upper)
|
||||
let is_cyrillic = word => word.split("").any(char => ("А" <= char and char <= "я"))
|
||||
|
||||
let n = keywords.len()
|
||||
for i in range(n) {
|
||||
for j in range(0, n - i - 1) {
|
||||
if (
|
||||
(not is_cyrillic(keywords.at(j)) and is_cyrillic(keywords.at(j + 1)))
|
||||
or (
|
||||
is_cyrillic(keywords.at(j)) == is_cyrillic(keywords.at(j + 1)) and keywords.at(j) > keywords.at(j + 1)
|
||||
)
|
||||
) {
|
||||
(keywords.at(j), keywords.at(j + 1)) = (keywords.at(j + 1), keywords.at(j))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
keywords.join(", ")
|
||||
}
|
||||
|
||||
\
|
||||
|
||||
#abstract.text
|
||||
]
|
||||
|
||||
// page 5 {{{2
|
||||
outline(
|
||||
title: [
|
||||
ЗМІСТ
|
||||
#v(spacing * 2, weak: true)
|
||||
],
|
||||
depth: 2,
|
||||
indent: auto,
|
||||
)
|
||||
|
||||
doc
|
||||
|
||||
// bibliography {{{2
|
||||
{
|
||||
heading(depth: 1, numbering: none)[Перелік джерел посилання]
|
||||
|
||||
bibliography(
|
||||
bib_path,
|
||||
style: "ieee",
|
||||
full: true,
|
||||
title: none,
|
||||
)
|
||||
|
||||
let bib_data = yaml(bib_path)
|
||||
|
||||
let format-entry(citation) = {
|
||||
if (citation.type == "Web") {
|
||||
let date_array = citation.url.date.split("-")
|
||||
let date = datetime(
|
||||
year: int(date_array.at(0)),
|
||||
month: int(date_array.at(1)),
|
||||
day: int(date_array.at(2)),
|
||||
)
|
||||
[
|
||||
#citation.title.
|
||||
#citation.author.
|
||||
URL: #citation.url.value (дата звернення: #date.display("[day].[month].[year]")).
|
||||
]
|
||||
} else if citation.type == "Book" [
|
||||
#citation.author
|
||||
#citation.title.
|
||||
#citation.publisher,
|
||||
#citation.date.
|
||||
#citation.page-total c.
|
||||
] else [
|
||||
UNSUPPORTED BIBLIOGRAPHY ENTRY TYPE, PLEASE OPEN AN ISSUE
|
||||
]
|
||||
}
|
||||
|
||||
show enum.item: it => {
|
||||
set par(first-line-indent: 0pt)
|
||||
box(width: 1.25cm)
|
||||
box(width: 1em + 0.5cm)[#it.number.]
|
||||
it.body
|
||||
linebreak()
|
||||
}
|
||||
|
||||
context {
|
||||
for (i, citation) in query(ref.where(element: none)).map(r => str(r.target)).dedup().enumerate() {
|
||||
enum.item(
|
||||
i + 1,
|
||||
format-entry(bib_data.at(citation)),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// appendices {{{2
|
||||
{
|
||||
counter(heading).update(0)
|
||||
|
||||
set heading(
|
||||
numbering: (i, ..nums) => {
|
||||
let char = upper(ua_alpha_numbering.at(i))
|
||||
if nums.pos().len() == 0 { char } else {
|
||||
char + "." + nums.pos().map(str).join(".")
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
show heading.where(level: 1): it => {
|
||||
set align(center)
|
||||
set text(size: 14pt, weight: "regular")
|
||||
|
||||
pagebreak(weak: true)
|
||||
bold[ДОДАТОК #counter(heading).display(it.numbering)]
|
||||
linebreak()
|
||||
it.body
|
||||
v(spacing * 2, weak: true)
|
||||
}
|
||||
|
||||
show heading.where(level: 2): it => {
|
||||
set text(size: 14pt, weight: "regular")
|
||||
|
||||
v(spacing * 2, weak: true)
|
||||
block(width: 100%, spacing: 0em)[
|
||||
#h(1.25cm)
|
||||
#counter(heading).display(it.numbering)
|
||||
#it.body
|
||||
]
|
||||
v(spacing * 2, weak: true)
|
||||
}
|
||||
|
||||
appendices
|
||||
}
|
||||
}
|
||||
|
||||
// Laboratory work template {{{1
|
||||
|
||||
/// DSTU 3008:2015 Template for NURE
|
||||
/// -> content
|
||||
/// - doc (content): Content to apply the template to.
|
||||
/// - doctype ("ЛБ" | "ПЗ"): Document type.
|
||||
/// - title (str): Title of the document.
|
||||
/// - subject_shorthand (str): Subject short name.
|
||||
/// - department_gen (str): Department name in genitive form.
|
||||
/// - worknumber (int): Number of the work, can be omitted.
|
||||
/// - authors ((name: str, full_name_gen: str, variant: int, group: str, gender: str),): List of Authors dicts.
|
||||
/// - mentor (name: str, gender: str, degree: str): Mentors objects.
|
||||
#let lab-pz-template(
|
||||
doc,
|
||||
doctype: "NONE",
|
||||
title: "NONE",
|
||||
subject_shorthand: "NONE",
|
||||
department_gen: "Програмної інженерії",
|
||||
worknumber: 1,
|
||||
authors: (),
|
||||
mentor: (),
|
||||
) = {
|
||||
set document(title: title, author: authors.at(0).name)
|
||||
|
||||
show: style
|
||||
|
||||
context counter(heading).update(worknumber - 1)
|
||||
|
||||
// page 1 {{{2
|
||||
align(center)[
|
||||
МІНІСТЕРСТВО ОСВІТИ І НАУКИ УКРАЇНИ \
|
||||
ХАРКІВСЬКИЙ НАЦІОНАЛЬНИЙ УНІВЕРСИТЕТ РАДІОЕЛЕКТРОНІКИ
|
||||
|
||||
\ \
|
||||
Кафедра #department_gen
|
||||
|
||||
\ \ \
|
||||
Звіт \
|
||||
з
|
||||
#if doctype == "ЛБ" [лабораторної роботи] else [практичної роботи]
|
||||
#if worknumber != none [№ #worknumber]
|
||||
|
||||
з дисципліни: "#subjects.at(subject_shorthand, default: "UNLNOWN SUBJECT, PLEASE OPEN AN ISSUE")"
|
||||
|
||||
з теми: "#title"
|
||||
|
||||
\ \ \ \
|
||||
|
||||
#columns(2)[
|
||||
#set align(left)
|
||||
#set par(first-line-indent: 0pt)
|
||||
#if authors.len() == 1 {
|
||||
let author = authors.at(0)
|
||||
if author.gender == "m" [Виконав:\ ] else [Виконала:\ ]
|
||||
[
|
||||
ст. гр. #author.group\
|
||||
#author.name\
|
||||
]
|
||||
if author.variant != none [Варіант: №#author.variant]
|
||||
} else [
|
||||
Виконали:\
|
||||
ст. гр. #authors.at(0).group\
|
||||
#authors.map(a => [ #a.name\ ])
|
||||
]
|
||||
|
||||
#colbreak()
|
||||
#set align(right)
|
||||
|
||||
#if mentor.gender == "m" { [Перевірив:\ ] } else { [Перевірила:\ ] }
|
||||
#mentor.degree #if mentor.degree.len() >= 15 [\ ]
|
||||
#mentor.name\
|
||||
]
|
||||
|
||||
#v(1fr)
|
||||
|
||||
Харків -- #datetime.today().display("[year]")
|
||||
]
|
||||
|
||||
pagebreak(weak: true)
|
||||
|
||||
heading(title)
|
||||
doc
|
||||
}
|
||||
|
||||
// vim:sts=2:sw=2:fdl=0:fdm=marker:cms=/*%s*/
|
24
semester-4/ОС/lb-2/src/.clangd
Normal file
@ -0,0 +1,24 @@
|
||||
# CompileFlags:
|
||||
# Add:
|
||||
# - -I/usr/x86_64-w64-mingw32/include
|
||||
# - -I/usr/x86_64-w64-mingw32/include/w32api
|
||||
# - -DUNICODE
|
||||
# - -D_UNICODE
|
||||
|
||||
CompileFlags:
|
||||
Add: [-Wall, -Wextra, -std=c++17, -DBUILD_SHARED, --target=x86_64-w64-mingw32]
|
||||
CompilationDatabase: build/
|
||||
|
||||
Diagnostics:
|
||||
UnusedIncludes: Strict
|
||||
|
||||
InlayHints:
|
||||
Enabled: Yes
|
||||
ParameterNames: Yes
|
||||
DeducedTypes: Yes
|
||||
|
||||
Index:
|
||||
Background: Build
|
||||
|
||||
Hover:
|
||||
ShowAKA: Yes
|
28
semester-4/ОС/lb-2/src/Justfile
Normal file
@ -0,0 +1,28 @@
|
||||
cc := "x86_64-w64-mingw32-clang++"
|
||||
flags := "-Wall -Wextra -std=c++17"
|
||||
|
||||
@clean:
|
||||
rm -rf build
|
||||
|
||||
@makedir-build: clean
|
||||
mkdir -p build
|
||||
|
||||
@build-lib-shared: makedir-build
|
||||
{{cc}} {{flags}} -D BUILD_SHARED --shared -Wl,--out-implib,build/rsa.lib library/rsa.cpp -o build/rsa.dll
|
||||
|
||||
@build-app-shared: build-lib-shared
|
||||
{{cc}} {{flags}} application/main.cpp -L build -l rsa -o build/main.exe
|
||||
|
||||
@build-lib-static: makedir-build
|
||||
{{cc}} {{flags}} -c -D BUILD_SHARED library/rsa.cpp -o build/rsa.o
|
||||
ar rcs build/rsa.lib build/rsa.o
|
||||
|
||||
@build-app-static: build-lib-static
|
||||
{{cc}} {{flags}} -D BUILD_STATIC application/main.cpp -L build -l rsa -o build/main.exe
|
||||
|
||||
@run:
|
||||
wine cmd /c build/main.exe
|
||||
|
||||
run-shared: build-app-shared run
|
||||
|
||||
run-static: build-app-static run
|
74
semester-4/ОС/lb-2/src/application/main.cpp
Normal file
@ -0,0 +1,74 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "../library/rsa.h"
|
||||
|
||||
char *int128_to_str(__int128_t n) {
|
||||
static char str[41] = {0};
|
||||
char *s = str + sizeof(str) - 1;
|
||||
bool neg = n < 0;
|
||||
if (neg)
|
||||
n = -n;
|
||||
do {
|
||||
*--s = "0123456789"[n % 10];
|
||||
n /= 10;
|
||||
} while (n);
|
||||
if (neg)
|
||||
*--s = '-';
|
||||
return s;
|
||||
}
|
||||
|
||||
int main() {
|
||||
// uint64_t p0 = 8589934609, q0 = 2147483693, e0 = 65537;
|
||||
// uint64_t p1 = 2147483659, q1 = 8589934621, e1 = 65537;
|
||||
|
||||
uint32_t p0 = 2147483659, q0 = 2147483693, e0 = 65537; // pair_0
|
||||
uint32_t p1 = 2147483659, q1 = 2147483693, e1 = 65537; // pair_1
|
||||
|
||||
rsa_Pair pair_0 = rsa_gen_pair(p0, q0, e0);
|
||||
rsa_Pair pair_1 = rsa_gen_pair(p1, q1, e1);
|
||||
|
||||
printf("pair_0:\n");
|
||||
printf("- e:\t%s\n", int128_to_str(pair_0.e));
|
||||
printf("- d:\t%s\n", int128_to_str(pair_0.d));
|
||||
printf("- n:\t%s\n", int128_to_str(pair_0.n));
|
||||
|
||||
printf("pair_1:\n");
|
||||
printf("- e:\t%s\n", int128_to_str(pair_1.e));
|
||||
printf("- d:\t%s\n", int128_to_str(pair_1.d));
|
||||
printf("- n:\t%s\n", int128_to_str(pair_1.n));
|
||||
|
||||
uint64_t t[] = {4096, 17, 8, 65500, 0x9fffffff};
|
||||
|
||||
for (size_t i = 0; i < 5; i++) {
|
||||
printf("- - - - - - - - - - - - - - - - - -\n");
|
||||
|
||||
printf("t[%zu]:\t\t%lld\n", i, t[i]);
|
||||
|
||||
__int128_t e1t = rsa_encrypt(t[i], pair_0.e, pair_0.n);
|
||||
printf("e1t:\t\t%s\n", int128_to_str(e1t));
|
||||
|
||||
__int128_t d1e1t = rsa_decrypt(e1t, pair_0.d, pair_0.n);
|
||||
printf("d1e1t\t\t%s\n", int128_to_str(d1e1t));
|
||||
|
||||
if (d1e1t != t[i]) {
|
||||
fprintf(stderr, "Error: decrypt[i]on failed - expected: %llu; got: %s\n",
|
||||
t[i], int128_to_str(d1e1t));
|
||||
return 1;
|
||||
}
|
||||
|
||||
__int128_t e0d1e1t = rsa_encrypt(t[i], pair_1.e, pair_1.n);
|
||||
printf("e0d1e1t:\t%s\n", int128_to_str(e0d1e1t));
|
||||
|
||||
__int128_t d0e0d1e1t = rsa_decrypt(e0d1e1t, pair_1.d, pair_1.n);
|
||||
printf("d0e0d1e1t:\t%s\n", int128_to_str(d0e0d1e1t));
|
||||
|
||||
if (d0e0d1e1t != t[i]) {
|
||||
fprintf(stderr, "Error: decrypt[i]on failed - expected: %llu; got: %s\n",
|
||||
t[i], int128_to_str(d0e0d1e1t));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
78
semester-4/ОС/lb-2/src/library/rsa.cpp
Normal file
@ -0,0 +1,78 @@
|
||||
#include "rsa.h"
|
||||
|
||||
__int128_t mul_mod(__int128_t a, __int128_t b, __int128_t mod) {
|
||||
__int128_t res = 0;
|
||||
a %= mod;
|
||||
|
||||
while (b > 0) {
|
||||
if (b & 1)
|
||||
res = (res + a) % mod;
|
||||
|
||||
a = (a << 1) % mod;
|
||||
b >>= 1;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
__int128_t pow_mod(__int128_t base, __int128_t exp, __int128_t mod) {
|
||||
__int128_t res = 1;
|
||||
base %= mod;
|
||||
|
||||
while (exp > 0) {
|
||||
if (exp & 1)
|
||||
res = mul_mod(res, base, mod);
|
||||
|
||||
base = mul_mod(base, base, mod);
|
||||
exp >>= 1;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
__int128_t mod_inverse(__int128_t e, __int128_t phi) {
|
||||
__int128_t a = e, b = phi;
|
||||
__int128_t x = 1, y = 0;
|
||||
__int128_t x1 = 0, y1 = 1;
|
||||
__int128_t q, temp;
|
||||
|
||||
while (b != 0) {
|
||||
q = a / b;
|
||||
|
||||
temp = a % b;
|
||||
a = b;
|
||||
b = temp;
|
||||
|
||||
temp = x - q * x1;
|
||||
x = x1;
|
||||
x1 = temp;
|
||||
|
||||
temp = y - q * y1;
|
||||
y = y1;
|
||||
y1 = temp;
|
||||
}
|
||||
|
||||
if (x < 0)
|
||||
x += phi;
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
rsa_Pair rsa_gen_pair(__int128_t p, __int128_t q, __int128_t e) {
|
||||
rsa_Pair pair;
|
||||
pair.e = e;
|
||||
pair.n = p * q;
|
||||
|
||||
__int128_t phi = (p - 1) * (q - 1);
|
||||
pair.d = mod_inverse(e, phi);
|
||||
|
||||
return pair;
|
||||
}
|
||||
|
||||
__int128_t rsa_encrypt(__int128_t data, __int128_t e, __int128_t n) {
|
||||
return pow_mod(data, e, n);
|
||||
}
|
||||
|
||||
__int128_t rsa_decrypt(__int128_t data, __int128_t d, __int128_t n) {
|
||||
return pow_mod(data, d, n);
|
||||
}
|
35
semester-4/ОС/lb-2/src/library/rsa.h
Normal file
@ -0,0 +1,35 @@
|
||||
#ifndef RSA_LIB
|
||||
#define RSA_LIB
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifdef BUILD_SHARED
|
||||
#define BUILD_SPEC __declspec(dllexport)
|
||||
#elif BUILD_STATIC
|
||||
#define BUILD_SPEC
|
||||
#else
|
||||
#define BUILD_SPEC __declspec(dllimport)
|
||||
#endif
|
||||
#else
|
||||
#define BUILD_SPEC
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
__int128_t d;
|
||||
__int128_t e;
|
||||
__int128_t n;
|
||||
} rsa_Pair;
|
||||
|
||||
BUILD_SPEC rsa_Pair rsa_gen_pair(__int128_t p, __int128_t q, __int128_t e);
|
||||
|
||||
BUILD_SPEC __int128_t rsa_encrypt(__int128_t data, __int128_t e, __int128_t n);
|
||||
BUILD_SPEC __int128_t rsa_decrypt(__int128_t data, __int128_t d, __int128_t n);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
378
semester-4/ОС/lb-2/Лр_2_Ситник_ПЗПІ_23_2.typ
Normal file
@ -0,0 +1,378 @@
|
||||
#import "@local/nure:0.0.0": *
|
||||
|
||||
#show: lab-pz-template.with(
|
||||
doctype: "ЛБ",
|
||||
title: "Створення та використання бібліотек. Частина 1",
|
||||
subject_shorthand: "ОС",
|
||||
department_gen: "Програмної інженерії",
|
||||
authors: (
|
||||
(
|
||||
name: "Ситник Є. С.",
|
||||
full_name_gen: "Ситника Єгора Сергійовича",
|
||||
group: "ПЗПІ-23-2",
|
||||
gender: "m",
|
||||
variant: none,
|
||||
),
|
||||
),
|
||||
mentor: (
|
||||
name: "Мельнікова Р. В.",
|
||||
gender: "f",
|
||||
degree: "доц. каф. ПІ",
|
||||
),
|
||||
worknumber: 2,
|
||||
)
|
||||
|
||||
#v(-spacing)
|
||||
|
||||
== Мета роботи
|
||||
Вивчити прийоми та методи створення та використання динамічних бібліотек.
|
||||
|
||||
== Хід роботи
|
||||
#v(-spacing)
|
||||
=== Визначите необхідні функції для реалізації алгоритму RSA. Визначите серед цих функцій ті, які повинні використовуватись в зовнішніх програмах
|
||||
|
||||
RSA -- це криптографічний алгоритм, який використовує пару ключів: відкритий і закритий. Відкритий ключ використовується для шифрування повідомлень, а закритий -- для їх розшифрування.
|
||||
|
||||
Для реалізації алгоритму RSA знадобиться мінімум 3 функції:
|
||||
+ функція генерації ключів;
|
||||
+ функція шифрування даних;
|
||||
+ функція розшифрування даних.
|
||||
|
||||
Також для зручності має сенс створити структуру, що буде зберігати пару ключів.
|
||||
|
||||
Ці функції та структура будуть доступні користувачу бібліотеки для зовнішнього використання.
|
||||
|
||||
=== Складіть файл заголовків таким чином, щоб цей файл заголовків можна було б використовувати для динамічної бібліотеки та програм, які використовують бібліотеку
|
||||
|
||||
Для операційної системи Windows створення динамічних бібліотек вимагає визначення певних розширених атрибутів класів зберігання (extended storage-class attributes), а саме -- "dllimport" та "dllexport".
|
||||
|
||||
Для універсальності бібліотеки необхідно створити макрос, який буде автоматично встановлювати потрібні атрибути в залежності від режиму компіляції.
|
||||
|
||||
Можна виділити такі особливі випадки компіляції:
|
||||
+ компіляція статичної бібліотеки для операційної системи Windows;
|
||||
+ компіляція динамічної бібліотеки для операційної системи Windows;
|
||||
+ компіляція бібліотеки для інших операційних систем;
|
||||
+ компіляція бібліотеки для використання із C;
|
||||
+ компіляція бібліотеки для використання із C++.
|
||||
|
||||
Для визначення режиму компіляції використаємо макроси, які повинен вказати користувач, та стандартні макроси та вирази, що надає компілятор.
|
||||
|
||||
Також не варто забувати про можливість підключення користувачем файлу заголовків в кількох місцях. Існує кілька способів запобігання подібним ситуаціям, найкращим для цієї бібліотеки буде використання макросу, який запобігатиме повторному включенню файлу заголовків, адже цей спосіб не залежить від компілятора, що використовується.
|
||||
|
||||
Всі файли, що стосуються бібліотеки (файл заголовків "rsa.h" та файл реалізації "rsa.cpp") знаходитимуться в директорії "library".
|
||||
|
||||
#figure(image("img/header.png", width: 80%), caption: [Файл заголовків "rsa.h"])
|
||||
|
||||
Для запобігання повторному включенню файлу заголовків використано конструкцію із макросом "RSA_LIB". Файл буде включено тільки перший раз, всі наступні рази препроцесор не включить вміст файлу, через визначений макрос.
|
||||
|
||||
Для можливості використання бібліотеки як із C, так і з C++ використано конструкцію "extern C", що включається у файл тільки за умови визначення макросу "\_\_cplusplus", що додається компілятором під час компіляції в режимі C++.
|
||||
|
||||
Для сумісності бібліотеки із різними операційними системами використано конструкцію із макросом "\_WIN32", що визначає необхідні атрибути лише під час компіляції для цільової платформи Windows.
|
||||
|
||||
Для визначення атрибутів під час статичної та динамічної компіляції використано конструкцію із макросами "BUILD_SHARED" та "BUILD_STATIC".
|
||||
|
||||
В залежності від результату виконання вище вказаних конструкцій буде визначено макрос "BUILD_SPEC", який використовується під час оголошення функцій для додавання необхідних атрибутів.
|
||||
|
||||
Для всіх функцій в якості типу аргументів та результату було використано тип "\_\_int128_t", що є найбільшим із стандартних типів на момент написання. Варто зазначити, що для шифрування RSA зазвичай використовують значно більші типи, реалізовані в спеціалізованих бібліотеках, таких як "OpenSSL BN" або "GNU Multiple Precision Arithmetic Library".
|
||||
|
||||
Оскільки C, на відміну від C++, не має вбудованої можливості ізолювати функції та змінні в просторах імен, кожна функція та структура починаються із назви бібліотеки, а саме -- "rsa".
|
||||
|
||||
=== Реалізуйте функції бібліотек
|
||||
|
||||
Перш за все необхідно реалізувати функцію створення пари ключів на основі переданих користувачем простих чисел та відкритої експоненти @gen_pair.
|
||||
|
||||
#figure(image("img/gen_pair.png", width: 100%), caption: [Функція "rsa\_gen\_pair"]) <gen_pair>
|
||||
|
||||
Далі реалізуємо функції шифрування та розшифрування @crypt.
|
||||
|
||||
#figure(image("img/crypt.png", width: 100%), caption: [Функції "rsa\_encrypt" та "rsa\_decrypt"]) <crypt>
|
||||
|
||||
Оскільки стандартна бібліотека С не включає необхідні математичні функції їх також необхідно реалізувати @math. Ці функції розраховані на внутрішнє використання, тому їх нема в файлі заголовків.
|
||||
|
||||
#figure(
|
||||
image("img/math.png", width: 80%),
|
||||
caption: [Математичні функції "mul\_mod", "pow\_mod" та "mod\_inverse"],
|
||||
) <math>
|
||||
|
||||
=== Створіть динамічну бібліотеку
|
||||
|
||||
Оскільки я використовую операційну систему Arch Linux, у мене нема доступу до компілятора Microsoft MSVC. Натомість мною було використано компілятор Clang із проєкту LLVM, та набір інструментів MinGW, що забезпечують кросс-компіляцію для Windows на POSIX-сумісних операційних системах (Linux, MacOS, BSD і подібних).
|
||||
|
||||
Під час компіляції динамічної бібліотеки необхідно:
|
||||
+ визначити макрос "BUILD_SHARED";
|
||||
+ вказати прапорець "shared" для компілятора;
|
||||
+ встановити значення, що відповідає назві бібліотеки, для прапорця "out-implib" для компонувальника.
|
||||
|
||||
Компілятор автоматично викликає компонувальник, передати аргументи для нього можна за допомогою прапорця "Wl".
|
||||
|
||||
Динамічні бібліотеки для Windows складаються з 2 компонентів:
|
||||
+ файл із розширенням ".dll" в якому знаходиться реалізація бібліотеки;
|
||||
+ файл із розширенням ".lib" в якому знаходиться інформація, необхідна для зв'язування програми та бібліотеки.
|
||||
|
||||
Для зручнішого управління проєктом має сенс використовувати систему збірки, та визначати всі команди компіляції за її допомогою. Я використаю систему збірки "Just" @just. Всі скомпільовані файли будуть знаходитись в директорії "build".
|
||||
|
||||
#figure(
|
||||
image("img/just.png", width: 100%),
|
||||
caption: [Вміст "Justfile" з інструкціями для збірки],
|
||||
) <just>
|
||||
|
||||
Скомпілюємо бібліотеку та перевіримо результат @dll_build.
|
||||
#figure(
|
||||
image("img/dll_build.png", width: 100%),
|
||||
caption: [Результат збірки динамічної бібліотеки],
|
||||
) <dll_build>
|
||||
|
||||
|
||||
Можемо побачити, що компіляція пройшла без помилок та попереджень, та після компіляції, як і очікувалося, ми отримали 2 файли бібліотеки.
|
||||
|
||||
=== Реалізуйте головну програму для динамічної бібліотеки для першого способу її використання
|
||||
|
||||
Відповідно умові реалізуємо програму із використанням функцій бібліотеки. Для доступу до них необхідно підключити файл заголовків бібліотеки.
|
||||
|
||||
Оберемо пари простих чисел та відкриті експоненти для створення 2 пар ключів, створимо пари, почергово перевіримо роботу функцій шифрування та дешифрування із 2 парами ключів на різних даних друкуючу в консоль результат кожного етапу.
|
||||
|
||||
Оскільки бібліотека розрахована на роботу із даними типу "\_\_int128_t", а стандартні функції друку в консоль не підтримують цей тип, додатково реалізуємо функцію для перетворення чисел такого типу на строки.
|
||||
|
||||
Всі файли, що стосуються програми (файл реалізації "main.cpp") знаходитимуться в директорії "application".
|
||||
|
||||
#figure(
|
||||
image("img/main.png", width: 70%),
|
||||
caption: [Вміст файлу "main.cpp"],
|
||||
) <main>
|
||||
|
||||
== Висновки
|
||||
Під час виконання даної лабораторної роботи я вивчив прийоми та методи створення та використання динамічних бібліотек.
|
||||
|
||||
#counter(heading).update(0)
|
||||
|
||||
#set heading(
|
||||
numbering: (i, ..nums) => {
|
||||
let char = upper(ua_alpha_numbering.at(i))
|
||||
if nums.pos().len() == 0 { char } else {
|
||||
char + "." + nums.pos().map(str).join(".")
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
#show heading.where(level: 1): it => {
|
||||
set align(center)
|
||||
set text(size: 14pt, weight: "regular")
|
||||
|
||||
pagebreak(weak: true)
|
||||
bold[ДОДАТОК #counter(heading).display(it.numbering)]
|
||||
linebreak()
|
||||
it.body
|
||||
v(spacing * 2, weak: true)
|
||||
}
|
||||
|
||||
= Вміст файлу "rsa.h"
|
||||
```
|
||||
#ifndef RSA_LIB
|
||||
#define RSA_LIB
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifdef BUILD_SHARED
|
||||
#define BUILD_SPEC __declspec(dllexport)
|
||||
#elif BUILD_STATIC
|
||||
#define BUILD_SPEC
|
||||
#else
|
||||
#define BUILD_SPEC __declspec(dllimport)
|
||||
#endif
|
||||
#else
|
||||
#define BUILD_SPEC
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
__int128_t d;
|
||||
__int128_t e;
|
||||
__int128_t n;
|
||||
} rsa_Pair;
|
||||
|
||||
BUILD_SPEC rsa_Pair rsa_gen_pair(__int128_t p, __int128_t q, __int128_t e);
|
||||
|
||||
BUILD_SPEC __int128_t rsa_encrypt(__int128_t data, __int128_t e, __int128_t n);
|
||||
BUILD_SPEC __int128_t rsa_decrypt(__int128_t data, __int128_t d, __int128_t n);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
```
|
||||
= Вміст файлу "rsa.cpp"
|
||||
```
|
||||
#include "rsa.h"
|
||||
|
||||
__int128_t mul_mod(__int128_t a, __int128_t b, __int128_t mod) {
|
||||
__int128_t res = 0;
|
||||
a %= mod;
|
||||
|
||||
while (b > 0) {
|
||||
if (b & 1)
|
||||
res = (res + a) % mod;
|
||||
|
||||
a = (a << 1) % mod;
|
||||
b >>= 1;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
__int128_t pow_mod(__int128_t base, __int128_t exp, __int128_t mod) {
|
||||
__int128_t res = 1;
|
||||
base %= mod;
|
||||
|
||||
while (exp > 0) {
|
||||
if (exp & 1)
|
||||
res = mul_mod(res, base, mod);
|
||||
|
||||
base = mul_mod(base, base, mod);
|
||||
exp >>= 1;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
__int128_t mod_inverse(__int128_t e, __int128_t phi) {
|
||||
__int128_t a = e, b = phi;
|
||||
__int128_t x = 1, y = 0;
|
||||
__int128_t x1 = 0, y1 = 1;
|
||||
__int128_t q, temp;
|
||||
|
||||
while (b != 0) {
|
||||
q = a / b;
|
||||
|
||||
temp = a % b;
|
||||
a = b;
|
||||
b = temp;
|
||||
|
||||
temp = x - q * x1;
|
||||
x = x1;
|
||||
x1 = temp;
|
||||
|
||||
temp = y - q * y1;
|
||||
y = y1;
|
||||
y1 = temp;
|
||||
}
|
||||
|
||||
if (x < 0)
|
||||
x += phi;
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
rsa_Pair rsa_gen_pair(__int128_t p, __int128_t q, __int128_t e) {
|
||||
rsa_Pair pair;
|
||||
pair.e = e;
|
||||
pair.n = p * q;
|
||||
|
||||
__int128_t phi = (p - 1) * (q - 1);
|
||||
pair.d = mod_inverse(e, phi);
|
||||
|
||||
return pair;
|
||||
}
|
||||
|
||||
__int128_t rsa_encrypt(__int128_t data, __int128_t e, __int128_t n) {
|
||||
return pow_mod(data, e, n);
|
||||
}
|
||||
|
||||
__int128_t rsa_decrypt(__int128_t data, __int128_t d, __int128_t n) {
|
||||
return pow_mod(data, d, n);
|
||||
}
|
||||
```
|
||||
= Вміст файлу "main.cpp"
|
||||
```
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "../library/rsa.h"
|
||||
|
||||
char *int128_to_str(__int128_t n) {
|
||||
static char str[41] = {0};
|
||||
char *s = str + sizeof(str) - 1;
|
||||
bool neg = n < 0;
|
||||
if (neg)
|
||||
n = -n;
|
||||
do {
|
||||
*--s = "0123456789"[n % 10];
|
||||
n /= 10;
|
||||
} while (n);
|
||||
if (neg)
|
||||
*--s = '-';
|
||||
return s;
|
||||
}
|
||||
|
||||
int main() {
|
||||
uint64_t p0 = 8589934609, q0 = 2147483693, e0 = 65537;
|
||||
uint64_t p1 = 2147483659, q1 = 8589934621, e1 = 65537;
|
||||
|
||||
rsa_Pair pair_0 = rsa_gen_pair(p0, q0, e0);
|
||||
rsa_Pair pair_1 = rsa_gen_pair(p1, q1, e1);
|
||||
|
||||
printf("pair_0:\n");
|
||||
printf("- e:\t%s\n", int128_to_str(pair_0.e));
|
||||
printf("- d:\t%s\n", int128_to_str(pair_0.d));
|
||||
printf("- n:\t%s\n", int128_to_str(pair_0.n));
|
||||
|
||||
printf("pair_1:\n");
|
||||
printf("- e:\t%s\n", int128_to_str(pair_1.e));
|
||||
printf("- d:\t%s\n", int128_to_str(pair_1.d));
|
||||
printf("- n:\t%s\n", int128_to_str(pair_1.n));
|
||||
|
||||
uint64_t t[] = {22, 17, 2, 65500, 100};
|
||||
|
||||
for (size_t i = 0; i < 5; i++) {
|
||||
printf("- - - - - - - - - - - - - - - - - -\n");
|
||||
|
||||
printf("t[%zu]:\t\t%lld\n", i, t[i]);
|
||||
|
||||
__int128_t e1t = rsa_encrypt(t[i], pair_0.e, pair_0.n);
|
||||
printf("e1t:\t\t%s\n", int128_to_str(e1t));
|
||||
|
||||
__int128_t d1e1t = rsa_decrypt(e1t, pair_0.d, pair_0.n);
|
||||
printf("d1e1t:\t\t%s\n", int128_to_str(d1e1t));
|
||||
|
||||
if (d1e1t != t[i]) {
|
||||
fprintf(stderr, "Error: decrypt[i]on failed - expected: %llu; got: %s\n",
|
||||
t[i], int128_to_str(d1e1t));
|
||||
return 1;
|
||||
}
|
||||
|
||||
__int128_t e0d1e1t = rsa_encrypt(t[i], pair_1.e, pair_1.n);
|
||||
printf("e0d1e1t:\t%s\n", int128_to_str(e0d1e1t));
|
||||
|
||||
__int128_t d0e0d1e1t = rsa_decrypt(e0d1e1t, pair_1.d, pair_1.n);
|
||||
printf("d0e0d1e1t:\t%s\n", int128_to_str(d0e0d1e1t));
|
||||
|
||||
if (d0e0d1e1t != t[i]) {
|
||||
fprintf(stderr, "Error: decrypt[i]on failed - expected: %llu; got: %s\n",
|
||||
t[i], int128_to_str(d0e0d1e1t));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
= Вміст файлу "Justfile"
|
||||
```
|
||||
cc := "x86_64-w64-mingw32-clang++"
|
||||
flags := "-Wall -Wextra -std=c++17"
|
||||
|
||||
@clean:
|
||||
rm -rf build
|
||||
|
||||
@makedir-build: clean
|
||||
mkdir -p build
|
||||
|
||||
@build-lib-shared: makedir-build
|
||||
{{cc}} {{flags}} -D BUILD_SHARED --shared -Wl,--out-implib,build/rsa.lib library/rsa.cpp -o build/rsa.dll
|
||||
|
||||
@build-app-shared: build-lib-shared
|
||||
{{cc}} {{flags}} application/main.cpp -L build -l rsa -o build/main.exe
|
||||
```
|