Чи може машинне навчання розшифрувати хеші SHA256?


43

У мене 64 хеш-символів SHA256.

Я сподіваюся підготувати модель, яка може передбачити, починається чистий текст, що використовується для створення хешу, з 1 чи ні.

Незалежно, якщо це "Можливо", який алгоритм був би найкращим підходом?

Мої початкові думки:

  • Створіть великий зразок хешей, який починається з 1, і великий зразок хешей, який не починається з 1
  • Встановіть кожен із 64 символів хеша як параметр для якоїсь непідконтрольної логістичної моделі регресії.
  • Тренуйте модель, кажучи їй, коли вона правильна / неправильна.
  • Будемо сподіватися, що зможемо створити модель, яка може передбачити, чи непростий текст починається з 1 чи ні з достатньо високою точністю (і з гідною каппою)

22
FYI: Це, ймовірно, мотивовано видобутком біткойна.
ClojureMostly

55
"Як би я тренував модель, яка дозволяє мені подорожувати часом, незалежно від того, чи це" можливо "?"
Конрад Рудольф

13
@Joshua OP хоче інвертувати SHA-256. Я дозволю йому опублікувати, навіть якщо це займе тисячу разів більше кроків, ніж SHA-256. Я також припиню існувати, оскільки рішення майже напевно використовує помилку в самій тканині реальності, щоб перемогти логіку.
Конрад Рудольф

15
Усі хеші SHA256 можуть бути згенеровані рядком, який починається з "1".
Реакційний

8
@cgTag Вибачте, але це просто неправильно. Вхід контролює вихід, інакше це не буде функцією в першу чергу. Крім того, тільки тому, що у вас є нескінченний перелік речей, це не означає, що одна з них починається з 1. Ви намагаєтесь довести відому криптографічну гіпотезу в коментарі SE. Примітка. Я також вважаю, що це правда, але стверджувати, що це правда, вводить в оману. Якщо ви маєте рацію, напевно буде документ або будь-яка інша довідка.
Педро

Відповіді:


98

Це насправді не є статистичною відповіддю, але:

Ні , ви не можете визначити перший символ простого тексту з хеша, тому що для даного хешу не існує такого поняття, як "простий текст".

SHA-256 - алгоритм хешування. Незалежно від того, який ваш простий текст, у вас виходить 32-байтовий підпис, який часто виражається шістнадцятковим шістнадцятковим рядком Існує набагато більше можливих простих текстів, ніж можливі 64 шістнадцяткові шістнадцяткові рядки - той самий хеш може генеруватися з будь-якої кількості різних простих текстів. Немає підстав вважати, що перший символ, який є / не є «1», є рівномірним для всіх простих текстів, що створюють заданий хеш.


21
Це поки що (на мій погляд) єдина правильна відповідь. Усі інші відповіді, здається, стосуються більше проблеми вивчення хеш-функції, а не навчитися інвертувати хеш (власне питання). Вони, схоже, ігнорують, що хеширование не є ін'єкційною функцією.
Лука Сіті

7
Не могли б ви передбачити ймовірність того, що перший знак - це один? Нестача єдиноборства не є рідкісною проблемою в статистичному навчанні.
Меттью Друрі

16
@MatthewDrury Враховуючи, що SHA256 призначений для того, щоб зробити всі входи однаково ймовірними для даного хешу, сподіваємось, буде нескінченно багато входів, починаючи з 1, для будь-якого даного хешу . Отже, якщо ви хочете оцінити ймовірність, ваша найкраща оцінка буде приблизно . 1256±ε
Конрад Рудольф

12
Так, згоден. Я просто хотів зазначити, що недостатня інжективність насправді не є структурною проблемою із застосуванням машинного навчання.
Меттью Друрі

6
@IMil Причина, про яку я конкретно згадував той факт, що це хеш-функція, - це не припускати, що жодна хеш-функція ніколи не могла б розкрити цю інформацію, а мотивувати твердження, що не існує такого поняття, як "явний текст". Зрозуміло, що (погана) хеш-функція може бути частково зворотна і чітко сказати нам щось про весь набір простих текстів, які могли б її створити, але немає причин вважати, що SHA-256.
Кріс Х

51

SHA256 розроблений таким чином, щоб бути максимально випадковим, тому навряд чи ви зможете відокремити хеші, що надходили з 1-го попередньо встановленого простого тексту, від тих, які не є просто не повинно бути жодної особливості хеш-рядка, яка б віддала цю інформацію.


5
"навряд чи" і "повинен" - Ось що мені скаже алгоритм. На перший погляд це здається неможливим, але я хотів би знати, який алгоритм та підхід використовувати для перевірки цієї гіпотези.
Джон

24
+1 Гарантується, що будь-яка «модель нерегульованої логістичної регресії» не зможе зробити кращого, ніж здогадуватися, якщо вона не зможе поставити справді астрономічну кількість випадків. Ця проблема є нахилом на вітряках.
whuber

44
Можна спробувати, але учень намагатиметься знайти статистичну залежність, яка навмисно призначена для того, щоб не існувати.
Павло Комаров

32
"Розроблений як можна випадковіше" - це заниження. Зокрема, конструкція має на меті максимально нелінійну залежність, де кожен вхідний біт впливає приблизно на 50% вихідних бітів, а кожен вихідний біт залежить приблизно від 50% вхідних бітів. Це відомо як плутанина і дифузія . Тут робиться завдання (відновлення лише першого біта) так само важко, як і відновлення всього повідомлення.
MSalters

12
Я думаю, ви можете зміцнити "навряд чи" у цій відповіді. ОП має нульовий шанс застосувати методи, засновані на статистиці, для прогнозування будь-якої частини хеша SHA256 із вмісту, або навпаки, навіть з помітним поліпшенням порівняно з випадковим здогадуванням. Практичне рішення полягає в тому, щоб попередньо обчислити цільову сукупність оригінального вмісту.
Ніл Слейтер

43

Незалежно, якщо це "Можливо", який алгоритм був би найкращим підходом?

Вибачте, але це безглузде питання. Якщо щось неможливо, то ви не можете шукати найкращого підходу до проблеми.

У цьому випадку це, безумовно, має бути неможливим, оскільки хешування - це одностороння функція: декілька входів (насправді нескінченних) можуть давати однаковий вихід. Якщо перший біт введення самостійно якось вплине на ймовірність конкретного хеш-значення, це означатиме, що алгоритм хешу повністю хибний.

Ви, звичайно, можете тренувати нейронну мережу, лінійний класифікатор, SVM та інше, щоб спробувати передбачити. І якщо вам вдасться надійно передбачити вхід з виводу для певного алгоритму хешування, це призведе до того, що цей алгоритм марний. Я б сказав, що для широко використовуваного алгоритму типу SHA256 така можливість є надзвичайно низькою. Однак розумний підхід дозволяє швидко виключати нові, не доведені та неперевірені алгоритми хешуваннявання.


6
sign(x)

11
@KonradRudolph: "Одностороння функція" має в цьому контексті специфічне значення, яке не є тим значенням, про яке ви думаєте. sign(x)в цьому сенсі не є односторонньою функцією, оскільки пошук примірників є тривіальним.
user2357112

4
При цьому, я не думаю, що відповідь також правильно використовує "односторонню функцію".
user2357112

1
@ user2357112 Спасибі, я цього не знав. Я знав лише значення як функцію, яка є сюжективною, але не біективною. Це теж визначення, яке дано у відповіді, і це те, на що я заперечував.
Конрад Рудольф

1
Так, вибачте, я трохи розслаблений з визначеннями. Однак я вважаю, що «односторонній» новачкам зрозуміліший, ніж суворіші.
ІМіль

26

Хоча не можна довести негатив на прикладі. І все-таки я відчуваю, що приклад був би сугестивним; і, можливо, корисно. І це показує, як можна було б (намагатися) вирішити подібні проблеми.

У випадку, коли я хочу зробити двійкові прогнози, використовуючи функції, що є двійковими векторами , Random Forest - це вагомий вибір. Я думаю, цей тип відповідей на другу частину вашого питання: що таке хороший алгоритм.

Ми добре хочемо попередньо обробити рядки SHA256 у бінарні (булеві) вектори, оскільки кожен біт є статистично незалежним, тому кожен біт є хорошою особливістю. Таким чином, це зробить наші входи булевими векторами 256 елементів.

Демо

Ось демонстрація того, як все можна зробити за допомогою бібліотеки Julia DecisionTree.jl .

Ви можете скопіювати вставку нижче в підказку julia.

using SHA
using DecisionTree
using Statistics: mean
using Random: randstring

const maxlen=10_000 # longest string (document) to be hashed.

gen_plaintext(x) = gen_plaintext(Val{x}())
gen_plaintext(::Val{true}) = "1" * randstring(rand(0:maxlen-1))
gen_plaintext(::Val{false}) = randstring(rand(1:maxlen))


bitvector(x) = BitVector(digits(x, base=2, pad=8sizeof(x)))
bitvector(x::AbstractVector) = reduce(vcat, bitvector.(x))

function gen_observation(class)
    plaintext = gen_plaintext(class)
    obs = bitvector(sha256(plaintext))
    obs
end

function feature_mat(obs)
    convert(Array, reduce(hcat, obs)')
end

########################################

const train_labels = rand(Bool, 100_000)
const train_obs = gen_observation.(train_labels)
const train_feature_mat = feature_mat(train_obs)

const test_labels = rand(Bool, 100_000)
const test_obs = gen_observation.(test_labels)
const test_feature_mat = feature_mat(test_obs)


# Train the model
const model = build_forest(train_labels, train_feature_mat)
@show model


#Training Set accuracy:
@show mean(apply_forest(model, train_feature_mat) .== train_labels)

#Test Set accuracy:
@show mean(apply_forest(model, test_feature_mat) .== test_labels)

Результати

Коли я це зробив, тренувався на 100 000 випадкових рядків ASCII довжиною до 10 000. Ось результати, які я побачив:

Тренуйте модель

julia> const model = build_forest(train_labels, train_feature_mat)
Ensemble of Decision Trees
Trees:      10
Avg Leaves: 16124.7
Avg Depth:  17.9

Точність набору тренувань:

julia> mean(apply_forest(model, train_feature_mat) .== train_labels)
0.95162

Точність тестового набору:

julia> mean(apply_forest(model, test_feature_mat) .== test_labels)
0.5016

Обговорення

Так що це в основному нічого. Ми пройшли від 95% на тренувальному наборі, до ледве понад 50% на тестовому наборі. Хтось може застосувати належні тести на гіпотезу, щоб побачити, чи можемо ми відкинути нульову
гіпотезу, але я впевнений, що ми не можемо. Це незначне поліпшення порівняно зі здогадами.

Це говорить про те, що цього не можна вивчити. Якщо випадковий ліс, може перейти від добре пристосованого до того, щоб вразити лише показник здогадок. Випадкові ліси цілком здатні вивчити складні матеріали. Якби було чому навчитися, я би сподівався хоча б на кілька відсотків.

Ви можете грати з різними хеш-функціями, змінюючи код. Що може бути цікаво, я отримав в основному однакові результати, коли використовував функцію julia у вбудованій hashфункції (яка не є криптографічно захищеним hsah, але все-таки є хорошим хешем, тому дійсно слід розсилати подібні рядки один від одного). Я також отримав однакові результати CRC32c.


15

Функції хешу (за задумом) надзвичайно погано підходять для виконання будь-якого машинного навчання з ними.

ML по суті є сімейством методів моделювання / оцінки локально безперервних функцій. Тобто ви намагаєтесь описати певну фізичну систему, яка, хоча може мати певні розриви, у певному сенсі у більшості простору параметрів досить гладка, так що для прогнозування результату для інших можна використовувати лише розкидану вибірку тестових даних. вхід. Для цього алгоритмам AI потрібно якось розкласти дані на розумне представлення основи, для чого тренінг підказав, що, наприклад, якщо ви бачите таку і таку форму (яка, схоже, співвідноситься з результатом такої і такої згортки), то є хороший шанс, що вихід повинен мати відповідну область таку і таку структуру (що знову можна описати згорткою чи чимось).

(Я знаю, багато підходів до ML зовсім не схожі на згортання, але загальна ідея завжди однакова: у вас є вхідний простір, який має такі великі розміри, що неможливо вичерпно пробити вибірку, тому ви знайдете розумне розкладання, яке дозволяє екстраполювати результати порівняно рідкого зразка.)

Однак ідея криптографічної хеш-функції полягає в тому, що будь-яка зміна простого тексту повинна призвести до зовсім іншого дайджесту. Отже, як би ви не розкладали функцію, місцеві оцінки не дозволять вам екстраполювати, як невеликі коливання навколо цієї частини впливають на результат. Якщо, звичайно, ви фактично не обробляєте всю інформацію обмеженого набору, але це не назветься машинним навчанням: ви просто будуєте таблицю з веселки .


4
Читаючи це, мені спало на думку, що а) щоб створити таблицю веселки, потрібно знати, яку хеш-функцію використовувати, і б) можливо, алгоритм машинного навчання визначить, який алгоритм використовується, даючи досить великий вибірку входів та виходів (принаймні, якщо алгоритм має виявлені вади). Тож якби початкова проблема була перетворена на предмет невідомої хеш-функції, яку потрібно визначити, це може бути цікавіше.
senderle

7

Це цікаве питання, оскільки воно ставить питання про те, що вважається "машинним навчанням". Звичайно, є алгоритм, який врешті вирішить цю проблему, якщо її можна буде вирішити. Виходить так:

  1. Виберіть улюблену мову програмування та визначтесь з кодуванням, яке відображає кожну рядок у (потенційно дуже велике) ціле число.

  2. Виберіть випадкове число і перетворіть його в рядок. Перевірте, чи дійсна програма вашою мовою. Якщо ні, виберіть інше число та спробуйте ще раз. Якщо це так, запустіть його, негайно призупиніть його та додайте до списку призупинених програм.

  3. Запустіть кілька призупинених програм на деякий час. Якщо будь-яка з них зупиняється, не виробляючи адекватного рішення, видаліть їх зі списку. Якщо хтось виробляє адекватне рішення, ви закінчили! В іншому випадку поверніться до 2 після того, як дозволите їм трохи працювати.

Немає сумніву, що якщо у вас є нескінченне сховище та нескінченний час, вищезгаданий алгоритм зрештою знайде хороше рішення. Але це, мабуть, не те, що ви маєте на увазі під «машинним навчанням».

Ось руб: якщо врахувати всі можливі проблеми, жоден алгоритм машинного навчання в середньому не може зробити краще! Це відомо як теорема про безкоштовний обід . Це доводить, що серед усіх можливих проблем, які можна було б вирішити в будь-якому заданому алгоритмі машинного навчання, число, яке воно може швидко вирішити , зникає невелике.

Він може швидко вирішити ці проблеми лише тому, що ними керуються шаблони, які алгоритм може передбачити. Наприклад, багато успішних алгоритмів передбачають наступне:

  1. Рішення можна описати деякими складними рядами множин матриць та нелінійних спотворень, керованих набором параметрів.

  2. Хороші рішення будуть згруповані в просторі параметрів, так що все, що вам потрібно зробити, - це вибрати мікрорайон пошуку, знайти там найкраще рішення, змістити околиці пошуку, щоб найкраще рішення знаходилось в центрі, і повторити.

Очевидно, що жодне з цих припущень не є загальним. Другий особливо підозрілий. І жоден безкоштовний обід говорить нам, що ці припущення навіть не займають більшу частину часу. Насправді вони майже ніколи не тримаються! Це наше щастя, що вони насправді мають певні проблеми, які насправді мають значення.

Вибрана вами проблема створена з самого початку, щоб порушити припущення 2. Функції хеша спеціально розроблені так, що подібні входи дають абсолютно різні результати.

Отже, на ваше запитання - який найкращий алгоритм машинного навчання для вирішення цієї проблеми? - ймовірно, є дуже простий відповідь: випадковий пошук.


Цікаво, як квантові обчислення впливатимуть на теорему без вільного обіду. Імовірно, квантові обчислення теж обмежені.
Макс Вернон

1
@MaxVernon о, цікаво. Я б очікував, що всі квантові алгоритми мають однакову властивість у порівнянні з іншими квантовими алгоритмами . Я не знаю, чи всі алгоритми квантової оптимізації мають середнє значення швидкості порівняно з класичними. Вони можуть! У мене є запитання і самовідповідь, які говорять про теорему про "безкоштовний обід", яка може бути актуальною. (tldr; обід безкоштовний, лише якщо ви проігноруєте деякі виконані роботи ... але мені цікаво, чи це зміниться у квантовому випадку.)
senderle

5

Це поруч із неможливим. Однак люди спостерігали деякі шаблони в SHA256, які можуть підказати про його невипадковість. Відмінністю для SHA256 за допомогою Bitcoin (видобуток швидше на цьому шляху) . Їх tldr:

"Щоб розрізнити ідеальний випадковий хеш перестановки і SHA256, хеш великої кількості (~ 2 ^ 80) кандидатів 1024 бітових блоків, як це зроблено в Bitcoin. Переконайтеся, що біти кандидатних блоків рідко встановлені (набагато менше, ніж 512 означає очікуване), згідно з протоколом Bitcoin, відкидання кандидатських блоків, які не відповідають стандарту "складності" Bitcoin (де отримані хеші починаються з великої кількості 0). З рештою набором дійсних кандидатів на введення (467369, коли цей аналіз був зроблений), спостерігайте за певним набором з 32 біт у вхідному блоці (розташованому там, де у біткоіна немає значення, вхідні біти 607-639). Зверніть увагу, що середня кількість бітів, встановлених у полі без значень, перекошена зліва, тобто менше очікуваного значення набору 16 біт (середнє оцінювання 15,428). "

Дивіться дискусію на сайті lobste.rs . Одне можливе пояснення - упередженість, яку запроваджують гірники.


2
Це цікаво. Але відповідь на сайті lobste.rs, ймовірно, правильна. Це величезний ухил, який легко виявити. Думка про те, що вона пройшла непомітно протягом такого довгого часу, є досить надуманою.
senderle

1
@senderle Для того, щоб використовувати зміщення (якщо такі є), слід придумати алгоритм (по суті, алгоритм ML / оптимізації), який обчислюється дешево, так що його власні накладні витрати при впровадженні / вимірюванні на найсучаснішому апаратному забезпеченні компенсується швидкістю, яку він забезпечує. Я дуже грубо здогадуюсь, що коефіцієнт для #hashtrials повинен бути більшим, ніж 10 разів, щоб перемогти грубу силу та її надто оптимізовані реалізації. Наслідки можуть бути дуже серйозними, особливо для людей, які роблять ставку на криптовалюти та протоколи безпеки.
IndieSolver

4

Я відповім програмою. Для зменшення обчислювальних вимог я використовую варіант sha256, який я називаю sha16, що є лише першими 16 бітами sha256.

#!/usr/bin/python3

import hashlib
from itertools import count

def sha16(plaintext):
    h = hashlib.sha256()
    h.update(plaintext)
    return h.hexdigest()[:4]

def has_plaintext_start_with_1(digest):
    """Return True if and only if the given digest can be generated from a
    plaintext starting with "1" first bit."""
    return True

def plaintext_starting_with_1(digest):
    """Return a plaintext starting with '1' matching the given digest."""
    for c in count():
        plaintext = (b'\x80' + str(c).encode('ascii'))
        d = sha16(plaintext)
        if d == digest:
            return plaintext

for digest in range(0x10000):
    digest = "%04x" % (digest,)
    plain = plaintext_starting_with_1(digest)
    print("%s hashes to %s" % (plain, digest))

Це дає результат:

b'\x8094207' hashes to 0000
b'\x8047770' hashes to 0001
b'\x8078597' hashes to 0002
b'\x8025129' hashes to 0003
b'\x8055307' hashes to 0004
b'\x80120019' hashes to 0005
b'\x8062700' hashes to 0006
b'\x8036411' hashes to 0007
b'\x80135953' hashes to 0008
b'\x8044091' hashes to 0009
b'\x808968' hashes to 000a
b'\x8039318' hashes to 000b
[...]

Я залишу повний доказ як вправу для читача, але візьмемо своє слово для цього: є вхід, який починається з "1" для кожного можливого дайджесту від 0000 до ffff.

Також є вхід, який не починається з "1". І є ще одна, яка починається з повних творів Шекспіра.

Це стосується будь-якої досить хорошої хеш-функції, хоча моє доказ грубої сили може стати обчислювально нездійсненним.


У математиці я не люблю сприймати ваше слово . Ваша програма демонструє, що ваша функція sha16 є сюжективною, але нічого більше. Ви не дали офіційного підтвердження того, що ця програма може довести фактичну функцію SHA-256. Згідно з вашим стилем висновку, гіпотеза Collatz була б вирішена, оскільки вона вже вирішена на 32 біти, і програму можна легко запустити довше.
Roland Illig

4

Те, що ви описуєте, в основному є попередньою атакою. Ви намагаєтеся знайти такий вхід, що, коли він хеширується, вихід має деяку властивість, наприклад "провідний 1". *

Це чітка мета криптографічних хешів запобігти таким атак попереднього зображення. Якщо ви можете зробити таку атаку, ми схильні вважати цей алгоритм небезпечним і перестаємо його використовувати.

Тож це означає, що це не неможливо, це означає, що ваш алгоритм машинного навчання повинен був одночасно перехитрити велику частину математиків у світі та їх суперкомп'ютери. Навряд чи ви це зробите.

Однак, якби ви це зробили, ви стали б відомими як хтось, хто порушив головний алгоритм криптографічного хешу. Та слава чогось варта!

* Технічно "перша атака попереднього зображення" намагається знайти відповідність конкретному хешу. Однак, щоб показати, що алгоритм хешу має стійкість до першої дії на атаку, вони зазвичай показують, що ви не можете знайти будь-якої змістовної інформації про вхід з хеша.


2

Більшість усіх відповідей тут говорить про те, чому ви не можете цього зробити, але ось пряма відповідь на:

Незалежно, якщо це "Можливо", який алгоритм був би найкращим підходом?

Якщо вхід є досить великим:

  1. Візьміть підрахунок набору дійсних символів.
  2. Візьміть зворотну кількість числа з кроку 1.

Це ймовірність того, що рядок введення починається з "1". Вам навіть не потрібно дивитись на вхід. Якщо ви можете зробити це краще, це означатиме, що хеш дуже зламаний. Ви можете заощадити багато циклів процесора, намагаючись навчити алгоритм для вибору випадкових чисел.

Ви можете навчити алгоритм, і він може придумати іншу відповідь через переоформлення. Тобто, якщо з алгоритмом хешу щось дійсно не так. Використання цього алгоритму виходить не так частіше, ніж якщо ви просто вибираєте випадкове значення.


1

Функції хешування цілеспрямовано розроблені таким чином, щоб їх важко моделювати, тому (як уже зазначалося) це, ймовірно, буде дуже складно. Тим не менш, будь-яка слабкість функції хешування зменшить її ентропію, зробивши її більш передбачуваною.

Незалежно, якщо це "Можливо", який алгоритм був би найкращим підходом?

Корисним прикладом є Фізично нерозбірлива функція , або ПУФ , яка є аналогом функції апаратного хешування. Як правило, виробничі варіанти цілеспрямовано використовуються для того, щоб дати кожному PUF дещо іншу реакцію, щоб їх "хешований" вихід був різним для даного введення. Недоліки в дизайні обмежують ентропію, однак, враховуючи достатню кількість пар, що реагують на виклики та відповіді, часто можна побудувати модель чорного блоку PUF, щоб можна було передбачити відповідь на новий, раніше небачений виклик.

Логістична регресія є найбільш часто використовуваним підходом для цих моделювальних атак, як, наприклад, у цій роботі Рюрмахра .

Генетичні алгоритми (або загалом еволюційні стратегії) можуть бути альтернативним підходом, оскільки вони застосовні до проблем, які не є диференційованими та / або лінійно відокремленими. Вони також обговорюються у вищенаведеній роботі.


1

251222562256

26402641

2256264(2256264)!

S=(2256264)
C=90100S
CSC

(1S1S11S2...1S(C1))(SC1SCSC2SC1SC3SC2...12)=(SC1)!S!

=(110(2256264)1)!(2256264)!
2(2263.99184665662260.6509677217)
210.13222373912260.6509677217

22562512


1

Проблема полягає в тому, що "машинне навчання" не є розумним. Він просто намагається знайти зразки. У SHA-256 немає шаблонів. Нічого знайти. Машинне навчання не має жодного шансу, кращого за грубу силу.

Якщо ви хочете зламати SHA-256 за допомогою комп'ютера, єдина можливість - це створити справжній інтелект, і оскільки багато розумних людей не знайшли способу створити SHA-256, вам потрібно створити штучний інтелект, що набагато вище, ніж що у багатьох розумних людей. Тоді ми не знаємо, чи може такий надлюдський інтелект зламати SHA-256, довести, що його не можна зламати, або вирішив би, що це не досить розумно робити (як і люди). Четверта можливість - це, звичайно, такий штучний інтелект над людьми навіть не турбуватиметься, а думатиме про важливіші проблеми (для нього).

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.