paint-brush
Шыфраванне: шыфры, дайджэсты, соль і IV - што вам трэба ведацьпа@gliimlang
Новая гісторыя

Шыфраванне: шыфры, дайджэсты, соль і IV - што вам трэба ведаць

па Gliimly14m2025/01/04
Read on Terminal Reader

Занадта доўга; Чытаць

Шыфраванне - гэта метад ператварэння даных у непрыдатную форму, якую можна зрабіць карыснай толькі з дапамогай дэшыфравання. Тут вы даведаецеся, як шыфраваць і дэшыфраваць дадзеныя з дапамогай пароля.
featured image - Шыфраванне: шыфры, дайджэсты, соль і IV - што вам трэба ведаць
Gliimly HackerNoon profile picture

Што такое шыфраванне?

Шыфраванне - гэта метад ператварэння даных у непрыдатную форму, якую можна зрабіць карыснай толькі з дапамогай дэшыфравання. Мэта складаецца ў тым, каб зрабіць дадзеныя даступнымі толькі для тых, хто можа іх расшыфраваць (г.зн. зрабіць іх прыдатнымі для выкарыстання). Як правіла, даныя павінны быць зашыфраваны, каб пераканацца, што іх нельга атрымаць у выпадку несанкцыянаванага доступу. Гэта апошняя лінія абароны пасля таго, як зламысніку ўдалося прарвацца праз сістэмы аўтарызацыі і кантролю доступу.

Гэта не азначае, што ўсе дадзеныя павінны быць зашыфраваны, таму што часта можа быць дастаткова сістэм аўтарызацыі і доступу, і, акрамя таго, існуе зніжэнне прадукцыйнасці для шыфравання і дэшыфравання даных. Калі і калі дадзеныя шыфруюцца, гэта пытанне планавання прымянення і ацэнкі рызыкі, а часам гэта таксама нарматыўнае патрабаванне, напрыклад, HIPAA або GDPR.

Дадзеныя могуць быць зашыфраваны ў стане спакою, напрыклад, на дыску, або падчас перадачы, напрыклад, паміж двума бакамі, якія маюць зносіны праз Інтэрнэт.

Тут вы даведаецеся, як шыфраваць і дэшыфраваць дадзеныя з дапамогай пароля, таксама вядомага як сіметрычнае шыфраванне. Гэты пароль павінен быць вядомы абодвум бакам, якія абменьваюцца інфармацыяй.

Шыфр, дайджэст, соль, ітэрацыі, IV

Каб правільна і бяспечна выкарыстоўваць шыфраванне, трэба растлумачыць некалькі паняццяў.


Шыфр - гэта алгарытм, які выкарыстоўваецца для шыфравання. Напрыклад, AES256 - гэта шыфр. Ідэя шыфра - гэта тое, пра што большасць людзей падумае, калі справа даходзіць да шыфравання.


Дайджэст - гэта ў асноўным хэш-функцыя, якая выкарыстоўваецца для шыфравання і падаўжэння пароля (напрыклад, ключа шыфравання), перш чым ён будзе выкарыстоўвацца шыфрам. Навошта гэта робіцца? Па-першае, ён стварае добра выпадковы хэш ключа аднастайнай даўжыні, які лепш працуе для шыфравання. Вельмі добра падыходзіць і для «засолкі», пра што пойдзе гаворка далей.


«Соль» - спосаб разгрому так званых «вясёлкавых» сталоў. Зламыснік ведае, што два хэшаваныя значэнні будуць выглядаць сапраўды гэтак жа, як і арыгіналы. Аднак калі вы дадасце да хэшавання значэнне солі, яны гэтага не зробяць. Яе называюць "соль", таму што яна як бы змешваецца з ключом, каб атрымаць нешта іншае.


Цяпер вясёлкавая табліца будзе спрабаваць супаставіць вядомыя хэшаваныя значэнні з загадзя вылічанымі дадзенымі, каб адгадаць пароль.


Звычайна соль генеруецца выпадковым чынам для кожнага ключа і захоўваецца разам з ім. Для таго, каб супаставіць вядомыя хэшы, зламыснік павінен быў бы загадзя вылічыць вясёлкавыя табліцы для вялікай колькасці выпадковых значэнняў, што, як правіла, немагчыма.

Вы часта чуеце пра "ітэрацыі" ў шыфраванні. Ітэрацыя - гэта адзіны цыкл, у якім ключ і соль змешваюцца такім чынам, каб угадаць ключ было цяжэй. Гэта робіцца шмат разоў, каб зламысніку ўскладніць адгадванне ключа з пункту гледжання вылічэнняў, таму "ітэрацыі" (множны лік). Як правіла, мінімальная неабходная колькасць ітэрацый складае 1000, але яна можа адрознівацца ад гэтага. Калі вы пачынаеце з сапраўды надзейнага пароля, звычайна вам спатрэбіцца менш.

IV (ці "Вектар ініцыялізацыі") - гэта звычайна выпадковае значэнне, якое выкарыстоўваецца для шыфравання кожнага паведамлення. Цяпер соль выкарыстоўваецца для атрымання ключа на аснове пароля. IV выкарыстоўваецца, калі ў вас ужо ёсць ключ і вы шыфруеце паведамленні. Мэта IV - прымусіць адны і тыя ж паведамленні выглядаць па-рознаму ў зашыфраваным выглядзе. Часам IV таксама мае паслядоўны кампанент, таму ён складаецца з выпадковага радка плюс паслядоўнасці, якая ўвесь час павялічваецца.


Гэта ўскладняе атакі "паўтору", у якіх зламысніку не трэба расшыфроўваць паведамленне; хутчэй, зашыфраванае паведамленне было "вынюхана" (г.зн. перахоплена паміж адпраўніком і атрымальнікам), а потым прайграна ў надзеі паўтарыць ужо выкананае дзеянне. Хаця ў рэчаіснасці большасць пратаколаў высокага ўзроўню ўжо маюць паслядоўнасць, дзе кожнае паведамленне мае, як частку, павялічваючы нумар пакета, так што ў большасці выпадкаў IV гэта не патрэбна.

Перадумовы

У гэтым прыкладзе выкарыстоўваецца структура Gliimly . Спачатку ўсталюйце яго.

Прыклад шыфравання

Каб запусціць прыклады тут, стварыце прыкладанне "enc" ва ўласным каталогу (падрабязней пра менеджэр праграм Gliimly глядзіце ў mgrg ):

 mkdir enc_example cd enc_example gg -k enc

Для шыфравання дадзеных выкарыстоўвайце аператар encrypt-data . Самая простая форма - зашыфраваць радок з нулявым канчаткам. Стварыце файл "encrypt.gliim" і скапіруйце гэта:

 begin-handler /encrypt public set-string str = "This contains a secret code, which is Open Sesame!" // Encrypt encrypt-data str to enc_str password "my_password" p-out enc_str @ // Decrypt decrypt-data enc_str password "my_password" to dec_str p-out dec_str @ end-handler

Вы можаце ўбачыць асноўнае выкарыстанне encrypt-data і decrypt-data . Вы даяце дадзеныя (арыгінальныя або зашыфраваныя) і пароль, і пайшлі. Дадзеныя шыфруюцца, а потым расшыфроўваюцца, атрымліваючы арыгінал.

У зыходным кодзе радковая зменная "enc_str" (якая ствараецца як "char *") будзе ўтрымліваць зашыфраваную версію "Гэта змяшчае сакрэтны код, які з'яўляецца Open Sesame!" і "dec_str" будуць расшыфраваныя даныя, якія павінны быць сапраўды такімі ж.

Каб запусціць гэты код з каманднага радка, спачатку зрабіце прыкладанне:

 gg -q

Затым Gliimly павінен стварыць bash-код для яго запуску - шлях запыту "/encrypt", які ў нашым выпадку апрацоўваецца функцыяй "void encrypt()", вызначанай у зыходным файле "encrypt.gliim". У Gliimly гэтыя імёны заўсёды супадаюць, што дазваляе лёгка пісаць, чытаць і выконваць код. Выкарыстоўвайце параметр «-r» у gg , каб паказаць шлях запыту і атрымаць код, неабходны для запуску праграмы:

 gg -r --req="/encrypt" --silent-header --exec


Вы атрымаеце такі адказ:

 72ddd44c10e9693be6ac77caabc64e05f809290a109df7cfc57400948cb888cd23c7e98e15bcf21b25ab1337ddc6d02094232111aa20a2d548c08f230b6d56e9 This contains a secret code, which is Open Sesame!


Тут вы маеце зашыфраваныя даныя, а затым гэтыя зашыфраваныя даныя расшыфроўваюцца з выкарыстаннем таго ж пароля. Нядзіўна, што вынік супадае з радком, які вы зашыфравалі ў першую чаргу.

Звярніце ўвагу, што па змаўчанні encrypt-data будзе ствараць зашыфраванае значэнне ў шаснаццатковай форме, якую чалавек чытае, што азначае, што яно складаецца з шаснаццатковых сімвалаў ад "0" да "9" і ад "a" да "f". Такім чынам, вы можаце захоўваць зашыфраваныя даныя ў звычайнай радку. Напрыклад, ён можа перайсці ў дакумент JSON, у слупок VARCHAR у базе даных або ў любым іншым месцы. Аднак вы таксама можаце ствараць двайковыя зашыфраваныя дадзеныя. Больш падрабязна пра гэта крыху пазней.

Шыфраваць дадзеныя ў двайковы вынік

У папярэднім прыкладзе выніковыя зашыфраваныя даныя ў шаснаццатковай форме, якую можна прачытаць чалавеку. Вы таксама можаце ствараць двайковыя зашыфраваныя даныя, якія не з'яўляюцца радком для чытання чалавекам і таксама карацейшыя. Каб зрабіць гэта, выкарыстоўвайце пункт "двайковы". Заменіце код у «encrypt.gliim» на:

 begin-handler /encrypt public set-string str = "This contains a secret code, which is Open Sesame!" // Encrypt encrypt-data str to enc_str password "my_password" binary // Save the encrypted data to a file write-file "encrypted_data" from enc_str get-app directory to app_dir @Encrypted data written to file <<p-out app_dir>>/encrypted_data // Decrypt data decrypt-data enc_str password "my_password" binary to dec_str p-out dec_str @ end-handler

Калі вы жадаеце атрымаць двайковыя зашыфраваныя дадзеныя, вы таксама павінны атрымаць іх даўжыню ў байтах, інакш вы не даведаецеся, дзе яны заканчваюцца, бо яны могуць утрымліваць нулявыя байты. Для гэтага выкарыстоўвайце прапанову "output-length". У гэтым кодзе зашыфраваныя даныя ў зменнай "enc_str" запісваюцца ў файл "encrypted_data", а даўжыня запісу складае "outlen" байтаў.


Калі файл запісваецца без шляху, ён заўсёды запісваецца ў хатні каталог прыкладання (гл. каталогі ), таму вы павінны выкарыстоўваць get-app , каб атрымаць гэты каталог.

Пры расшыфроўцы дадзеных звярніце ўвагу на выкарыстанне пункта «ўваходная даўжыня». Ён паказвае, колькі байтаў маюць зашыфраваныя дадзеныя. Відавочна, што вы можаце атрымаць гэта з зменнай "outlen", дзе encrypt-data захоўвае даўжыню зашыфраваных даных. Калі шыфраванне і дэшыфраванне раз'яднаныя, г.зн. працуюць у асобных праграмах, вы пераканайцеся, што гэтая даўжыня даступная.

Заўважце таксама, што калі даныя зашыфраваны як "двайковы" (гэта азначае стварэнне двайковага вываду), дэшыфраванне павінна выкарыстоўваць тое ж самае.

Зрабіце заяўку:

 gg -q


Запусціце яго гэтак жа, як і раней:

 gg -r --req="/encrypt" --silent-header --exec


Вынік:

 Encrypted data written to file /var/lib/gg/enc/app/encrypted_data This contains a secret code, which is Open Sesame!


Расшыфраваныя дадзеныя цалкам супадаюць з арыгіналам.

Вы можаце ўбачыць фактычныя зашыфраваныя даныя, запісаныя ў файл, з дапамогай утыліты «васьмярковы дамп» («od») Linux:

 od -c /var/lib/gg/enc/app/encrypted_data


з такім вынікам:

 $ od -c /var/lib/gg/enc/app/encrypted_data 0000000 r 335 324 L 020 351 i ; 346 254 w 312 253 306 N 005 0000020 370 \t ) \n 020 235 367 317 305 t \0 224 214 270 210 315 0000040 # 307 351 216 025 274 362 033 % 253 023 7 335 306 320 0000060 224 # ! 021 252 242 325 H 300 217 # \vm V 351 0000100

Вось і ёсць. Вы заўважыце, што дадзеныя двайковыя, і яны на самой справе ўтрымліваюць нулявы байт(ы).

Шыфраваць двайковыя дадзеныя

Дадзеныя для шыфравання ў гэтых прыкладах з'яўляюцца радком, г.зн., раздзеленымі нулямі. Вы можаце зашыфраваць двайковыя даныя гэтак жа лёгка, указаўшы іх цалкам (паколькі Gliimly адсочвае, колькі там байтаў!) або ўказаўшы іх даўжыню ў пункце «input-length», напрыклад, скапіруйце гэта ў «encrypt.gliim»:

 begin-handler /encrypt public set-string str = "This c\000ontains a secret code, which is Open Sesame!" // Encrypt encrypt-data str to enc_str password "my_password" input-length 12 p-out enc_str @ // Decrypt decrypt-data enc_str password "my_password" to dec_str // Output binary data; present null byte as octal \000 string-length dec_str to res_len start-loop repeat res_len use i start-with 0 if-true dec_str[i] equal 0 p-out "\\000" else-if pf-out "%c", dec_str[i] end-if end-loop @ end-handler

Гэта зашыфруе 12 байтаў у месцы памяці "enc_str" незалежна ад любых нулявых байтаў. У дадзеным выпадку гэта «This c», за якім ідзе нулявы байт, за якім ідзе радок «ontain», але гэта могуць быць любыя двайковыя дадзеныя, напрыклад, змесціва файла JPG.

Што тычыцца дэшыфравання, вы атрымаеце колькасць байтаў, расшыфраваных у прапанове "output-length". Нарэшце, расшыфраваныя даныя паказваюцца дакладна арыгінальнымі, а нулявы байт прадстаўлены ў тыповым васьмярковым прадстаўленні.

Зрабіце заяўку:

 gg -q


Запусціце яго гэтак жа, як і раней:

 gg -r --req="/encrypt" --silent-header --exec


Вынік:

 6bea45c2f901c0913c87fccb9b347d0a This c\000ontai


Зашыфраванае значэнне карацейшае, таму што ў гэтым выпадку даныя таксама карацейшыя, а вынік цалкам супадае з арыгіналам.

Выкарыстоўвайце любы шыфр або дайджэст

Па змаўчанні выкарыстоўваецца шыфраванне AES256 і SHA256 са стандартнай бібліятэкі OpenSSL , абодва з якіх шырока выкарыстоўваюцца ў крыптаграфіі. Аднак вы можаце выкарыстоўваць любы даступны шыфр і дайджэст (напрыклад, хэш), якія падтрымліваюцца OpenSSL (нават карыстальніцкія, якія вы падаеце).

Каб убачыць, якія алгарытмы даступныя, зрабіце гэта ў камандным радку:

 #get list of cipher providers openssl list -cipher-algorithms #get list of digest providers openssl list -digest-algorithms


Гэтыя два дадуць спіс алгарытмаў шыфравання і дайджэста (хэшавання). Некаторыя з іх могуць быць слабейшымі за стандартныя, выбраныя Gliimly, а іншыя могуць быць там толькі для зваротнай сумяшчальнасці са старымі сістэмамі. Тым не менш, іншыя могуць быць зусім новымі і не мець дастаткова часу, каб быць пацверджаны ў той ступені, якую вы хочаце, каб яны былі.


Такім чынам, будзьце асцярожныя, выбіраючы гэтыя алгарытмы, і абавязкова даведайцеся, чаму вы змяняеце алгарытмы па змаўчанні. Тым не менш, вось прыклад выкарыстання шыфравання Camellia-256 (г.зн. "CAMELLIA-256-CFB1") з дайджэстам "SHA3-512". Заменіце код у «encrypt.gliim» на:

 begin-handler /encrypt public set-string str = "This contains a secret code, which is Open Sesame!" // Encrypt data encrypt-data str to enc_str password "my_password" \ cipher "CAMELLIA-256-CFB1" digest "SHA3-512" p-out enc_str @ // Decrypt data decrypt-data enc_str password "my_password" to dec_str \ cipher "CAMELLIA-256-CFB1" digest "SHA3-512" p-out dec_str @ end-handler


Зрабіце заяўку:

 gg -q


Запусціце:

 gg -r --req="/encrypt" --silent-header --exec


У гэтым выпадку вынік:

 f4d64d920756f7220516567727cef2c47443973de03449915d50a1d2e5e8558e7e06914532a0b0bf13842f67f0a268c98da6 This contains a secret code, which is Open Sesame!

Зноў жа, вы атрымаеце зыходныя дадзеныя. Звярніце ўвагу, што вы павінны выкарыстоўваць адзін і той жа шыфр і дайджэст як у encrypt-data, так і ў decrypt-data!

Вы, вядома, можаце стварыць двайковае зашыфраванае значэнне, як і раней, выкарыстоўваючы пункты "двайковы" і "вывадная даўжыня".

Калі ў вас ёсць знешнія сістэмы, якія шыфруюць даныя, і вы ведаеце, які шыфр і дайджэст яны выкарыстоўваюць, вы можаце супаставіць іх і зрабіць свой код сумяшчальным. Gliimly выкарыстоўвае стандартную бібліятэку OpenSSL, так што ёсць верагоднасць, што іншае праграмнае забеспячэнне таксама можа.

Выкарыстанне солі

Каб дадаць солі ў шыфраванне, выкарыстоўвайце пункт "соль". Вы можаце стварыць выпадковую соль, выкарыстоўваючы аператар random-string (або random-crypto , калі ёсць неабходнасць). Вось код для «encrypt.gliim»:

 begin-handler /encrypt public set-string str = "This contains a secret code, which is Open Sesame!" // Get salt random-string to rs length 16 // Encrypt data encrypt-data str to enc_str password "my_password" salt rs @Salt used is <<p-out rs>>, and the encrypted string is <<p-out enc_str>> // Decrypt data decrypt-data enc_str password "my_password" salt rs to dec_str p-out dec_str @ end-handler


Зрабіце заяўку:

 gg -q


Запусціце некалькі разоў:

 gg -r --req="/encrypt" --silent-header --exec gg -r --req="/encrypt" --silent-header --exec gg -r --req="/encrypt" --silent-header --exec


Вынік:

 Salt used is VA9agPKxL9hf3bMd, and the encrypted string is 3272aa49c9b10cb2edf5d8a5e23803a5aa153c1b124296d318e3b3ad22bc911d1c0889d195d800c2bd92153ef7688e8d1cd368dbca3c5250d456f05c81ce0fdd This contains a secret code, which is Open Sesame! Salt used is FeWcGkBO5hQ1uo1A, and the encrypted string is 48b97314c1bc88952c798dfde7a416180dda6b00361217ea25278791c43b34f9c2e31cab6d9f4f28eea59baa70aadb4e8f1ed0709db81dff19f24cb7677c7371 This contains a secret code, which is Open Sesame! Salt used is nCQClR0NMjdetTEf, and the encrypted string is f19cdd9c1ddec487157ac727b2c8d0cdeb728a4ecaf838ca8585e279447bcdce83f7f95fa53b054775be1bb2de3b95f2e66a8b26b216ea18aa8b47f3d177e917 This contains a secret code, which is Open Sesame!

Як бачыце, для кожнага шыфравання генеруецца выпадковае значэнне солі (у дадзеным выпадку даўжынёй 16 байт), і зашыфраванае значэнне кожны раз адрозніваецца, нават калі дадзеныя, якія шыфруюцца, аднолькавыя! Гэта ўскладняе ўзлом шыфравання такім чынам.

Вядома, каб расшыфраваць, вы павінны запісаць соль і выкарыстоўваць яе сапраўды гэтак жа, як пры шыфраванні. У кодзе тут зменная "rs" змяшчае соль. Калі вы захоўваеце зашыфраваныя значэнні ў базе дадзеных, вы, хутчэй за ўсё, захаваеце соль побач з ёй.

Вектар ініцыялізацыі

На практыцы вы не будзеце выкарыстоўваць рознае значэнне солі для кожнага паведамлення. Ён кожны раз стварае новы ключ, і гэта можа знізіць прадукцыйнасць. І ў гэтым сапраўды няма неабходнасці: выкарыстанне солі робіць кожны ключ (нават аднолькавы) нашмат цяжэй адгадаць. Пасля таго, як вы гэта зробіце, вам можа не спатрэбіцца рабіць гэта зноў ці часта.

Замест гэтага вы б выкарыстоўвалі IV (вектар ініцыялізацыі) для кожнага паведамлення. Звычайна гэта выпадковая радок, з-за якой адны і тыя ж паведамленні выглядаюць па-рознаму і павялічвае вылічальныя выдаткі на ўзлом пароля. Вось новы код для «encrypt.gliim»:

 begin-handler /encrypt public // Get salt random-string to rs length 16 // Encrypt data start-loop repeat 10 use i start-with 0 random-string to iv length 16 encrypt-data "The same message" to enc_str password "my_password" salt rs iterations 2000 init-vector iv cache @The encrypted string is <<p-out enc_str>> // Decrypt data decrypt-data enc_str password "my_password" salt rs iterations 2000 init-vector iv to dec_str cache p-out dec_str @ end-loop end-handler


Зрабіце заяўку:

 gg -q


Запусціце некалькі разоў:

 gg -r --req="/encrypt" --silent-header --exec gg -r --req="/encrypt" --silent-header --exec gg -r --req="/encrypt" --silent-header --exec


Вынік можа быць:

 The encrypted string is 787909d332fd84ba939c594e24c421b00ba46d9c9a776c47d3d0a9ca6fccb1a2 The same message The encrypted string is 7fae887e3ae469b666cff79a68270ea3d11b771dc58a299971d5b49a1f7db1be The same message The encrypted string is 59f95c3e4457d89f611c4f8bd53dd5fa9f8c3bbe748ed7d5aeb939ad633199d7 The same message The encrypted string is 00f218d0bbe7b618a0c2970da0b09e043a47798004502b76bc4a3f6afc626056 The same message The encrypted string is 6819349496b9f573743f5ef65e27ac26f0d64574d39227cc4e85e517f108a5dd The same message The encrypted string is a2833338cf636602881377a024c974906caa16d1f7c47c78d9efdff128918d58 The same message The encrypted string is 04c914cd9338fcba9acb550a79188bebbbb134c34441dfd540473dd8a1e6be40 The same message The encrypted string is 05f0d51561d59edf05befd9fad243e0737e4a98af357a9764cba84bcc55cf4d5 The same message The encrypted string is ae594c4d6e72c05c186383e63c89d93880c8a8a085bf9367bdfd772e3c163458 The same message The encrypted string is 2b28cdf5a67a5a036139fd410112735aa96bc341a170dafb56818dc78efe2e00 The same message

Вы бачыце, што адно і тое ж паведамленне выглядае па-рознаму ў зашыфраваным выглядзе, але пры расшыфроўцы яно зноў тое ж самае. Зразумела, пароль, соль, колькасць ітэрацый і ініцыялізацыйны вектар павінны быць аднолькавымі як для шыфравання, так і для дэшыфравання.

Звярніце ўвагу на выкарыстанне пункта "кэш" у encrypt-data і decrypt-data. Ён эфектыўна кэшуе вылічаны ключ (зададзены пароль, соль, алгарытмы шыфра/дайджэсту і колькасць ітэрацый), таму ён не вылічваецца кожны раз у цыкле. З «кэшам» ключ вылічваецца адзін раз, а потым для кожнага паведамлення выкарыстоўваецца іншы IV (у «ініцыялізацыйным вектары»).

Калі вы хочаце перыядычна аднаўляць ключ, выкарыстоўвайце пункт "ачысціць кэш", які дае лагічнае значэнне. Калі ісціна, ключ пералічваецца, у адваротным выпадку ён застаецца ў спакоі. Глядзіце encrypt-data для больш падрабязнай інфармацыі.

Заключэнне

Вы навучыліся шыфраваць і дэшыфраваць дадзеныя з дапамогай розных шыфраў, дайджэстаў, солі і значэнняў IV у Gliimly. Вы таксама можаце стварыць зразумелыя для чалавека зашыфраваныя значэнні і двайковы вывад, а таксама зашыфраваць як радкі, так і двайковыя значэнні (напрыклад, дакументы).