Простая (небезопасная) хеш-функция для JavaScript?

Возможный дубликат:
Создайте хэш из строки в Javascript / jQuery

Может ли кто-нибудь предложить простую (т.е. десятки строк кода, а не сотни строк) хеш-функцию, написанную на (совместимом с браузером) JavaScript? В идеале я бы хотел что-то, что при передаче строки в качестве входных данных производит что-то похожее на 32-символьную шестнадцатеричную строку, которая является типичным выводом MD5, SHA1 и т. Д. Это не должно быть криптографически безопасным, просто достаточно устойчивым к столкновениям . (Мой первоначальный вариант использования - это URL-адреса, но я, вероятно, захочу использовать его в других строках в будущем.)


person mjs    schedule 25.05.2011    source источник
comment
Есть ли конкретная причина, по которой вы не хотите использовать sha1? есть множество примеров этого в js   -  person Alex K.    schedule 25.05.2011
comment
Я хочу упаковать это с другим кодом длиной около 50 строк; Я не хочу, чтобы моя хеш-функция была в 10 раз длиннее интересных битов.   -  person mjs    schedule 25.05.2011
comment
Думаю, теперь я понимаю вашу точку зрения. Есть ли причина, по которой вы не можете использовать включение? Вам действительно нужно использовать только один файл?   -  person jsalonen    schedule 25.05.2011
comment
Да, я мог бы, и я готов сделать это в случае необходимости, но я бы предпочел что-то автономное, которое я могу опубликовать как суть на github или аналогичном.   -  person mjs    schedule 25.05.2011
comment
Я хочу создать html-страницу с как можно большим количеством примеров алгоритмов хеширования, которые я могу найти. Мог бы я получить список хеш-функций.   -  person    schedule 13.07.2014
comment
Реализация одноразового хэша Дженкинса window.hashJoaat=function(b){for(var a=0,c=b.length;c--;)a+=b.charCodeAt(c),a+=a<<10,a^=a>>6;a+=a<<3;a^=a>>11;return((a+(a<<15)&4294967295)>>>0).toString(16)};   -  person Orwellophile    schedule 15.10.2016
comment
stringHash32 () является функцией AMPHash32. скорее всего будет достаточно.   -  person mjs    schedule 05.11.2017


Ответы (6)


Я сам в этом не проверял, но вы можете посмотреть это JavaScript-реализация метода Java String.hashCode (). Кажется достаточно коротким.

С помощью этого прототипа вы можете просто вызвать .hashCode() для любой строки, например. "some string".hashCode(), и получить числовой хэш-код (точнее, эквивалент Java), например 1395333309.

String.prototype.hashCode = function() {
    var hash = 0;
    if (this.length == 0) {
        return hash;
    }
    for (var i = 0; i < this.length; i++) {
        var char = this.charCodeAt(i);
        hash = ((hash<<5)-hash)+char;
        hash = hash & hash; // Convert to 32bit integer
    }
    return hash;
}
person Barak    schedule 12.01.2012
comment
SHA1 и MD5 невероятно медленные. Я провел кучу сравнительных тестов, и эта реализация хеширования Java оказалась самой быстрой и с наименьшим количеством коллизий (на относительно однородных данных), чем любые другие, которые я пробовал. Очень коротко и мило. - person Jimbly; 31.05.2012
comment
Очень круто! Единственное, что это загрязняет prototype из String методом, отличным от Ecmascript. Я бы переписал его как отдельную функцию, возможно, поместил бы в вашу библиотеку утилит. - person Husky; 16.10.2012
comment
Другое дело, что он создает глобальную переменную i, потому что забыл ключевое слово var в цикле. Но эти проблемы легко исправить. - person Stijn de Witt; 03.03.2016
comment
@Jimbly Спасибо за тестирование и отчет о результатах. Очень полезно! - person Stijn de Witt; 03.03.2016
comment
Реализация Javascript высечена на камне? Есть ли гарантии, что они не изменят его с помощью будущих версий Javascript? Что произойдет, если они решат улучшить свой алгоритм? Это, вероятно, приведет к хешированию строк в новые значения, что сделает эти значения несовместимыми с любыми значениями, которые вы сохранили или где вы полагаетесь на согласованное хеш-значение. Я бы очень опасался использовать API черного ящика, где у вас нет контроля над исходным кодом. - person AndroidDev; 29.07.2017
comment
Документация для Java String.hashCode(), поскольку ссылка в статье имеет 404: devdocs.io/openjdk~8/java/lang/string#hashCode-- - person waldyrious; 16.08.2017
comment
в SO есть более популярный вопрос с тем же ответом stackoverflow.com/questions/7616461/ - person JLarky; 05.05.2018
comment
Микрооптимизация: удалите блок if (this.length == 0) {return hash}, поскольку он в любом случае избыточен (for выполняется, пока длина положительна, в противном случае по умолчанию возвращается 0). Я что-то упускаю? - person Eugen Mihailescu; 19.04.2019
comment
Поскольку в 2019 году мы пишем javascript по-другому, здесь то же самое, но без привязки его к прототипу String ... `` `function hashCode (source) {let hash = 0; если (source.length == 0) {вернуть хеш; } для (var i = 0; i ‹source.length; i ++) {var char = source.charCodeAt (i); hash = ((hash ‹< 5) -hash) + char; хеш = хэш & хеш; // Преобразование в 32-битное целое число} return hash; } `` ` - person Liron Navon; 07.05.2019
comment
Одной строкой: Array.from(str).reduce((hash, char) => 0 | (31 * hash + char.charCodeAt(0)), 0) (где str - строка) - person Mingwei Samuel; 13.07.2020
comment
Но как это исправить? - person Cybernetic; 03.03.2021
comment
@Cybernetic, хеширование - это односторонний метод, который необратим и не может быть отменен - person Mouneer; 26.03.2021
comment
@Mouneer В общем да, но для владельца ключа это обратимо. Таким образом, у держателя ключей должна быть возможность отменить операцию. Например, если вы использовали это для хеширования пароля на сервере. - person Cybernetic; 26.03.2021
comment
@Cybernetic, вот как люди используют их, например, с паролями, но это нельзя назвать Undo, поскольку это означает, что вы можете вернуть исходную хешированную строку, и это в основном неприменимо - person Mouneer; 26.03.2021
comment
Одна коллизия этого алгоритма: FB & Ea - person Shubanker; 18.05.2021

Есть много реализаций хеш-функций, написанных на JS. Например:

Если вам не нужна безопасность, вы также можете использовать base64, который не является хеш-функцией, не имеет фиксированного вывода и может быть просто декодирован пользователем, но выглядит более легким и может использоваться для скрытых значений: http://www.webtoolkit.info/javascript-base64.html

person silex    schedule 25.05.2011
comment
кодировка строки base64 более или менее имеет ту же длину, что и исходная строка; Я бы хотел что-нибудь покороче, например, хэш. - person mjs; 25.05.2011
comment
base64 даже длиннее, чем ввод, кстати, чтобы уточнить, что немного больше. - person My1; 11.04.2017

Ознакомьтесь с этими реализациями

person Stefan Filip    schedule 25.05.2011
comment
OP спрашивает о небезопасных, некриптографических хэшах, MD5 и SHA-1 - это криптографические хэши, которые должны были быть безопасными. - person bryc; 03.02.2020

Простой хешер объекта:

(function () {
    Number.prototype.toHex = function () {
        var ret = ((this<0?0x8:0)+((this >> 28) & 0x7)).toString(16) + (this & 0xfffffff).toString(16);
        while (ret.length < 8) ret = '0'+ret;
        return ret;
    };
    Object.hashCode = function hashCode(o, l) {
        l = l || 2;
        var i, c, r = [];
        for (i=0; i<l; i++)
            r.push(i*268803292);
        function stringify(o) {
            var i,r;
            if (o === null) return 'n';
            if (o === true) return 't';
            if (o === false) return 'f';
            if (o instanceof Date) return 'd:'+(0+o);
            i=typeof o;
            if (i === 'string') return 's:'+o.replace(/([\\\\;])/g,'\\$1');
            if (i === 'number') return 'n:'+o;
            if (o instanceof Function) return 'm:'+o.toString().replace(/([\\\\;])/g,'\\$1');
            if (o instanceof Array) {
                r=[];
                for (i=0; i<o.length; i++) 
                    r.push(stringify(o[i]));
                return 'a:'+r.join(';');
            }
            r=[];
            for (i in o) {
                r.push(i+':'+stringify(o[i]))
            }
            return 'o:'+r.join(';');
        }
        o = stringify(o);
        for (i=0; i<o.length; i++) {
            for (c=0; c<r.length; c++) {
                r[c] = (r[c] << 13)-(r[c] >> 19);
                r[c] += o.charCodeAt(i) << (r[c] % 24);
                r[c] = r[c] & r[c];
            }
        }
        for (i=0; i<r.length; i++) {
            r[i] = r[i].toHex();
        }
        return r.join('');
    }
}());

Основой здесь является стрингификатор, который просто преобразует любой объект в уникальную строку. Затем hashCode проходит по объекту, хешируя вместе символы строкового объекта.

Для дополнительных точек экспортируйте стрингификатор и создайте синтаксический анализатор.

person Fordi    schedule 29.03.2012
comment
какая-либо причина не использовать JSON.stringify? - person Jehan; 09.08.2014
comment
Март 2012 г. В то время я не мог предположить, что JSON правильно работает в определенном браузере. Кроме того, JSON удаляет функции, поэтому их нельзя будет хешировать с использованием JSON в качестве стрингификатора. - person Fordi; 15.08.2014

Ознакомьтесь с этой реализацией MD5 для JavaScript. Его лицензия BSD и очень проста в использовании. Пример:

md5 = hex_md5("message to digest")
person jsalonen    schedule 25.05.2011
comment
Я нашел это, и это сработает, но я надеялся на что-то меньшее и более простое. Кроме того, не является ли дайджест сообщения результатом hex_md5(message)? - person mjs; 25.05.2011
comment
Да, дайджест - это результат, параметр - это сообщение, которое вы хотите дайджестировать, следовательно, сообщение от до дайджеста. - person jsalonen; 25.05.2011
comment
Но в любом случае, каким образом вы хотите, чтобы реализация была проще? Эта реализация представляет собой простой файл JavaScript с менее чем 400 строками. Вам просто нужна одна функция или что? - person jsalonen; 25.05.2011
comment
Теперь это имеет для меня больше смысла; раньше у вас было что-то вроде hex_md5("message_digest") = "fb6cecc85a100197ae3ad68d1f9f2886", верно? (Не могу найти редакцию вашего ответа.) - person mjs; 25.05.2011
comment
Да, я поправил. Но можете ли вы подробнее остановиться на проблеме простоты: каким образом вы хотите более простую библиотеку? - person jsalonen; 25.05.2011

person    schedule
comment
Этот сценарий засоряет глобальную область видимости следующими переменными: j, k, a. Причина этого в том, что они не являются частью оператора var, а просто частью выражения, которое оценивается как var i. Вместо этого используйте var i, j, k, a; i = j = k = a = 0;. - person Niet the Dark Absol; 25.05.2012
comment
Да, JS плохо написан, но, похоже, он напрямую отвечает на вопрос OP и предоставляет пример кода. Спасибо! - person mkoistinen; 30.11.2013