Самый простой способ сокрытия конфиденциальной информации - PullRequest
3 голосов
/ 20 марта 2010

Какой самый простой способ скрыть конфиденциальный идентификатор, предоставляя некоторые эквивалентные средства идентификации данных извне?

Например, допустим, у меня есть таблица базы данных с записями, и одна из них -поле чувствительного идентификатора.

ID
2A
1S
etc...

тогда я хочу получить вторую запись:

ID    PublicID
2A    AXXX44328
1S    KKKZJSAAS

, чтобы при получении PublicID я всегда мог определить, к какому идентификатору он относится:

H(PublicID) = ID

но никто другой не может этого сделать.

Также обратите внимание, что я хочу иметь возможность воспроизводить строку как минимум в двух разных местах.Поэтому, если у меня два сервера / базы данных, ID 2A должен сопоставляться со строкой AXX44328 на каждом из них независимо.

Я подозреваю, что это похоже на шифрование - с выбрасыванием открытого ключа?

Ответы [ 4 ]

3 голосов
/ 20 марта 2010

Если ваши идентификаторы относительно короткие (15 байт или меньше), то я предлагаю зашифровать их блочным шифром, а именно AES . AES использует секретный ключ K длиной 128, 192 или 256 бит (достаточно 128 бит). Поскольку AES обрабатывает блок размером 16 байтов, вам нужно немного дополнить свой идентификатор. «Обычный» заполнитель (известный как «PKCS # 5») состоит в добавлении n байтов ( n> = 1 ), все они имеют значение n так, чтобы полученная длина была подходящей (здесь вам нужна длина 16).

Таким образом, преобразование ID (конфиденциальные данные) в S (шифрованная строка, которая может быть показана широкой публике): S = AESencrypt_K ( площадка (ID)) . Обратная операция: ID = unpad (AESdecrypt_K (S)) . Если ID равен 16 байтам или более, то при шифровании будет использоваться несколько вызовов AES, и есть некоторые тонкости в том, как эти вызовы связаны друг с другом. Ключевое слово режим цепочки и обычный ответ "CBC".

Знание секретного ключа K (тот же K ) необходимо для обеих операций. Это означает, что тот, кто может вычислить S из ID , также может вычислить ID из S и наоборот.

Теперь, если вам нужно, чтобы некоторые сущности могли вычислять S из ID , не давая им возможности выполнять обратную операцию, тогда все будет сложнее. В частности, у вас не должно быть детерминированного процесса: если существует единственный S , который может быть вычислен из ID , тогда любой может попробовать исчерпывающий поиск возможных значений ID , пока не будет найдено соответствие с данным S . Таким образом, вы должны расслабить модель, так как данный ID может дать большое количество возможных зашифрованных строк S ', так что все эти S' могут быть преобразованным обратно в ID кем-то, кто имеет "правильное" секретное значение. Это то, что вы получите от асимметричного шифрования. Обычный алгоритм асимметричного шифрования - RSA . С 1024-битным ключом RSA (типичный размер для надлежащей защиты) ID может иметь размер до 117 байт, а S ' будет иметь длину 128 байт (размер увеличение соответствует введенным случайным данным, что делает процесс недетерминированным). Если 128 байтов слишком много, вы можете получить более короткие зашифрованные сообщения с помощью шифрования Эль-Гамаля по эллиптическим кривым (примерно до 40 байт или около того, для размера до 10 байт ID ), но вы может быть трудно найти существующую реализацию.

3 голосов
/ 20 марта 2010

Достаточно сгенерировать случайную уникальную строку какого-либо вида и сохранить ее в базе данных в качестве вашего публичного идентификатора.Индексируйте таблицу по общедоступному идентификатору, и вы можете легко получить реальный идентификатор (и другие значения строк), используя открытый идентификатор.Поскольку база данных является частной, никто не может определить идентификатор с помощью открытого идентификатора.

Простой способ генерировать случайную уникальную строку - взять хеш (например, SHA-1) реального идентификатора +некоторое солт-значение, например

my $public_id = sha1( $salt . $id );

Значение $salt должно быть длинной случайной строкой, которая генерируется один раз, хранится на сервере и никогда не раскрывается публично.Злоумышленнику очень трудно (почти невозможно) взломать реальный идентификатор из публичного идентификатора путем грубого форсирования хэша (что может быть довольно легко без соли, если идентификатор короткий и числовой)

Преимущество этого подхода состоит в том, что один и тот же $ id всегда будет отображаться на один и тот же $ public_id, пока значение $ salt остается постоянным.


Если это не вариант, сгенерируйтеслучайный ключ и зашифруйте реальный идентификатор с его помощью, и используйте зашифрованную версию в качестве публичного идентификатора.Затем вы можете расшифровать этот идентификатор позже, чтобы получить реальный идентификатор.

1 голос
/ 20 марта 2010

Поскольку вы хотите иметь возможность воссоздания идентификатора в двух автономных базах данных, вам потребуется какой-то общий ключ.

Это идеальное место для HMAC .Чтобы украсть у RFC-2104 по википедии:

Пусть:H (·) - криптографическая хеш-функцияK - секретный ключ, дополняемый вправо дополнительными нулями до размера блока хеш-функцииможет быть сообщение для аутентификации∥ обозначить конкатенациюExclusive обозначает эксклюзив или (XOR)opad будет внешним дополнением (0x5c5c5c… 5c5c, шестнадцатеричная константа длиной в один блок)ipad будет внутренним отступом (0x363636… 3636, шестнадцатеричная константа длиной в один блок)

Тогда HMAC (K, m) математически определяется какHMAC (K, m) = H ((K ⊕ opad) ∥ H ((K ⊕ ipad) ∥ m)).

Но вам не нужно реализовывать это самостоятельно!Используйте стандартную библиотеку по вашему выбору.Например, в Python:

>>> import hmac
>>> hmac.new(key='abc123secret make me long', msg='This is my unique key #1')
<hmac.HMAC instance at 0xb77bdbac>
>>> _.hexdigest()
'c23a224afa917d13fbef58ee14884269'

Теперь у вас есть вычисляемый уникальный идентификатор.Предварительно вычислите как первичные ключи в вашей базе данных.Выполните поиск при необходимости!


В качестве sidenote, NOT используйте соленый хеш (Google: "не хэшируйте секреты" ) и НЕ используйте зашифрованную версию ваших данных.Первый из-за атак на расширение сообщения.Последнее, потому что вы излишне выставляете данные таким образом, который отвечает исключительно на безопасность вашего ключа.

Я бы связался с большим количеством ссылок, но я новый пользователь.: - \

1 голос
/ 20 марта 2010

Вы не указали язык программирования. Вот пример в PHP, подобный тому, что RJH предложил с SHA1, но использует правильный алгоритм симметричного шифрования, а не SHA1, исключая (даже удаленную) возможность коллизий:


define('KEY', 'S4mPhZg3rQga');

function encrypt($text)
{
    return base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, KEY, $text, MCRYPT_MODE_ECB, mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND)));
}

function decrypt($text)
{
    return mcrypt_decrypt(MCRYPT_RIJNDAEL_256, KEY, base64_decode($text), MCRYPT_MODE_ECB, mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND));
}

// example usage:
$C = encrypt('1234');
echo("Public ID: $C\n");

$P = decrypt($C);
echo("Private ID: $P\n");

Значение KEY должно быть установлено один раз, с одинаковым значением на обоих серверах, и никогда не должно раскрываться. Вы будете использовать encrypt () при отображении данных и decrypt () при приеме данных извне. На самом деле нет необходимости хранить PublicID, вы просто вычисляете его на лету.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...