AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 56844
Accepted
efesar
efesar
Asked: 2014-01-16 11:23:24 +0800 CST2014-01-16 11:23:24 +0800 CST 2014-01-16 11:23:24 +0800 CST

有没有一种快速的方法来查找 SQL Server 2008 R2 中所有已加密/具有加密数据的列?

  • 772

有没有一种快速的方法来查找 SQL Server 2008 R2 中所有已加密/具有加密数据的列?

我需要取消开发服务器中所有加密列中的数据(根据我们的业务规则)。我知道大部分列,因为我们经常使用它们,但我想彻底,而且我想能够证明我已经找到了它们。

我搜索了网络,查看了INFORMATION_SCHEMA并检查了我认为有用的 DMV 以及sys.columns和sys.objects——但到目前为止还没有运气。

sql-server sql-server-2008-r2
  • 4 4 个回答
  • 8312 Views

4 个回答

  • Voted
  1. Best Answer
    Edward Dortland
    2014-01-17T06:17:03+08:002014-01-17T06:17:03+08:00

    假设您正在讨论使用 SQL Server 密钥加密的数据,则可以找到这些列。

    该Key_name()函数将返回用于加密该特定值的密钥的名称,如果没有使用“已知”密钥(第 3 方,或简单未加密)加密任何内容,则返回 NULL。

    有了这个知识,我们可以测试每一列,看看它是否至少包含一个行,该行的 varbinary 值返回一个键名

    key_name() 的功能

    --create a test database
    CREATE DATABASE [Test_ENCR]
    GO
    
    --change context
    USE [Test_ENCR]
    GO
    
    
    --because it's possible to encrypt different rows with different keys I'll create 2 keys for this demo
    -- Create a symmetric key
    CREATE SYMMETRIC KEY symmetricKey1
       WITH ALGORITHM = AES_128
       ENCRYPTION BY PASSWORD = 'password01!';
    GO
    
    -- Create a second key
    CREATE SYMMETRIC KEY symmetricKey2 
       WITH ALGORITHM = AES_128
       ENCRYPTION BY PASSWORD = 'password02!';
    GO
    
    
    
    --create a table that will have a column holding:
    --1: encrypted row with key1
    --2: encrypted row with key2
    --3: a non encrypted just varbinary value
    
    CREATE TABLE encryptedTable
    (ID int IDENTITY PRIMARY KEY,
    EncryptedCol varbinary(256) NOT NULL);
    GO
    
    
    -- open key1
    OPEN SYMMETRIC KEY symmetricKey1 
        DECRYPTION BY PASSWORD = 'password01!';
    GO
    
    -- open key2
    OPEN SYMMETRIC KEY symmetricKey2 
        DECRYPTION BY PASSWORD = 'password02!';
    GO
    
    --insert encrypted data with key1
    INSERT INTO encryptedTable(encryptedCol)
    VALUES ( ENCRYPTBYKEY (Key_GUID('symmetricKey1'), 'EncryptedText1'));
    GO
    
    --insert encrypted data with key2
    INSERT INTO encryptedTable(encryptedCol)
    VALUES ( ENCRYPTBYKEY (Key_GUID('symmetricKey2'), 'EncryptedText2'));
    GO
    
    
    --insert just varbinary data
    INSERT INTO encryptedTable(encryptedCol)
    VALUES (CONVERT(varbinary(256),'NotEncryptedTextJustVarBinary'))
    
    
    
    --have a look, without the key, all varbinary for you.
    SELECT * FROM encryptedTable
    GO
    

    结果:

    在此处输入图像描述

    --Return all key_names
    SELECT DISTINCT     key_name(encryptedcol), 
                        EncryptedCol 
    FROM encryptedTable;
    

    结果:

    在此处输入图像描述

    如何实现它来查找加密列

    --How do we dynamically find all the columns that have at least one row with a encrypted value?
    
    -- first we will find all tables and column with a varbinary datatype
    -- then we will test all those columns with a simple select
    -- If the key_name() function returns a value, the column and table name are stored together with the keyname
    
    --create a table to hold all varbinary columns and tables
    CREATE TABLE #TablesWithVarbinCols (    ID int IDENTITY,
                                    TableName nvarchar(128),
                                    ColumnName nvarchar(128)
                                    );
    
    --create a table to hold the end result
    CREATE TABLE #TablesWithEncryption (
                                    TableName nvarchar(128),
                                    ColumnName nvarchar(128),
                                    KeyName varchar(128)
                                    );
    
    
    --find and store all table and column names of user tables containing a varbinary column
    INSERT INTO #TablesWithVarbinCols (TableName,ColumnName)
    SELECT      o.[name] as TableName,
                c.[name] as ColumnName
    FROM        sys.objects o
    INNER JOIN  sys.columns c
    ON          o.[object_id]=c.[object_id] 
    INNER JOIN  sys.types t
    ON          c.system_type_id=t.system_type_id
    WHERE       o.[type]='U'
    AND         t.name=N'varbinary'
    AND         c.max_length > -1;
    
    
    DECLARE @col nvarchar(256)
    DECLARE @tab nvarchar(256)
    DECLARE @c int = 1
    DECLARE @MaxC int
    DECLARE @SQL varchar(max)
    
    SELECT @MaxC=MAX(ID)
    FROM #TablesWithVarbinCols
    
    --loop the previous result and create a simple select statement with a key_name() is not null where clause. 
    --If you have a result, store the details
    WHILE @c <= @MaxC
    BEGIN
        SELECT  @Tab=TableName,
             @col=ColumnName
        FROM    #TablesWithVarbinCols
        WHERE   ID=@c
    
        SET @SQL='  INSERT INTO #TablesWithEncryption (TableName, ColumnName, KeyName)
                    SELECT DISTINCT '''+@Tab +''',''' +@col +''', key_name('+@Col +') from '+ @tab +' 
                    WHERE key_name('+@Col +') is not null;'
        exec (@SQL)
    
        DELETE
        FROM #TablesWithVarbinCols
        WHERE id=@c;
        SET @c=@c+1
    END
    
    --select the result
    SELECT * FROM #TablesWithEncryption;
    

    结果:

    在此处输入图像描述

    --cleanup
    DROP TABLE #TablesWithVarbinCols;
    DROP TABLE #TablesWithEncryption;
    
    • 11
  2. Mike Fal
    2014-01-16T11:47:30+08:002014-01-16T11:47:30+08:00

    单元级加密的问题在于列本身并没有真正加密,而是该列中包含的数据。列本身只是 varbinary 列(因为这是必需的)并且可以包含完全清晰的数据。真正使数据加密的是使用ENCRYPTBY*和函数。DECRYPTBY*

    您可以从简单地在 sys.columns 视图中查询所有 varbinary 列开始:

    select
      object_name(a.object_id) [objectname]
      ,a.name [columnname]
      ,a.column_id
    from
       sys.columns a
       join sys.types b on (a.system_type_id = b.system_type_id)
    where
       b.name = N'varbinary';
    

    否则,您需要检查您的代码以确定加密/解密函数的使用位置:

    select
       object_name(object_id) [objectname]
       ,definition
    from
       sys.sql_modules
    where
       definition like N'%ENCRYPT%' 
       OR definition like N'%DECRYPT%';
    
    • 8
  3. roncansan
    2018-09-15T11:18:00+08:002018-09-15T11:18:00+08:00

    在特定数据库上运行以下查询

    select 
        t.name as [Table],
        c.name as [Column], 
        c.encryption_type_desc
    from   
        sys.all_columns c inner join
        sys.tables t on c.object_id = t.object_id
    where  
        c.encryption_type is not null 
    order by
        t.name,
        c.name
    

    略有改动

    https://social.msdn.microsoft.com/Forums/sqlserver/en-US/ca9d8360-5d7e-4de1-abe6-ce1afda595a9/how-to-find-which-table-columns-are-encrypted?forum=sqlsecurity

    • 1
  4. matzek
    2018-11-10T07:51:25+08:002018-11-10T07:51:25+08:00

    您可以通过搜索所有 varbinary 列并使用 KEY_NAME 函数检查加密密钥来找到使用 keys\certificates 加密的列。

    然而,这个过程有点昂贵和耗时。如果您需要定期查找这些列,我建议使用扩展属性“标记”这些列。我们可以在 Edward Dortland 的解决方案的基础上构建,并使用扩展属性(如 encrypted、encryptkey 和 encryptcert)“标记”找到的列。

    --create a table to hold all varbinary columns and tables
    CREATE TABLE #TablesWithVarbinCols (    ID int IDENTITY,
                                SchemaName nvarchar(128),
                                TableName nvarchar(128),
                                ColumnName nvarchar(128)
                                );
    
    --find and store all table and column names of user tables containing a 
    varbinary column
    INSERT INTO #TablesWithVarbinCols (SchemaName,TableName,ColumnName)
    SELECT      s.[name] as SchemaName,
                o.[name] as TableName,
                c.[name] as ColumnName
    FROM        sys.objects o
    INNER JOIN  sys.schemas s
    ON          s.[schema_id] = o.[schema_id]
    INNER JOIN  sys.columns c
    ON          o.[object_id]=c.[object_id] 
    INNER JOIN  sys.types t
    ON          c.system_type_id=t.system_type_id
    WHERE       o.[type]='U'
    AND         t.name=N'varbinary'
    AND         c.max_length > -1;
    
    DECLARE @sch nvarchar(128)
    DECLARE @col nvarchar(256)
    DECLARE @tab nvarchar(256)
    DECLARE @key nvarchar(256)
    DECLARE @cert nvarchar(256)
    DECLARE @c int = 1
    DECLARE @MaxC int
    DECLARE @SQL nvarchar(max)
    
    SELECT @MaxC=MAX(ID)
    FROM #TablesWithVarbinCols
    
    --loop the previous result and create a simple select statement with a 
    key_name() is not null where clause. 
    --If you have a result, store the details
    WHILE @c <= @MaxC
    BEGIN
        SET @key = NULL;
        SELECT  @sch=SchemaName,
                @Tab=TableName,
                @col=ColumnName
        FROM    #TablesWithVarbinCols
        WHERE   ID=@c
    
    
    SET @SQL='SELECT DISTINCT @key= key_name('+@Col +') from '+ @tab +' 
                WHERE key_name('+@Col +') is not null;'
    
    
    exec sp_executesql @SQL, N'@key nvarchar(256) out', @key out
    
    SELECT @cert =  c.name 
    from sys.symmetric_keys sk
    join sys.key_encryptions ke
        on
        sk.symmetric_key_id= ke.key_id
    join sys.certificates c
        on
        ke.thumbprint=c.thumbprint
    where sk.name = @key
    
    
    IF (@key IS NOT NULL)
    BEGIN
    
        SET @SQL=
        'EXEC sp_addextendedproperty @name = N''encrypted'', @value = N''1'', '+
        '@level0type = N''Schema'', @level0name = '''+@Sch+''', '+
        '@level1type = N''Table'', @level1name = '''+@tab+''','+
        '@level2type = N''Column'', @level2name = '''+@col+'''
        '
    
        EXEC sp_executesql @SQL
    
        SET @SQL=
        'EXEC sp_addextendedproperty @name = N''encryptkey'', @value = '''+@key+''', '+
        '@level0type = N''Schema'', @level0name = '''+@Sch+''', '+
        '@level1type = N''Table'', @level1name = '''+@tab+''','+
        '@level2type = N''Column'', @level2name = '''+@col+'''
        '
    
        EXEC sp_executesql @SQL
    
        SET @SQL=
        'EXEC sp_addextendedproperty @name = N''encryptcert'', @value = '''+@cert+''', '+
        '@level0type = N''Schema'', @level0name = '''+@Sch+''', '+
        '@level1type = N''Table'', @level1name = '''+@tab+''','+
        '@level2type = N''Column'', @level2name = '''+@col+'''
        '
    
        EXEC sp_executesql @SQL
    
    END
    
    DELETE
    FROM #TablesWithVarbinCols
    WHERE id=@c;
    SET @c=@c+1
    
    END
    
    drop table #TablesWithVarbinCols
    

    然后我们可以通过搜索扩展属性轻松找到加密列。

    --Adjust WHERE clause depending on what tags you are looking for
    SELECT
       SCHEMA_NAME(tbl.schema_id) AS SchemaName,    
       tbl.name AS TableName, 
       clmns.name AS ColumnName,
      p.name AS ExtendedPropertyName,    --remove for programming
       CAST(p.value AS sql_variant) AS ExtendedPropertyValue
    FROM
       sys.tables AS tbl
       INNER JOIN sys.all_columns AS clmns ON clmns.object_id=tbl.object_id
       INNER JOIN sys.extended_properties AS p ON p.major_id=tbl.object_id AND p.minor_id=clmns.column_id AND p.class=1
    WHERE p.name in ('encrypted','encryptkey','encryptcert')
    
    • 1

相关问题

  • SQL Server - 使用聚集索引时如何存储数据页

  • 我需要为每种类型的查询使用单独的索引,还是一个多列索引可以工作?

  • 什么时候应该使用唯一约束而不是唯一索引?

  • 死锁的主要原因是什么,可以预防吗?

  • 如何确定是否需要或需要索引

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目

    • 12 个回答
  • Marko Smith

    如何让sqlplus的输出出现在一行中?

    • 3 个回答
  • Marko Smith

    选择具有最大日期或最晚日期的日期

    • 3 个回答
  • Marko Smith

    如何列出 PostgreSQL 中的所有模式?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Jin 连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane 如何列出 PostgreSQL 中的所有模式? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve