/// <summary> /// Вспомогательная функция для шифрования данных по алгоритму ГОСТ 28147-89 /// с зацеплением /// </summary> /// <param name="session">Текущая сессия</param> /// <param name="data">Данные для шифрования</param> /// <param name="initVector">Синхропосылка</param> /// <param name="keyId">Ключ для шифрования</param> /// <returns>Зашифрованные данные</returns> public static byte[] CBC_Gost28147_89_Encrypt(ISession session, byte[] data, byte[] initVector, IObjectHandle keyId) { // Дополняем данные по ISO 10126 byte[] dataWithPadding = ISO_10126_Padding.Pad(data, Settings.GOST28147_89_BLOCK_SIZE); byte[] round = new byte[Settings.GOST28147_89_BLOCK_SIZE]; Buffer.BlockCopy(initVector, 0, round, 0, initVector.Length); using (var ms = new MemoryStream()) { var mechanism = Settings.Factories.MechanismFactory.Create(CKM.CKM_GOST28147_ECB); for (var i = 0; i < dataWithPadding.Length / Settings.GOST28147_89_BLOCK_SIZE; i++) { byte[] currentData = new byte[Settings.GOST28147_89_BLOCK_SIZE]; Buffer.BlockCopy(dataWithPadding, i * Settings.GOST28147_89_BLOCK_SIZE, currentData, 0, currentData.Length); byte[] block = round.Xor(currentData); // Получение зашифрованного блока данных byte[] encryptedBlock = session.Encrypt(mechanism, keyId, block); Buffer.BlockCopy(encryptedBlock, 0, round, 0, encryptedBlock.Length); ms.Write(encryptedBlock, 0, encryptedBlock.Length); } return(ms.ToArray()); } }
static void Main(string[] args) { try { // Инициализировать библиотеку Console.WriteLine("Library initialization"); using (var pkcs11 = new Pkcs11(Settings.RutokenEcpDllDefaultPath, Settings.OsLockingDefault)) { // Получить доступный слот Console.WriteLine("Checking tokens available"); Slot slot = Helpers.GetUsableSlot(pkcs11); // Открыть RW сессию в первом доступном слоте Console.WriteLine("Opening RW session"); using (Session session = slot.OpenSession(false)) { // Выполнить аутентификацию Пользователя Console.WriteLine("User authentication"); session.Login(CKU.CKU_USER, SampleConstants.NormalUserPin); try { // Получить данные для шифрования byte[] sourceData = SampleData.Encrypt_Gost28147_89_CBC_SourceData; // Получить ключ для шифрования Console.WriteLine("Getting secret key..."); List <ObjectHandle> keys = session.FindAllObjects(SymmetricKeyAttributes); Errors.Check("No keys found", keys.Count > 0); // Выполнить дополнение данных по ISO 10126 byte[] dataWithPadding = ISO_10126_Padding.Pad(sourceData, SampleConstants.Gost28147_89_BlockSize); // Получить синхропосылку var random = new Random(); byte[] initVector = new byte[SampleConstants.Gost28147_89_BlockSize]; random.NextBytes(initVector); byte[] round = new byte[SampleConstants.Gost28147_89_BlockSize]; Buffer.BlockCopy(initVector, 0, round, 0, initVector.Length); Console.WriteLine("Encrypting..."); byte[] encryptedData; using (var ms = new MemoryStream()) { // Инициализировать операцию шифрования var mechanism = new Mechanism((uint)Extended_CKM.CKM_GOST28147_ECB); for (var i = 0; i < dataWithPadding.Length / SampleConstants.Gost28147_89_BlockSize; i++) { byte[] currentData = new byte[SampleConstants.Gost28147_89_BlockSize]; Buffer.BlockCopy(dataWithPadding, i * SampleConstants.Gost28147_89_BlockSize, currentData, 0, currentData.Length); byte[] block = round.Xor(currentData); // Получение зашифрованного блока данных byte[] encryptedBlock = session.Encrypt(mechanism, keys[0], block); Buffer.BlockCopy(encryptedBlock, 0, round, 0, encryptedBlock.Length); ms.Write(encryptedBlock, 0, encryptedBlock.Length); } encryptedData = ms.ToArray(); } // Распечатать буфер, содержащий зашифрованные данные Console.WriteLine(" Encrypting buffer is:"); Helpers.PrintByteArray(encryptedData); Console.WriteLine("Encryption has been completed successfully"); // Расшифровать данные Console.WriteLine("Decrypting..."); round = new byte[SampleConstants.Gost28147_89_BlockSize]; Buffer.BlockCopy(initVector, 0, round, 0, initVector.Length); byte[] decryptedData; using (var ms = new MemoryStream()) { var mechanism = new Mechanism((uint)Extended_CKM.CKM_GOST28147_ECB); for (var i = 0; i < encryptedData.Length / SampleConstants.Gost28147_89_BlockSize; i++) { byte[] currentData = new byte[SampleConstants.Gost28147_89_BlockSize]; Buffer.BlockCopy(encryptedData, i * SampleConstants.Gost28147_89_BlockSize, currentData, 0, currentData.Length); // Получение расшифрованного блока данных byte[] decryptedBlock = session.Decrypt(mechanism, keys[0], currentData); byte[] decryptedRound = round.Xor(decryptedBlock); Buffer.BlockCopy(currentData, 0, round, 0, currentData.Length); ms.Write(decryptedRound, 0, decryptedRound.Length); } // Снимаем дополнение данных decryptedData = ISO_10126_Padding.Unpad(ms.ToArray()); } // Распечатать буфер, содержащий расшифрованные данные Console.WriteLine(" Decrypted buffer is:"); Helpers.PrintByteArray(decryptedData); Console.WriteLine("Decryption has been completed successfully"); // Сравнить исходные данные с расшифрованными bool encryptionState = (Convert.ToBase64String(sourceData) == Convert.ToBase64String(decryptedData)); Errors.Check("Source data and decrypted data are not equal", encryptionState); Console.WriteLine("Source data and decrypted data are equal"); } finally { // Сбросить права доступа как в случае исключения, // так и в случае успеха. // Сессия закрывается автоматически. session.Logout(); } } } } catch (Pkcs11Exception ex) { Console.WriteLine($"Operation failed [Method: {ex.Method}, RV: {ex.RV}]"); } catch (Exception ex) { Console.WriteLine($"Operation failed [Message: {ex.Message}]"); } }