繁体   English   中英

在 T-SQL 上解密 AES 128

[英]Decrypt AES 128 on T-SQL

我有一个当前使用 AES 128 的数据库。该数据库有大约 800 万条记录,客户想要的是解码密码和 hash 密码,因此无法解密密码。 这是一个 web 应用程序,其数据存储在远程服务器上。 我尝试使用 web 应用程序进行转换,但它一直超时。 由于这是 8 百万,go 需要一段时间才能通过所有项目,所以我的下一个想法是让 SQL 做解密和散列。 我可以让它运行接下来的几天。

我遇到的问题是每列都有带有唯一盐的加密密码。 我找不到使用加密密码和盐来解密密码的 function。 有没有 function? 还是第三方? 有没有更好的方法来 go 关于这个?

谢谢!

在 SQL 服务器中执行此操作的最简单/唯一的方法是在 C# 中编写 CLR 用户定义的 Function (UDF)。

更多细节。 如果是我,我会添加一个新列来包含新密码 hash 并定期运行更新语句来构造新密码 hash,如下所示:

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

其中DecryptAndHash()是您的 CLR UDF。 转换完成后,您应该可以自由地删除旧列并推出更新以使用新的身份验证逻辑。

可能想在桌面上放置一个触发器,以使 hash 与加密密码同步,以防万一有人在这一切进行时更改密码。

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内部的实现留给读者作为练习。

您可以查看应用程序的身份验证,并从源代码中查看它如何验证密码。 在那里您应该看到应用程序正在加密密码并将其与数据库中的加密值进行比较。 加密 function 应该很容易反转。 盐通常不与加密一起使用,它用于生成 hash 以防止查找攻击。

我不认为 SQL 可以在 AES128 上进行解密,无论如何都不是直接的方式。 但是您可以使用标准 API 编写一个简单的 .NET 应用程序,该应用程序将解密每个密码,hash 使用盐并将其写回数据库。

存储加密密码的关键在于它们不能被解密。 加密实际上是使用密码作为密钥对某个常量(+salt)进行的。

所以基本上目标已经达到了,你不能解密“密码”来得到他们的明文版本。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM