Сложная часть в основном связана с обработкой изображений, а не с криптографией.
Вы хотите извлечь из изображения достаточную энтропию надежным способом.
Это во многом связано с тем, как вы используете образ и модель противника.
Если ваш противник вообще ничего не знает об изображении, может быть достаточно некоторых простых грубых признаков, если ваш противник много знает об изображении, например, взглянул на него или знает примерно, где оно было снято, вам нужно быть более осторожным. от того, какая информация извлекается из изображения, и потребуется использовать более мелкие детали изображения, которые будет трудно извлечь стабильным образом.
Если каждый раз, когда изображение используется, оно сканируется одним и тем же высококачественным сканером, а между использованиями хранится в безопасном месте, чтобы оно не выцветало, не сморщивалось и не накапливало пыль, было бы проще получить сканы очень близко друг к другу и иметь только простое автоматическое выравнивание и дискретизация (пространственная и цветовая), чтобы каждый раз получать почти одну и ту же последовательность битов.
Тогда вопрос, какая модель ошибок у нас для результатов сканирования? Ожидаем ли мы гауссовский шум? соль и перец? шум выравнивания? вращение? добавление больших непрерывных кусков шума? световой шум?
С каждым типом шума можно бороться по-разному.
Общая схема решения: мы используем методы обработки изображений, чтобы минимизировать шум, чтобы перейти к представлению, которое устраняет большинство из них, затем вы ограничиваете пространство только определенными допустимыми точками и выбираете ближайшую допустимую точку к тому, что у нас есть, чтобы уменьшить шум до нуля.
Мы будем достаточно агрессивно дискретизировать и выбирать достаточно редкие действительные точки, чтобы мы могли надежно добраться до нулевого шума. На этом этапе у нас все еще должно быть намного больше требуемой длины ключа, но в пространстве, все еще тесно связанном с исходным изображением, и поэтому биты будут смещены и коррелированы.
Применение криптографического хэша к этим данным должно упорядочить их и позволить нам получить достаточное количество высококачественного ключевого материала, надежно полученного, и получать один и тот же ключ точно при каждом сканировании. Это может быть использовано, например, как ключ AES.
Если вы хотите создать ключ RSA, вам понадобится гораздо больше случайных битов. Однако вы можете извлечь столько битов, сколько сможете извлечь, при этом каждый раз надежно получая одни и те же биты, и использовать их для заполнения криптографического PRNG и использовать его для создания закрытого ключа RSA.
Редактировать: я не пытался реализовать полное решение, но я открыл блокнот и поиграл с предложенной моделью шума, гауссовский шум и сдвиги, которые, как мне кажется, легко исправляются, поэтому я проверил, что произойдет, если я поверну изображение (с причудливым интерполяции) на 2 градуса и повернуть назад на 1,8 градуса. Я получил максимальную разницу (на изображении выше) 33%, это подтверждает мое утверждение о том, что путем определения наилучшего поворота и сдвига счетчика, снижения разрешения и агрессивного квантования, игнорируя края, мы должны быть в состоянии получить 1-2 бита на канал на ~ 25 областей пикселей. Для приведенного выше изображения получается не менее 36 КБ бит, и после хэширования, я уверен, у него будет 128 бит фактической энтропии.
Edit2: я загрузил предоставленные изображения сканов в оттенках серого и поиграл с ними, я полуавтоматически выровнял первые два изображения.
img = io.imread("сканы/scan078.tif")
img2 = io.imread("сканы/scan079.tif")
imgr = transform.rotate (img, угол = -0,78)
imgr2 = transform.rotate (img2, угол = -0,805)
tr1=transform.rescale(imgr[:-10,:-6],0.1)[20:-20,20:-20]
tr2=transform.rescale(imgr2[10:,6:],0.1)[20:-20,20:-20]
Это чтение поворачивает каждое выравнивание и кадрирование, понижает разрешение в 10 раз и кадрирует, чтобы избавиться от краев, которые могут иметь артефакты.
Это дает максимальную разницу менее 6% на значение пикселя. Что очень хорошо. Однако эта разница в 6% легко может быть около любой выбранной нами отсечки, поэтому даже агрессивное квантование не дает 0 ошибок.
бин1 = тр1> 0,5
бин2 = тр2> 0,5
Это дало разницу в 103 бита из 27248 бит или 0,37%. Эти ошибки кажутся разумно разбросанными.
Это агрессивное изменение размера и квантизация приводит к потере большого количества информации, но, вероятно, у нас ее еще достаточно.
Вот как выглядит изображение:
Ошибки довольно хорошо распределены (и мы всегда можем применить фиксированную перестановку или использовать более крупные символы, если это необходимо). Итак, теперь мы можем применить любой шаг исправления ошибок (например, Рид Соломон), мы просто выполним шаг декодирования (на самом деле этого не делали), и мы должны получить одинаковый результат для любого изображения с высокой вероятностью и все еще иметь ~ 20 КБ бит.
Если мы уменьшим масштаб в 5 раз вместо 10, мы получим 816 различных битов. но получите в 4 раза больше битов с разницей 0,6%. Можно поиграть с этим и найти оптимум.
Мы также, вероятно, можем добиться большего успеха на этапе квантования и надежно сохранить больше информации. Агрессивное квантование, которое я использовал, будет работать только для достаточно сбалансированных фотографий, переэкспонированное изображение будет иметь одно значение. Мы могли бы добавить предварительную обработку для обработки этого сценария.