Способ создания подписи или хэша изображения в ASP.NET для обнаружения дубликатов? - PullRequest
2 голосов
/ 02 декабря 2009

Я управляю довольно большим сайтом, на котором мои участники добавляют тысячи изображений каждый день. Очевидно, что существует много дубликатов, и мне просто интересно, смогу ли я во время загрузки изображения сгенерировать подпись или хэш изображения, чтобы я мог сохранить его. И каждый раз, когда кто-то загружает изображение, я просто запускаю проверку, если эта подпись уже существует, и выдает ошибку, сообщающую, что это изображение уже существует. Не уверен, что такого рода технология уже существует для asp.net, но я знаю о tineye.com, который уже это делает.

Если вы думаете, что можете помочь, я был бы признателен за ваш вклад.

Kris

Ответы [ 5 ]

2 голосов
/ 02 декабря 2009

Вы используете любой производный HashAlgorithm для генерации хеша из байтового массива файла. Обычно используется MD5, но вы можете заменить это для любого из тех, которые предусмотрены в пространстве имен System.Security.Cryptography. Это работает для любого двоичного файла, а не только для изображений.

Многие сайты предоставляют MD5-хэши при загрузке файлов для проверки правильности загрузки файла. Например, в образе ISO CD / DVD могут отсутствовать байты, когда вы получили все это. После того, как вы загрузили файл, вы генерируете для него хеш и убедитесь, что он совпадает с тем, что на сайте написано. Если все сравнивается, у вас есть точная копия.

Я бы, вероятно, использовал что-то похожее на это:

public static class Helpers
{
    //If you're running .NET 2.0 or lower, remove the 'this' keyword from the
    //method signature as 2.0 doesn't support extension methods.
    static string GetHashString(this byte[] bytes, HashAlgorithm cryptoProvider)
    {
        byte[] hash = cryptoProvider.ComputeHash(bytes);
        return Convert.ToBase64String(hash);
    }
}

Требуется:

using System.Security.Cryptography;

Звоните используя:

byte[] bytes = File.ReadAllBytes("FilePath");
string filehash = bytes.GetHashString(new MD5CryptoServiceProvider());

или если вы работаете в .NET 2.0 или ниже:

string filehash = Helpers.GetHashString(File.ReadAllBytes("FilePath"), new MD5CryptoServiceProvider());

Если вы решили использовать другой метод хеширования вместо MD5 для минимальной вероятности столкновений:

string filehash = bytes.GetHashString(new SHA1CryptoServiceProvider());

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

Вы можете использовать любой другой класс хеширования, просто изменив поставщика услуг, которого вы передаете:

string md5Hash = bytes.GetHashString(new MD5CryptoServiceProvider());
string sha1Hash = bytes.GetHashString(new SHA1CryptoServiceProvider());
string sha256Hash = bytes.GetHashString(new SHA256CryptoServiceProvider());
string sha384Hash = bytes.GetHashString(new SHA384CryptoServiceProvider());
string sha512Hash = bytes.GetHashString(new SHA512CryptoServiceProvider());
1 голос
/ 02 декабря 2009

Как правило, вы просто используете MD5 или подобное для создания хэша. Хотя это не обязательно будет уникальным, поэтому я рекомендую использовать хеш в качестве отправной точки. Определите, соответствует ли изображение каким-либо известным хешам, которые вы сохранили, а затем по отдельности загрузите те, которые ему соответствуют, и проведите полное байтовое сравнение потенциальных коллизий, чтобы убедиться.

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

1 голос
/ 02 декабря 2009

Посмотрите в пространстве имен System.Security.Cryptography. У вас есть выбор из нескольких алгоритмов / реализаций хеширования. Вот пример использования md5, но так как у вас их много, вам может потребоваться что-то большее, например, SHA1:

public byte[] HashImage(Stream imageData)
{
    return new MD5CryptoServiceProvider().ComputeHash(imageData);
} 
0 голосов
/ 02 декабря 2009

Ключевое слово, которое может представлять интерес: перцептивное хеширование .

0 голосов
/ 02 декабря 2009

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

var fileStream = Request.Files[0].InputStream;//the uploaded file
var hasher = System.Security.Cryptography.HMACMD5();
var theHash = hasher.ComputeHash(fileStream);

System.Security.Cryptography

...