Генерация хэша строки (1Cv8)

Материал из КинтВики
Версия от 09:52, 7 октября 2010; Павел Лазарев (обсуждение | вклад) (Новая страница: «Категория:Примеры кода 1С __TOC__ Некоторые реализации: ==Хэш строки== <source lang=1c> Функция стр...»)
(разн.) ← Предыдущая | Текущая версия (разн.) | Следующая → (разн.)
Перейти к: навигация, поиск


Некоторые реализации:

Хэш строки

Функция стрПолучитьХэш(Знач стрСтрока) Экспорт
	Сумма1 = 0;
	Сумма2 = 1;
	ДлинаСтроки = СтрДлина(стрСтрока);
	Для ъ = 1 По ДлинаСтроки Цикл
		//КодСимвола = КодСимвола(стрСтрока, ДлинаСтроки);
		КодСимвола = КодСимвола(Сред(стрСтрока, ДлинаСтроки, 1));
		Сумма1 = Сумма1+КодСимвола*ДлинаСтроки;
		Сумма2 = Сумма2*КодСимвола;
		ДлинаСтроки = ДлинаСтроки-1;
	КонецЦикла;
	ПростоеЧисло = 165684646484683;
	Если Сумма1 = 0 Тогда Сумма1 = ПростоеЧисло; КонецЕсли;
	КодСимвола = Сумма1*Сумма2*ПростоеЧисло;
	Возврат Лев(Формат(КодСимвола,"ЧГ = "), 32);
КонецФункции

Хэш md5

Источник: http://1c.proclub.ru/modules/mydownloads/personal.php?cid=5&lid=5287

// Обработка рассчитывает Хэш код текста по алгоритму MD5
// Весь алгоритм реализован на языке 1С и не требует никаких дополнительных внешних компонент.
// Можно вводить текст интерактивно или передавать из другой обработки
//
// При запуске из другой обработки передается СписокЗначений с параметрами:
//				"Строка"-собственно строка текста или объект типа "Текст"
// Возврат		"ХэшКод"-собственно 32 символа Хэш кода
//
//      Текст можно передавать поблочно
//		При передаче текста по блокам 
//		ДЛИНА БЛОКА, КРОМЕ ПОСЛЕДНЕГО, ДОЛЖНА БЫТЬ КРАТНА 64 БАЙТАМ!
//		дополнительно задаются
//				"Длина" - равна -1(минус 1) для всех блоков кроме последнего
//						  для последнего блока длина всего текста в байтах
//	            "ХэшКод" - Хэш код предыдущего блока (для первого блока не задается)
//
Перем A,B,C,D; // Составляющие ХэшКода (по 4 байта или 8 символов в 16с/с) 
Перем A_[32],B_[32],C_[32],D_[32];
Перем EAX[32],EBX[32],ECX[32],EDX[32]; // Регистры
Перем S11,S12,S13,S14,S21,S22,S23,S24,S31,S32,S33,S34,S41,S42,S43,S44;
Перем M[64];
Перем Степень[32];
Перем Stepen31; //2 в степени 31
Перем Stepen32; //2 в степени 32
Перем X[16];    //Текстовый массив в числовом коде
//Перем Степень[32]; // Массив степеней
Процедура Расчет(Стр,Длина=0) Далее
//*******************************************
Процедура _XOR(П1[],П2[],Итог[])
	Для инд=1 По 32 Цикл
		Если П1[инд] <> П2[инд] Тогда
			Итог[инд]=1;
		Иначе
			Итог[инд]=0;
		КонецЕсли;
	КонецЦикла;
КонецПроцедуры
//*******************************************
Процедура _AND(П1[],П2[],Итог[])
	Для инд=1 По 32 Цикл
		Если (П1[инд]=1) И (П2[инд]=1) Тогда
			Итог[инд]=1;
		Иначе
			Итог[инд]=0;
		КонецЕсли;
	КонецЦикла;
КонецПроцедуры
//*******************************************
Процедура _OR(П1[],П2[],Итог[])
	Для инд=1 По 32 Цикл
		Если (П1[инд]=1) ИЛИ (П2[инд]=1) Тогда
			Итог[инд]=1;
		Иначе
			Итог[инд]=0;
		КонецЕсли;
	КонецЦикла;
КонецПроцедуры
//*******************************************
Процедура _ADD(П1[],П2[],Итог[])
	Добавка=0;
	Для инд=1 По 32 Цикл
		Итог[инд]=П1[инд]+П2[инд]+Добавка;
		Если Итог[инд]=2 Тогда
			Итог[инд]=0;
			Добавка=1;
		ИначеЕсли Итог[инд]=3 Тогда
			Итог[инд]=1;
			Добавка=1;
		Иначе
			Добавка=0;
		КонецЕсли;
	КонецЦикла;
КонецПроцедуры
//*******************************************
Процедура _NOT(П1[],Итог[])
	Для инд=1 По 32 Цикл
		Если П1[инд]=0 Тогда
			Итог[инд]=1;
		Иначе
			Итог[инд]=0;	
		КонецЕсли;
	КонецЦикла;
КонецПроцедуры
//*******************************************
Процедура _ROL(П1[],П2,Итог[])
	Для инд=1 По 32 Цикл
		инд1=инд+П2;
		Если инд1 > 32 Тогда
			инд1=инд1-32;
		КонецЕсли;
		Итог[инд1]=П1[инд];
	КонецЦикла;
КонецПроцедуры
//*******************************************
Процедура FF(a[],b[],c[],d[],X,s,t)
	_and(b,c,EAX);
	_not(b,EBX);
	_and(EBX,d,ECX);
	_or(EAX,ECX,EBX);
	
	X1=X+t;
	Если X1 >= Stepen32 Тогда
		X1=X1-Stepen32;
	КонецЕсли;
	Для инд=1 По 32 Цикл
		инд1=32-инд+1;
		Степ=Степень[инд1];
		Если X1 >= Степ Тогда
			X1=X1-Степ;
			EDX[инд1]=1;
		Иначе
			EDX[инд1]=0;
		КонецЕсли;
	КонецЦикла;
	_ADD(EBX,a,ECX);
	_ADD(ECX,EDX,EAX);
	
	_rol(EAX,s,ECX);
	_ADD(ECX,b,a);
КонецПроцедуры
//*******************************************
Процедура GG(a[],b[],c[],d[],X,s,t)
	_and(b,d,EAX);
	_not(d,EDX);
	_and(EDX,c,ECX);
	_or(EAX,ECX,EBX);
	
	X1=X+t;
	Если X1 >= Stepen32 Тогда
		X1=X1-Stepen32;
	КонецЕсли;
	Для инд=1 По 32 Цикл
		инд1=32-инд+1;
		Степ=Степень[инд1];
		Если X1 >= Степ Тогда
			X1=X1-Степ;
			EDX[инд1]=1;
		Иначе
			EDX[инд1]=0;
		КонецЕсли;
	КонецЦикла;
	_ADD(EBX,a,ECX);
	_ADD(ECX,EDX,EAX);
	
	_rol(EAX,s,ECX);
	_ADD(ECX,b,a);
КонецПроцедуры
//*******************************************
Процедура HH(a[],b[],c[],d[],X,s,t)
	_xor(b,c,EAX);
	_xor(EAX,d,EBX);
	
	X1=X+t;
	Если X1 >= Stepen32 Тогда
		X1=X1-Stepen32;
	КонецЕсли;
	Для инд=1 По 32 Цикл
		инд1=32-инд+1;
		Степ=Степень[инд1];
		Если X1 >= Степ Тогда
			X1=X1-Степ;
			EDX[инд1]=1;
		Иначе
			EDX[инд1]=0;
		КонецЕсли;
	КонецЦикла;
	_ADD(EBX,a,ECX);
	_ADD(ECX,EDX,EAX);
	_rol(EAX,s,ECX);
	_ADD(ECX,b,a);
	
КонецПроцедуры
//*******************************************
Процедура II(a[],b[],c[],d[],X,s,t)
	_not(d,EAX);
	_or(EAX,b,ECX);
	_xor(ECX,c,EBX);
	
	X1=X+t;
	Если X1 >= Stepen32 Тогда
		X1=X1-Stepen32;
	КонецЕсли;
	Для инд=1 По 32 Цикл
		инд1=32-инд+1;
		Степ=Степень[инд1];
		Если X1 >= Степ Тогда
			X1=X1-Степ;
			EDX[инд1]=1;
		Иначе
			EDX[инд1]=0;
		КонецЕсли;
	КонецЦикла;
	_ADD(EBX,a,ECX);
	_ADD(ECX,EDX,EAX);
	_rol(EAX,s,ECX);
	_ADD(ECX,b,a);
	
КонецПроцедуры
//******************************************************************************
Функция Из_16_В_Число(Знач Значение)
    Результат=0;
	Значение=ВРег(Значение);
	М=1;
    Для Х=1 По 4 Цикл
    	Результат=Результат+(Найти("0123456789ABCDEF",Сред(Значение,2*Х,1))-1)*М;
		М=М*16;
    	Результат=Результат+(Найти("0123456789ABCDEF",Сред(Значение,2*Х-1,1))-1)*М;
		М=М*16;
    КонецЦикла;
    Возврат Результат;
КонецФункции
//*******************************************
Функция Из_Число_В_16(Знач Значение)
	Результат="";
	Для инд=1 По 4 Цикл
		Остат=Значение%16+1;
		Результат1=Сред("0123456789ABCDEF",Остат,1);
		Значение=Цел(Значение/16);
		Остат=Значение%16+1;
		Результат2=Сред("0123456789ABCDEF",Остат,1);
		Значение=Цел(Значение/16);
		Результат=Результат+Результат2+Результат1;
	КонецЦикла;
    Возврат Результат;
КонецФункции
//*******************************************
Процедура MD5Hash()
Перем A1[32],B1[32],C1[32],D1[32];
	Для i=1 По 32 Цикл
		A1[i]	=	A_[i];
		B1[i]	=	B_[i];
		C1[i]	=	C_[i];
		D1[i]	=	D_[i];
	КонецЦикла;
	
// --------------------------------------------------------------------------
// Round 1.
// --------------------------------------------------------------------------
                        FF      (a_,b_,c_,d_, X[1], S11, 3614090360)  ;// Step 1
                        FF      (d_,a_,b_,c_, X[2], S12, 3905402710)  ;// Step 2
                        FF      (c_,d_,a_,b_, X[3], S13,  606105819)  ;// Step 3
                        FF      (b_,c_,d_,a_, X[4], S14, 3250441966)  ;// Step 4
                        FF      (a_,b_,c_,d_, X[5], S11, 4118548399)  ;// Step 5
                        FF      (d_,a_,b_,c_, X[6], S12, 1200080426)  ;// Step 6
                        FF      (c_,d_,a_,b_, X[7], S13, 2821735955)  ;// Step 7
                        FF      (b_,c_,d_,a_, X[8], S14, 4249261313)  ;// Step 8
                        FF      (a_,b_,c_,d_, X[9], S11, 1770035416)  ;// Step 9
                        FF      (d_,a_,b_,c_, X[10],S12, 2336552879)  ;// Step 10
                        FF      (c_,d_,a_,b_, X[11],S13, 4294925233)  ;// Step 11
                        FF      (b_,c_,d_,a_, X[12],S14, 2304563134)  ;// Step 12
                        FF      (a_,b_,c_,d_, X[13],S11, 1804603682)  ;// Step 13
                        FF      (d_,a_,b_,c_, X[14],S12, 4254626195)  ;// Step 14
                        FF      (c_,d_,a_,b_, X[15],S13, 2792965006)  ;// Step 15
                        FF      (b_,c_,d_,a_, X[16],S14, 1236535329)  ;// Step 16
// --------------------------------------------------------------------------
// Round 2.
// --------------------------------------------------------------------------
                        GG      (a_,b_,c_,d_, X[2], S21, 4129170786)  ;// Step 17
                        GG      (d_,a_,b_,c_, X[7], S22, 3225465664)  ;// Step 18
                        GG      (c_,d_,a_,b_, X[12],S23,  643717713)  ;// Step 19
                        GG      (b_,c_,d_,a_, X[1], S24, 3921069994)  ;// Step 20
                        GG      (a_,b_,c_,d_, X[6], S21, 3593408605)  ;// Step 21
                        GG      (d_,a_,b_,c_, X[11],S22,   38016083)  ;// Step 22 
                        GG      (c_,d_,a_,b_, X[16],S23, 3634488961)  ;// Step 23
                        GG      (b_,c_,d_,a_, X[5], S24, 3889429448)  ;// Step 24
                        GG      (a_,b_,c_,d_, X[10],S21,  568446438)  ;// Step 25
                        GG      (d_,a_,b_,c_, X[15],S22, 3275163606)  ;// Step 26
                        GG      (c_,d_,a_,b_, X[4], S23, 4107603335)  ;// Step 27
                        GG      (b_,c_,d_,a_, X[9], S24, 1163531501)  ;// Step 28
                        GG      (a_,b_,c_,d_, X[14],S21, 2850285829)  ;// Step 29
                        GG      (d_,a_,b_,c_, X[3], S22, 4243563512)  ;// Step 30
                        GG      (c_,d_,a_,b_, X[8], S23, 1735328473)  ;// Step 31
                        GG      (b_,c_,d_,a_, X[13],S24, 2368359562)  ;// Step 32
// --------------------------------------------------------------------------
// Round 3.
// --------------------------------------------------------------------------
                        HH      (a_,b_,c_,d_, X[6], S31, 4294588738)  ;// Step 33
                        HH      (d_,a_,b_,c_, X[9], S32, 2272392833)  ;// Step 34
                        HH      (c_,d_,a_,b_, X[12],S33, 1839030562)  ;// Step 35
                        HH      (b_,c_,d_,a_, X[15],S34, 4259657740)  ;// Step 36
                        HH      (a_,b_,c_,d_, X[2], S31, 2763975236)  ;// Step 37
                        HH      (d_,a_,b_,c_, X[5], S32, 1272893353)  ;// Step 38
                        HH      (c_,d_,a_,b_, X[8], S33, 4139469664)  ;// Step 39
                        HH      (b_,c_,d_,a_, X[11],S34, 3200236656)  ;// Step 40
                        HH      (a_,b_,c_,d_, X[14],S31,  681279174)  ;// Step 41
                        HH      (d_,a_,b_,c_, X[1], S32, 3936430074)  ;// Step 42
                        HH      (c_,d_,a_,b_, X[4], S33, 3572445317)  ;// Step 43
                        HH      (b_,c_,d_,a_, X[7], S34,   76029189)  ;// Step 44
                        HH      (a_,b_,c_,d_, X[10],S31, 3654602809)  ;// Step 45
                        HH      (d_,a_,b_,c_, X[13],S32, 3873151461)  ;// Step 46
                        HH      (c_,d_,a_,b_, X[16],S33,  530742520)  ;// Step 47
                        HH      (b_,c_,d_,a_, X[3], S34, 3299628645)  ;// Step 48
// --------------------------------------------------------------------------
// Round 4.
// --------------------------------------------------------------------------
                        II      (a_,b_,c_,d_, X[1], S41, 4096336452)  ;// Step 49
                        II      (d_,a_,b_,c_, X[8], S42, 1126891415)  ;// Step 50
                        II      (c_,d_,a_,b_, X[15],S43, 2878612391)  ;// Step 51
                        II      (b_,c_,d_,a_, X[6], S44, 4237533241)  ;// Step 52
                        II      (a_,b_,c_,d_, X[13],S41, 1700485571)  ;// Step 53
                        II      (d_,a_,b_,c_, X[4], S42, 2399980690)  ;// Step 54
                        II      (c_,d_,a_,b_, X[11],S43, 4293915773)  ;// Step 55
                        II      (b_,c_,d_,a_, X[2], S44, 2240044497)  ;// Step 56
                        II      (a_,b_,c_,d_, X[9], S41, 1873313359)  ;// Step 57
                        II      (d_,a_,b_,c_, X[16],S42, 4264355552)  ;// Step 58
                        II      (c_,d_,a_,b_, X[7], S43, 2734768916)  ;// Step 59
                        II      (b_,c_,d_,a_, X[14],S44, 1309151649)  ;// Step 60
                        II      (a_,b_,c_,d_, X[5], S41, 4149444226)  ;// Step 61
                        II      (d_,a_,b_,c_, X[12],S42, 3174756917)  ;// Step 62
                        II      (c_,d_,a_,b_, X[3], S43,  718787259)  ;// Step 63
                        II      (b_,c_,d_,a_, X[10],S44, 3951481745)  ;// Step 64
// --------------------------------------------------------------------------
    
	_ADD(A_,A1,A_);
	_ADD(B_,B1,B_);
	_ADD(C_,C1,C_);
	_ADD(D_,D1,D_);
КонецПроцедуры
//*******************************************
Процедура ПриОткрытии()
	Если ТипЗначенияСтр(Форма.Параметр)="СписокЗначений" Тогда
		СтатусВозврата(0);
		Стр=Форма.Параметр.Получить("Строка");
		Если ПустоеЗначение(Форма.Параметр.Получить("ХэшКод")) <> 1 Тогда
			Код=Форма.Параметр.Получить("ХэшКод");
			A	=	Из_16_В_Число(Лев(Код,8));
			B	=	Из_16_В_Число(Сред(Код,9,8));
			C	=	Из_16_В_Число(Сред(Код,17,8));
			D	=	Из_16_В_Число(Прав(Код,8));
		Иначе
			A	=	1732584193;
			B	=	4023233417;
			C	=	2562383102;
			D	=	271733878;
		КонецЕсли;
		Длина=Число(Форма.Параметр.Получить("Длина"));
	
		Для i=1 По 32 Цикл
			i1=32-i+1;
			Степ=Степень[i1];
			Если A >= Степ Тогда
				A=A-Степ;
				A_[i1]=1;
			Иначе
				A_[i1]=0;
			КонецЕсли;
			Если B >= Степ Тогда
				B=B-Степ;
				B_[i1]=1;
			Иначе
				B_[i1]=0;
			КонецЕсли;
			Если C >= Степ Тогда
				C=C-Степ;
				C_[i1]=1;
			Иначе
				C_[i1]=0;
			КонецЕсли;
			Если D >= Степ Тогда
				D=D-Степ;
				D_[i1]=1;
			Иначе
				D_[i1]=0;
			КонецЕсли;
		КонецЦикла;

		Если ТипЗначенияСтр(Стр)="Текст" Тогда
			Текст=Стр;
			Стр="";
			Длина=0;
			Для инд=1 По Текст.КоличествоСтрок() Цикл
				Стр1=Текст.ПолучитьСтроку(инд);
				Стр=Стр+Стр1;
				Пока СтрДлина(Стр) >= 8192 Цикл
					Расчет(Лев(Стр,8192),-1);
					Длина=Длина+8192;
					Стр=Сред(Стр,8193);
				КонецЦикла;
			КонецЦикла;
			Длина=Длина+СтрДлина(Стр);
		КонецЕсли;
		
		Расчет(Стр,Длина);
		
		A	=	0;
		B	=	0;
		C	=	0;
		D	=	0;
		Для i=1 По 32 Цикл
			Степ=Степень[i];
			Если A_[i]=1 Тогда
				A=A+Степ;	
			КонецЕсли;
			Если B_[i]=1 Тогда
				B=B+Степ;	
			КонецЕсли;
			Если C_[i]=1 Тогда
				C=C+Степ;	
			КонецЕсли;
			Если D_[i]=1 Тогда
				D=D+Степ;	
			КонецЕсли;
		КонецЦикла;
		
		ХэшКод=Из_Число_В_16(A)+Из_Число_В_16(B)+Из_Число_В_16(C)+Из_Число_В_16(D);
		Форма.Параметр.Установить("ХэшКод",ХэшКод);
		Возврат;
	КонецЕсли;
КонецПроцедуры
//*******************************************
Процедура Расчет(Стр,Длина=0)
	Перем Мас[64];
	
	Если Длина=0 Тогда
		Длина=СтрДлина(Стр);
	КонецЕсли;
	
	// Определение Хэш кодов 64 байтных блоков
	ДлСтр=СтрДлина(Стр);
	Пока ДлСтр >= 64 Цикл
		i1=0;
		Для i = 1 По 16 Цикл
			X[i]=КодСимв(Сред(Стр,i1+1,1))+
			КодСимв(Сред(Стр,i1+2,1))*256+
			КодСимв(Сред(Стр,i1+3,1))*65536+
			КодСимв(Сред(Стр,i1+4,1))*16777216;
			i1=i1+4;
		КонецЦикла;
		MD5Hash();
		Стр=Сред(Стр,65);
		ДлСтр=СтрДлина(Стр);
	КонецЦикла;
	
	// Финал - определение Хэш кода последнего блока
	Если Длина <> -1 Тогда  // Если Длина=-1 то значит это не последний блок
		ДлинаБит=Длина*8;
		Для i = 1 По ДлСтр Цикл 
			Мас[i]=КодСимв(Сред(Стр,i,1));
		КонецЦикла;
		Мас[ДлСтр+1]=128;
		Длина=ДлСтр+1;
		
		// В последнем блоке нет свободных 8 байт для длины
		// Дополняем блок до 64 байт
		Если Длина > 56 Тогда
			Для i = Длина+1 По 64 Цикл
				Мас[i]=0;
			КонецЦикла; 
			i1=0;
			Для i = 1 По 16 Цикл
				X[i]=Мас[i1+1]+
				Мас[i1+2]*256+
				Мас[i1+3]*65536+
				Мас[i1+4]*16777216;
				i1=i1+4;
			КонецЦикла;
			MD5Hash();
			Длина=0;
		КонецЕсли;
		
		// Дополняем блок до 56 байт и заносим длину в битах
		Для i = Длина+1 По 56 Цикл
			Мас[i]=0;
		КонецЦикла;
		i1=0;
		Для i = 1 По 14 Цикл
			X[i]=Мас[i1+1]+
			Мас[i1+2]*256+
			Мас[i1+3]*65536+
			Мас[i1+4]*16777216;
			i1=i1+4;
		КонецЦикла;
		X[15]=ДлинаБит%Stepen32;
		X[16]=Цел(ДлинаБит/Stepen32);
		MD5Hash();
	КонецЕсли;
	
КонецПроцедуры
//*******************************************
Процедура Сформировать()
	A	=	1732584193;
	B	=	4023233417;
	C	=	2562383102;
	D	=	271733878;
	Для i=1 По 32 Цикл
		i1=32-i+1;
		Степ=Степень[i1];
		Если A >= Степ Тогда
			A=A-Степ;
			A_[i1]=1;
		Иначе
			A_[i1]=0;
		КонецЕсли;
		Если B >= Степ Тогда
			B=B-Степ;
			B_[i1]=1;
		Иначе
			B_[i1]=0;
		КонецЕсли;
		Если C >= Степ Тогда
			C=C-Степ;
			C_[i1]=1;
		Иначе
			C_[i1]=0;
		КонецЕсли;
		Если D >= Степ Тогда
			D=D-Степ;
			D_[i1]=1;
		Иначе
			D_[i1]=0;
		КонецЕсли;
	КонецЦикла;
	Расчет(СтрокаХэш);
	
	A	=	0;
	B	=	0;
	C	=	0;
	D	=	0;
	Для i=1 По 32 Цикл
		Степ=Степень[i];
		Если A_[i]=1 Тогда
			A=A+Степ;	
		КонецЕсли;
		Если B_[i]=1 Тогда
			B=B+Степ;	
		КонецЕсли;
		Если C_[i]=1 Тогда
			C=C+Степ;	
		КонецЕсли;
		Если D_[i]=1 Тогда
			D=D+Степ;	
		КонецЕсли;
	КонецЦикла;
		
	ХэшКод=Из_Число_В_16(A)+Из_Число_В_16(B)+Из_Число_В_16(C)+Из_Число_В_16(D);
	Форма.ХэшКод.Заголовок(ХэшКод);
КонецПроцедуры
//*******************************************
S11 =  7;
S12 = 12;
S13 = 17;
S14 = 22;
S21 =  5;
S22 =  9;
S23 = 14;
S24 = 20;
S31 =  4;
S32 = 11;
S33 = 16;
S34 = 23;
S41 =  6;
S42 = 10;
S43 = 15;
S44 = 21;

Степень[1]=1;
Для инд=2 По 32 Цикл
	Степень[инд]=Степень[инд-1]*2;
КонецЦикла;
Stepen31=Степень[32];
Stepen32=Stepen31*2;

Хэш через объект capicom

objHashedData = Новый COMОбъект("CAPICOM.HashedData");
objHashedData.Algorithm = 3;
objHashedData.Hash(НужнаяСтрока);
Сообщить(objHashedData.Value);