Расшифровать AES 128 на T-SQL - PullRequest
3 голосов
/ 28 апреля 2011

У меня есть база данных, которая в настоящее время использует AES 128. База данных содержит около 8 миллионов записей, и клиент хочет декодировать пароли и вместо этого хэшировать их, чтобы пароли не могли быть расшифрованы.Это веб-приложение с данными, хранящимися на удаленном сервере.Я пытался использовать веб-приложение для преобразования, но время ожидания истекло.Поскольку это 8 милов, потребуется время, чтобы просмотреть все элементы, поэтому моей следующей идеей было заставить SQL выполнять дешифрование и хеширование.Я мог бы позволить ему работать в течение следующих нескольких дней.

Проблема, которую я имею, состоит в том, что у каждого столбца есть зашифрованный пароль с уникальной солью.Я не могу найти функцию для расшифровки пароля с использованием зашифрованного пароля и соли.Есть ли функция?Даже третья сторона?Есть ли лучший способ сделать это?

Спасибо!

Ответы [ 3 ]

3 голосов
/ 28 апреля 2011

Самый простой / единственный способ сделать это в SQL Server - написать пользовательскую функцию (UDF) CLR на C #.См.

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

update top 10000 dbo.users
set hashedPassword = DecryptAndHash( encryptedPassword )
where hashedPassword is null

, где DecryptAndHash() - это вашCLR UDF.Как только преобразование завершено, вы можете свободно удалить старый столбец и развернуть обновление, чтобы использовать новую логику аутентификации.

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

FWIW, код не должен быть намного сложнее, чем

using System;
using Microsoft.SqlServer.Server;

namespace Sandbox
{
    public static class EncryptionFunctions
    {

        /// <summary>
        /// Encrypts a string
        /// </summary>
        /// <param name="plainText"></param>
        /// <returns>varbinary</returns>
        [SqlFunction]
        public static byte[] Encrypt( string plainText )
        {
            byte[] cipherText ;
            using ( EncryptionEngine cipher = EncryptionEngine.GetInstance() )
            {
                cipherText = cipher.Encrypt( plainText ) ;
            }
            return cipherText ;
        }

        /// <summary>
        /// Decrypts a previously encrypted varbinary
        /// </summary>
        /// <param name="cipherText"></param>
        /// <returns>string</returns>
        [SqlFunction]
        public static string Decrypt( byte[] cipherText )
        {
            string plainText ;
            using ( EncryptionEngine cipher = EncryptionEngine.GetInstance() )
            {
                plainText = cipher.Decrypt( cipherText ) ;
            }
            return plainText ;
        }

        /// <summary>
        /// Compute the secure hash of a [plaintext] string
        /// </summary>
        /// <param name="plainText"></param>
        /// <returns> varbinary </returns>
        [SqlFunction]
        public static byte[] SecureHash( string plainText )
        {
            byte[] hash ;
            using ( EncryptionEngine cipher = EncryptionEngine.GetInstance() )
            {
                hash = cipher.ComputeSecureHash( plainText ) ;
            }
            return hash ;
        }

        /// <summary>
        /// Convenience wrapper method to take a previously encrypted string, decrypt it and compute its secure hash
        /// </summary>
        /// <param name="cipherText"></param>
        /// <returns>varbinary</returns>
        [SqlFunction]
        public static byte[] DecryptAndHash( byte[] cipherText )
        {
            byte[] hash ;
            using ( EncryptionEngine cipher = EncryptionEngine.GetInstance() )
            {
                hash = cipher.ComputeSecureHash( cipher.Decrypt( cipherText ) ) ;
            }
            return hash ;
        }

        /// <summary>
        /// The core encrypt/decrypt/hash engine
        /// </summary>
        private class EncryptionEngine : IDisposable
        {
            /// <summary>
            /// get an instance of this class
            /// </summary>
            /// <returns></returns>
            public static EncryptionEngine GetInstance()
            {
                return new EncryptionEngine() ;
            }

            #region IDisposable Members

            /// <summary>
            /// Dispose of any unmanaged resources
            /// </summary>
            public void Dispose()
            {
                throw new NotImplementedException();
            }

            #endregion

            /// <summary>
            /// Encrypt a plaintext string
            /// </summary>
            /// <param name="plainText"></param>
            /// <returns></returns>
            internal byte[] Encrypt( string plainText )
            {
                throw new NotImplementedException();
            }

            /// <summary>
            /// Decrypt an encrypted string
            /// </summary>
            /// <param name="cipherText"></param>
            /// <returns></returns>
            internal string Decrypt( byte[] cipherText )
            {
                throw new NotImplementedException();
            }

            /// <summary>
            /// Compute the secure hash of a string
            /// </summary>
            /// <param name="plainText"></param>
            /// <returns></returns>
            internal byte[] ComputeSecureHash( string plainText )
            {
                throw new NotImplementedException();
            }

        }

    }
}

Реализация внутренних компонентов EncryptionEngineоставлено в качестве упражнения для читателя.

2 голосов
/ 28 апреля 2011

Вы можете взглянуть на аутентификацию вашего приложения и посмотреть из исходного кода, как оно аутентифицирует пароль.Там вы должны увидеть, что приложение шифрует пароль и сравнивает его с зашифрованным значением в базе данных.Функцию шифрования там должно быть легко изменить.Соль обычно не используется вместе с шифрованием, она используется при генерации хеша для защиты от атак поиска.

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

0 голосов
/ 28 апреля 2011

Смысл хранения зашифрованных паролей в том, что они не могут быть расшифрованы. Шифрование фактически выполняется для некоторой константы (+ соль) с использованием пароля в качестве ключа.

Таким образом, в основном цель уже достигнута, вы не можете расшифровать «пароли», чтобы получить их версии в виде открытого текста.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...