На эту публикацию вдохновили три момента:
- В 1С алгоритм шифрования AES можно использовать только через zip файл, что показалось неудобным и не совсем правильным с точки зрения безопасности.
- Публикация № 151246, где нашел понятный и простой шаблон для создания com библиотеки C# для работы с 1С. "Как написать COM-объект для 1С на Visual Studio C# 2008"
- Шифровать без использования громоздкой системы сертификатов (если нет в этом необходимости)
Тип данных входные и выходные: только строка и cтрока Base64, массив байтов в параметрах не используется. В тестовых целях константы можно заменить на реквизиты.
Константы:
1. UnlockKey (СоленыйХеш) - не хранится, он расчитывается из мПароля и соли.
2. EncKey (основной ключ шифрования) - шифрован ключом PubKey
3. PubKey - публичный RSA
4. PrivatKey (приватный RSA) - шифрован UnlockKey
// ********************
// Как работать с библиотекой:
// AES ШифроватьКонтрольнуюФразуСохранитьКлюч
&НаКлиенте
Процедура ШифроватьКонтрольнуюФразуСохранитьКлюч(Команда)
Если Не ЗначениеЗаполнено(pass) Тогда // pass - строка
Сообщить("контрольное слово пустое !!");
возврат;
КонецЕсли;
ВремяСтарт=ТекущаяУниверсальнаяДатаВМиллисекундах();
ШифроватьКонтрольнуюФразуСохранитьКлючНаСервере();
Сообщить ("Шифровка контр фразы, потрачено млсек: "+ (ТекущаяУниверсальнаяДатаВМиллисекундах()-ВремяСтарт));
КонецПроцедуры
// AES ШифроватьКонтрольнуюФразуСохранитьКлючНаСервере
&НаСервере
Процедура ШифроватьКонтрольнуюФразуСохранитьКлючНаСервере()
МойОбъект = Новый COMОбъект("Crypto1C.MyClass");
Ответ_Com=МойОбъект.EncryptStringToBytes_Aes(pass); // генерим Key,IV сохраняем, нужны для шифрования данных в хранилище
если НЕ Ответ_Com.Success Тогда
Сообщить(Ответ_Com.Message);
Возврат;
КонецЕсли;
ШифрованнаяСтрока=Ответ_Com.Encrypted_64;
Key=Ответ_Com.Key_64 ; // строка base64
IV=Ответ_Com.IV_64 ; // строка base64
ДлинаКлючаРазмер= ПолучитьДвоичныеДанныеИзBase64Строки(Key).Размер();
ДлинаВектораРазмер= ПолучитьДвоичныеДанныеИзBase64Строки(IV).Размер();
ДлинаШифрованнаяСтрокаРазмер= ПолучитьДвоичныеДанныеИзBase64Строки(ШифрованнаяСтрока).Размер();
ЖурналЛогов.ДобавитьСтроку("ДлинаКлюча (EncKey) байт/длина:" + ДлинаКлючаРазмер+"/"+СтрДлина(Key));
ЖурналЛогов.ДобавитьСтроку("ДлинаВектора (IV) байт/длина: "+ДлинаВектораРазмер+"/"+СтрДлина(IV));
ЖурналЛогов.ДобавитьСтроку("Контрольная фраза шифрованная AES байт/длина: "+ДлинаШифрованнаяСтрокаРазмер+"/"+СтрДлина(ШифрованнаяСтрока));
ЖурналЛогов.ДобавитьСтроку("**************************************");
МойОбъект = Неопределено;
КонецПроцедуры
// AES Шифровать PrivKey
&НаСервере
Процедура ШифроватьPrivKeyСохранитьВБазе()
МойОбъект = Новый COMОбъект("Crypto1C.MyClass");
Ответ_Com=МойОбъект.EncryptStringToBytes_Aes(ПубличныйИПриватныйКлюч,Key,IV); ПубличныйИПриватныйКлюч = строка
если Ответ_Com.Success Тогда
ШифрованнаяСтрока=Ответ_Com.Data; // строка Base64
КонецЕсли;
ДлинаКлючаРазмер= ПолучитьДвоичныеДанныеИзBase64Строки(Key).Размер();
ДлинаВектораРазмер= ПолучитьДвоичныеДанныеИзBase64Строки(IV).Размер();
ДлинаШифрованнаяСтрокаРазмер= ПолучитьДвоичныеДанныеИзBase64Строки(ШифрованнаяСтрока).Размер();
ЖурналЛогов.ДобавитьСтроку("ДлинаКлюча байт/длина:" + ДлинаКлючаРазмер+"/"+СтрДлина(Key));
ЖурналЛогов.ДобавитьСтроку("ДлинаВектора байт/длина: "+ДлинаВектораРазмер+"/"+СтрДлина(IV));
ЖурналЛогов.ДобавитьСтроку("ДлинаШифрованнаяСтрока байт/длина: "+ДлинаШифрованнаяСтрокаРазмер+"/"+СтрДлина(ШифрованнаяСтрока));
МойОбъект = Неопределено;
КонецПроцедуры
// AES дешифровать
&НаКлиенте
Процедура Расшифровать(Команда)
РасшифроватьНаСервере();
КонецПроцедуры
// AES дешифровать
&НаСервере
Процедура РасшифроватьНаСервере()
МойОбъект = Новый COMОбъект("Crypto1C.MyClass");
Ответ_Com=МойОбъект.DecryptStringFromBytes_Aes(ШифрованнаяСтрока,Key,IV);
если Ответ_Com.Success Тогда
ДешифрованнаяСтрока=Ответ_Com.DecryptedString ; // строка
КонецЕсли;
ЖурналЛогов.ДобавитьСтроку(ДешифрованнаяСтрока);
МойОбъект = Неопределено;
КонецПроцедуры
// PBKDF2
&НаКлиенте
Процедура PBKDF2_ПолучитьКлючИСохранитьСоль(Команда)
Если Не ЗначениеЗаполнено(mPwd) Тогда // mPwd - строка
Сообщить("mPwd пустое !!");
возврат;
КонецЕсли;
ВремяСтарт=ТекущаяУниверсальнаяДатаВМиллисекундах();
PBKDF2_ПолучитьКлючИСохранитьСольНаСервере();
Сообщить ("ХЕШ потрачено млсек: "+ (ТекущаяУниверсальнаяДатаВМиллисекундах()-ВремяСтарт));
КонецПроцедуры
// PBKDF2
&НаСервере
Процедура PBKDF2_ПолучитьКлючИСохранитьСольНаСервере()
// PBKDF2(string pwd, int myIterations, string AlgName, out string salt_64)
// new HashAlgorithmName(AlgName)
//Asymmetric algorithms implemented using other technologies:
//Must recognize at least "MD5", "SHA1", "SHA256", "SHA384", and "SHA512".
//Should recognize additional CNG identifiers for any additional hash algorithms that they support.
//Due to collision problems with MD5 and SHA1, Microsoft recommends a security model based on SHA256 or better.
МойОбъект = Новый COMОбъект("Crypto1C.MyClass");
МойОбъектОтвет=МойОбъект.PBKDF2(mPwd, 100000, "SHA512"); //PBKDF2(mPwd, кол-во итерации, алгортим хеширования)
UnlockKey=МойОбъектОтвет.HashPwdSalt_64; // строка Base64
Соль=МойОбъектОтвет.Salt_64;
ЖурналЛогов.ДобавитьСтроку("Соль: "+Соль);
ЖурналЛогов.ДобавитьСтроку("UnlockKey: "+UnlockKey); // нужен для AES шифрования PrivKey
UnlockKeyРазмер= ПолучитьДвоичныеДанныеИзBase64Строки(UnlockKey).Размер();
СольРазмер= ПолучитьДвоичныеДанныеИзBase64Строки(Соль).Размер();
ЖурналЛогов.ДобавитьСтроку("Соль байт/длина: "+СольРазмер+"/"+СтрДлина(Соль));
ЖурналЛогов.ДобавитьСтроку("UnlockKey (ключ для AES) байт/длина:" + UnlockKeyРазмер+"/"+СтрДлина(UnlockKey));
ЖурналЛогов.ДобавитьСтроку("**************************************");
МойОбъект = Неопределено;
КонецПроцедуры
&НаКлиенте
Процедура ОчиститьЖурнал(Команда)
ЖурналЛогов.Очистить();
КонецПроцедуры
// Получить ключи RSA
&НаСервере
Процедура ПолучитьКлючи_RSA_НаСервере()
//ОбъектКриптографии = Новый COMОбъект("System.Security.Cryptography.RSACryptoServiceProvider"); требует на входе массив байтов ((
ОбъектКриптографии = Новый COMОбъект("Crypto1C.MyClass");
Ответ = ОбъектКриптографии.RSAKeyGenerator();
// Значение true, чтобы включать закрытый и открытый ключ RSA;
// значение false, чтобы включать только открытый ключ.
//SuccessCom=Ответ.Success;
//MessageCom=Ответ.Message;
//DataCom=Ответ.Data;
ПубличныйКлюч=Ответ.PublicKey; // строка
ПубличныйИПриватныйКлюч=Ответ.PrivatKey; // строка
Если НЕ Ответ.Success Тогда
Сообщить(Ответ.Message);
КонецЕсли;
ПубличныйКлючРазмер= ПолучитьДвоичныеДанныеИзСтроки(ПубличныйКлюч).Размер();
ПубличныйИПриватныйКлючРазмер= ПолучитьДвоичныеДанныеИзСтроки(ПубличныйИПриватныйКлюч).Размер();
ЖурналЛогов.ДобавитьСтроку("Публичный ключ : "+ПубличныйКлюч);
ЖурналЛогов.ДобавитьСтроку("Приватный ключ : "+ПубличныйИПриватныйКлюч);
ЖурналЛогов.ДобавитьСтроку("ПубличныйКлючРазмер байт/длина:" + ПубличныйКлючРазмер+"/"+СтрДлина(ПубличныйКлюч));
ЖурналЛогов.ДобавитьСтроку("ПриватныйКлючРазмер байт/длина: "+ПубличныйИПриватныйКлючРазмер+"/"+СтрДлина(ПубличныйИПриватныйКлюч));
ЖурналЛогов.ДобавитьСтроку("**************************************");
ОбъектКриптографии = Неопределено;
КонецПроцедуры
&НаКлиенте
Процедура ПолучитьКлючи_RSA(Команда)
ВремяСтарт=ТекущаяУниверсальнаяДатаВМиллисекундах();
ПолучитьКлючи_RSA_НаСервере();
Сообщить ("RSA потрачено млсек: "+ (ТекущаяУниверсальнаяДатаВМиллисекундах()-ВремяСтарт));
КонецПроцедуры
// Проверка работы RSA
&НаСервере
Процедура Шифровка_RSA()
Если Не ЗначениеЗаполнено(ИсхТекстСтрока) Тогда
сообщить("ИсхТекстСтрока пустая!!");
Возврат;
КонецЕсли;
// сом для саое шифрования
МойОбъект = Новый COMОбъект("Crypto1C.MyClass");
//шифруем ***********************
ЗашифрованныйТекстСтр="";
РасшифрованныйТекстСтр="";
Ответ_Com = МойОбъект.RSAEncrypt(ИсхТекстСтрока, ПубличныйКлюч, false);
если Ответ_Com.Success Тогда
ЗашифрованныйТекстСтр=Ответ_Com.Encrypted_64 ; // строка base64
КонецЕсли;
ПубличныйКлючРазмер= ПолучитьДвоичныеДанныеИзСтроки(ПубличныйКлюч).Размер();
ПубличныйИПриватныйКлючРазмер= ПолучитьДвоичныеДанныеИзСтроки(ПубличныйИПриватныйКлюч).Размер();
ЗашифрованныйТекстСтрРазмер= ПолучитьДвоичныеДанныеИзBase64Строки(ЗашифрованныйТекстСтр).Размер();
ИсхТекстСтрокаРазмер= ПолучитьДвоичныеДанныеИзСтроки(ИсхТекстСтрока).Размер();
ЖурналЛогов.ДобавитьСтроку("Публичный ключ: "+ПубличныйКлюч);
ЖурналЛогов.ДобавитьСтроку("Приватный ключ: "+ПубличныйИПриватныйКлюч);
ЖурналЛогов.ДобавитьСтроку("Шифрованный текст : "+ЗашифрованныйТекстСтр);
ЖурналЛогов.ДобавитьСтроку("РасшифрованныйТекстСтр : "+РасшифрованныйТекстСтр);
ЖурналЛогов.ДобавитьСтроку("ЗашифрованныйТекстСтрРазмер байт/длина: "+ЗашифрованныйТекстСтрРазмер+"/"+СтрДлина(ЗашифрованныйТекстСтр));
ЖурналЛогов.ДобавитьСтроку("ПубличныйКлючРазмер байт/длина:" + ПубличныйКлючРазмер+"/"+СтрДлина(ПубличныйКлюч));
ЖурналЛогов.ДобавитьСтроку("ПубличныйИПриватныйКлючРазмер байт/длина: "+ПубличныйИПриватныйКлючРазмер+"/"+СтрДлина(ПубличныйИПриватныйКлюч));
ЖурналЛогов.ДобавитьСтроку("ИсхТекстСтрокаРазмер байт/длина: "+ИсхТекстСтрокаРазмер+"/"+СтрДлина(ИсхТекстСтрока));
МойОбъект = Неопределено;
////Pass the data to ENCRYPT, the public key information
////(using RSACryptoServiceProvider.ExportParameters(false),
////and a boolean flag specifying no OAEP padding.
//encryptedData_64 = RSAEncrypt(StringToEncrypt, PublickKey_XML, false);
//
////Pass the data to DECRYPT, the private key information
////(using RSACryptoServiceProvider.ExportParameters(true),
////and a boolean flag specifying no OAEP padding.
//decryptedString = RSADecrypt(encryptedData_64, PrivatKey_XML, false);
КонецПроцедуры
// Дешифровка RSA
&НаСервере
Процедура Дешифров_RSA()
Если Не ЗначениеЗаполнено(ПубличныйИПриватныйКлюч) Тогда
сообщить("ПубличныйИПриватныйКлюч пустая!!");
Возврат;
КонецЕсли;
// сом для саое шифрования
МойОбъект = Новый COMОбъект("Crypto1C.MyClass");
//расшифруем ******************
РасшифрованныйТекстСтр="";
Ответ_Com = МойОбъект.RSADecrypt(ЗашифрованныйТекстСтр, ПубличныйИПриватныйКлюч, false);
если Ответ_Com.Success Тогда
РасшифрованныйТекстСтр=Ответ_Com.DecryptedString ; // строка
КонецЕсли;
ПубличныйКлючРазмер= ПолучитьДвоичныеДанныеИзСтроки(ПубличныйКлюч).Размер();
ПубличныйИПриватныйКлючРазмер= ПолучитьДвоичныеДанныеИзСтроки(ПубличныйИПриватныйКлюч).Размер();
ЗашифрованныйТекстСтрРазмер= ПолучитьДвоичныеДанныеИзBase64Строки(ЗашифрованныйТекстСтр).Размер();
ИсхТекстСтрокаРазмер= ПолучитьДвоичныеДанныеИзСтроки(ИсхТекстСтрока).Размер();
ЖурналЛогов.ДобавитьСтроку("Публичный ключ: "+ПубличныйКлюч);
ЖурналЛогов.ДобавитьСтроку("Приватный ключ: "+ПубличныйИПриватныйКлюч);
ЖурналЛогов.ДобавитьСтроку("Шифрованный текст : "+ЗашифрованныйТекстСтр);
ЖурналЛогов.ДобавитьСтроку("РасшифрованныйТекстСтр : "+РасшифрованныйТекстСтр);
ЖурналЛогов.ДобавитьСтроку("ЗашифрованныйТекстСтрРазмер байт/длина: "+ЗашифрованныйТекстСтрРазмер+"/"+СтрДлина(ЗашифрованныйТекстСтр));
ЖурналЛогов.ДобавитьСтроку("ПубличныйКлючРазмер байт/длина:" + ПубличныйКлючРазмер+"/"+СтрДлина(ПубличныйКлюч));
ЖурналЛогов.ДобавитьСтроку("ПубличныйИПриватныйКлючРазмер байт/длина: "+ПубличныйИПриватныйКлючРазмер+"/"+СтрДлина(ПубличныйИПриватныйКлюч));
ЖурналЛогов.ДобавитьСтроку("ИсхТекстСтрокаРазмер байт/длина: "+ИсхТекстСтрокаРазмер+"/"+СтрДлина(ИсхТекстСтрока));
МойОбъект = Неопределено;
КонецПроцедуры
&НаКлиенте
Процедура Шифрование_RSA(Команда)
Шифровка_RSA();
КонецПроцедуры
&НаСервере
Процедура ПолучитьКлючПоСолиНаСервере()
СольСохранненая=ОбщийСерверныйПривилегированный.УстановитьПолучитьКонстанту("Соль",ложь,);
UnlockKey="";
Соль = СольСохранненая; // строка
МойОбъект = Новый COMОбъект("Crypto1C.MyClass");
UnlockKey=МойОбъект.PBKDF2_GetXash(mPwd, 100000, "SHA512", Соль).HashPwdSalt_64 ;
ЖурналЛогов.ДобавитьСтроку("Соль: "+Соль);
ЖурналЛогов.ДобавитьСтроку("UnlockKey: "+UnlockKey);
UnlockKeyРазмер= ПолучитьДвоичныеДанныеИзBase64Строки(UnlockKey).Размер();
СольРазмер= ПолучитьДвоичныеДанныеИзBase64Строки(Соль).Размер();
ЖурналЛогов.ДобавитьСтроку("UnlockKey байт/длина:" + UnlockKeyРазмер+"/"+СтрДлина(UnlockKey));
ЖурналЛогов.ДобавитьСтроку("Соль байт/длина: "+СольРазмер+"/"+СтрДлина(Соль));
МойОбъект = Неопределено;
КонецПроцедуры
&НаКлиенте
Процедура ПолучитьКлючПоСоли(Команда)
ПолучитьКлючПоСолиНаСервере();
КонецПроцедуры
&НаКлиенте
Процедура Дешифровка_RSA(Команда)
Дешифров_RSA();
КонецПроцедуры
&НаСервере
Процедура ШифроватьПоКлючу_AESНаСервере() // шифруем по заданному
МойОбъект = Новый COMОбъект("Crypto1C.MyClass");
// 1. получить хеш по соли
Соль="";
UnlockKey="";
СольСохраненная=ОбщийСерверныйПривилегированный.УстановитьПолучитьКонстанту("Соль",ложь,);
Соль=СольСохраненная;
UnlockKey=МойОбъект.PBKDF2_GetXash(mPwd, 100000, "SHA512", СольСохраненная).HashPwdSalt_64 ;
// 2. получить PrivKey по UnlockKey AES
ДешифрованнаяСтрока="";
IV="";
PrivKey_шифр=ОбщийСерверныйПривилегированный.УстановитьПолучитьКонстанту("PrivKey",ложь,);
IV_Сохр=ОбщийСерверныйПривилегированный.УстановитьПолучитьКонстанту("IV",ложь,);
IV=IV_Сохр;
Ответ_Com=МойОбъект.DecryptStringFromBytes_Aes(PrivKey_шифр,UnlockKey,IV_Сохр);
если Ответ_Com.Success Тогда
ПубличныйИПриватныйКлюч=Ответ_Com.DecryptedString ;
иначе
сообщить ("2.DecryptStringFromBytes_Aes: "+Ответ_Com.Message);
КонецЕсли;
// 3. получить EncKey по PrivKey RSA
РасшифрованныйТекстСтр="";
EncKey_шифр=ОбщийСерверныйПривилегированный.УстановитьПолучитьКонстанту("EncKey",ложь,);
Ответ_Com = МойОбъект.RSADecrypt(EncKey_шифр, ПубличныйИПриватныйКлюч, false);
если Ответ_Com.Success Тогда
EncKey=Ответ_Com.DecryptedString ;
Key= EncKey;
иначе
сообщить ("3.RSADecrypt: "+Ответ_Com.Message);
КонецЕсли;
// 4. Шифруем Aes_ByKey
Ответ_Com=МойОбъект.EncryptStringToBytes_Aes_ByKey(pass,Key,IV);
если Ответ_Com.Success Тогда
ШифрованнаяСтрока=Ответ_Com.Encrypted_64 ;
иначе
сообщить ("4.AesEncrypt: "+Ответ_Com.Message);
КонецЕсли;
ДлинаКлючаРазмер= ПолучитьДвоичныеДанныеИзBase64Строки(Key).Размер();
ДлинаВектораРазмер= ПолучитьДвоичныеДанныеИзBase64Строки(IV).Размер();
ДлинаШифрованнаяСтрокаРазмер= ПолучитьДвоичныеДанныеИзBase64Строки(ШифрованнаяСтрока).Размер();
ЖурналЛогов.ДобавитьСтроку("ДлинаКлюча байт/длина:" + ДлинаКлючаРазмер+"/"+СтрДлина(Key));
ЖурналЛогов.ДобавитьСтроку("ДлинаВектора байт/длина: "+ДлинаВектораРазмер+"/"+СтрДлина(IV));
ЖурналЛогов.ДобавитьСтроку("ДлинаШифрованнаяСтрока байт/длина: "+ДлинаШифрованнаяСтрокаРазмер+"/"+СтрДлина(ШифрованнаяСтрока));
МойОбъект = Неопределено;
КонецПроцедуры
&НаКлиенте
Процедура ШифроватьПоКлючу_AES(Команда)
Если НЕ ЗначениеЗаполнено(mPwd)Тогда
Сообщить ("поле mPwd пустое !!");
Возврат;
КонецЕсли;
ШифроватьПоКлючу_AESНаСервере();
КонецПроцедуры
&НаСервере
Процедура ШифроватьИСохранитьКлючиНаСервере()
ОбщийСерверныйПривилегированный.УстановитьПолучитьКонстанту("Соль",истина,Соль);
ОбщийСерверныйПривилегированный.УстановитьПолучитьКонстанту("PubKey",истина,ПубличныйКлюч);
ОбщийСерверныйПривилегированный.УстановитьПолучитьКонстанту("IV",истина,IV); // вектор AES хранилища
ОбщийСерверныйПривилегированный.УстановитьПолучитьКонстанту("КонтрольнаяФраза",истина,ШифрованнаяСтрока); // Контрольная Фраза для проверки EncKey и IV
Если НЕ ЗначениеЗаполнено(ПубличныйИПриватныйКлюч) ИЛИ НЕ ЗначениеЗаполнено(UnlockKey) ИЛИ НЕ ЗначениеЗаполнено(IV) Тогда
Сообщить ("не заполнены: ПубличныйИПриватныйКлюч, UnlockKey, IV" );
возврат;
КонецЕсли;
Если НЕ ЗначениеЗаполнено(Key) ИЛИ НЕ ЗначениеЗаполнено(ПубличныйКлюч) Тогда
Сообщить ("не заполнены: Key, ПубличныйКлюч" );
возврат;
КонецЕсли;
ШифроватьИСохранитьПриватКлюч ();
ШифроватьИСохранитьКлючХранилища ();
КонецПроцедуры
&НаКлиенте
Процедура ШифроватьИСохранитьКлючи(Команда)
Если ПоляОчищены Тогда
Сообщить ("операция невыполниам, все поля очищены!!");
Возврат ;
КонецЕсли;
ВремяСтарт=ТекущаяУниверсальнаяДатаВМиллисекундах();
ШифроватьИСохранитьКлючиНаСервере();
Сообщить ("Шифровка ключей и запись, потрачено млсек: "+ (ТекущаяУниверсальнаяДатаВМиллисекундах()-ВремяСтарт));
КонецПроцедуры
&НаСервере
Процедура ШифроватьИСохранитьПриватКлюч()
МойОбъект = Новый COMОбъект("Crypto1C.MyClass");
Ответ_Com=МойОбъект.EncryptStringToBytes_Aes_ByKey(ПубличныйИПриватныйКлюч,UnlockKey,IV); // нужен отдельный вектор IV ?
если Ответ_Com.Success Тогда
ПриватныйКлючШифрованный=Ответ_Com.Encrypted_64 ;
Иначе
Сообщить (Ответ_Com.messsage);
КонецЕсли;
ОбщийСерверныйПривилегированный.УстановитьПолучитьКонстанту("PrivKey",истина,ПриватныйКлючШифрованный);// шифруется(AES)ключом UnlockKey
МойОбъект = Неопределено;
КонецПроцедуры
&НаСервере
Процедура ШифроватьИСохранитьКлючХранилища()
// сом для саое шифрования
МойОбъект = Новый COMОбъект("Crypto1C.MyClass");
Ответ_Com = МойОбъект.RSAEncrypt(Key, ПубличныйКлюч, false);
если Ответ_Com.Success Тогда
EncKey_Зашифрованныйр=Ответ_Com.Encrypted_64 ;
Иначе
Сообщить (Ответ_Com.messsage);
КонецЕсли;
ОбщийСерверныйПривилегированный.УстановитьПолучитьКонстанту("EncKey",истина,EncKey_Зашифрованныйр); // шифруется(RSA) ключом PubKey
EncKey_Зашифрованный_Размер= ПолучитьДвоичныеДанныеИзBase64Строки(EncKey_Зашифрованныйр).Размер();
ЖурналЛогов.ДобавитьСтроку("EncKey_Зашифрованныйр байт/длина: "+EncKey_Зашифрованный_Размер+"/"+СтрДлина(EncKey_Зашифрованныйр));
МойОбъект = Неопределено;
КонецПроцедуры
&НаСервере
Процедура ПроверитьКонтрольнуюФаразуНаСервере()
МойОбъект = Новый COMОбъект("Crypto1C.MyClass");
// 1. получить хеш по соли
Соль="";
UnlockKey="";
СольСохраненная=ОбщийСерверныйПривилегированный.УстановитьПолучитьКонстанту("Соль",ложь,);
Соль=СольСохраненная;
UnlockKey=МойОбъект.PBKDF2_GetXash(mPwd, 100000, "SHA512", СольСохраненная).HashPwdSalt_64 ;
// 2. получить PrivKey по UnlockKey AES
ДешифрованнаяСтрока="";
IV="";
PrivKey_шифр=ОбщийСерверныйПривилегированный.УстановитьПолучитьКонстанту("PrivKey",ложь,);
IV_Сохр=ОбщийСерверныйПривилегированный.УстановитьПолучитьКонстанту("IV",ложь,);
IV=IV_Сохр;
Ответ_Com=МойОбъект.DecryptStringFromBytes_Aes(PrivKey_шифр,UnlockKey,IV_Сохр);
если Ответ_Com.Success Тогда
ПубличныйИПриватныйКлюч=Ответ_Com.DecryptedString ;
иначе
сообщить ("2.DecryptStringFromBytes_Aes: "+Ответ_Com.Message);
КонецЕсли;
// 3. получить EncKey по PrivKey RSA
РасшифрованныйТекстСтр="";
EncKey_шифр=ОбщийСерверныйПривилегированный.УстановитьПолучитьКонстанту("EncKey",ложь,);
Ответ_Com = МойОбъект.RSADecrypt(EncKey_шифр, ПубличныйИПриватныйКлюч, false);
если Ответ_Com.Success Тогда
EncKey=Ответ_Com.DecryptedString ;
Key= EncKey;
//РасшифрованныйТекстСтр = EncKey;
иначе
сообщить ("3.RSADecrypt: "+Ответ_Com.Message);
КонецЕсли;
// 4. получить исходную строку по EncKey AES
ДешифрованнаяСтрока="";
Фраза_шифр=ОбщийСерверныйПривилегированный.УстановитьПолучитьКонстанту("КонтрольнаяФраза",ложь,);
Ответ_Com=МойОбъект.DecryptStringFromBytes_Aes(Фраза_шифр,EncKey,IV);
если Ответ_Com.Success Тогда
pass=Ответ_Com.DecryptedString ;
иначе
сообщить ("4.DecryptStringFromBytes_Aes: "+Ответ_Com.Message);
КонецЕсли;
МойОбъект = Неопределено;
КонецПроцедуры
&НаКлиенте
Процедура ПроверитьКонтрольнуюФаразу(Команда)
Если НЕ ЗначениеЗаполнено(mPwd) Тогда
Сообщить ("mPwd пустое!");
Возврат;
КонецЕсли;
ВремяСтарт=ТекущаяУниверсальнаяДатаВМиллисекундах();
ПроверитьКонтрольнуюФаразуНаСервере();
Сообщить ("Проверка контрольной фразы, потрачено млсек: "+ (ТекущаяУниверсальнаяДатаВМиллисекундах()-ВремяСтарт));
КонецПроцедуры
&НаКлиенте
Процедура ОчиститьПоляФормы(Команда)
ОчиститьНаСервере();
ПоляОчищены=Истина;
КонецПроцедуры
&НаСервере
Процедура ОчиститьЭлемент(рекв)
Попытка
ЭтаФорма[рекв].Очистить();
Исключение
КонецПопытки;
Попытка
ЭтаФорма[рекв] = Неопределено
Исключение
КонецПопытки;
КонецПроцедуры
&НаСервере
Функция ОчиститьНаСервере()
для Каждого рекв из ЭтаФорма.ПолучитьРеквизиты() Цикл
Если рекв.имя = "Объект" Тогда
об = РеквизитФормыВЗначение("Объект");
Для Каждого р Из об.Метаданные().Реквизиты Цикл
если р.Имя <> "СтрокаДляОзвучки" тогда
Объект[р.Имя] = Неопределено;
КонецЕсли;
КонецЦикла;
Для Каждого р Из об.Метаданные().ТабличныеЧасти Цикл
Объект[р.Имя].Очистить();
КонецЦикла;
Иначе
если рекв.Имя <> "mPwd" И рекв.Имя <> "ЖурналЛогов" тогда
ОчиститьЭлемент(рекв.имя) ;
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецФункции
// ***********************************
Библиотека работает на windows с установленной .net версии не ниже 4.0, регистрируется запуском RegAsm.exe, в директории C:\Windows\Microsoft.NET\Framework64\v4.0.30319, ключами /codebase или /unregister
Публикация сопровождается:
Библиотекой Crypto1C.dll
Архив с двумя файлами исходников на C# Crypto1C.rar