Sql server 加密列作为主键的一部分,按不工作分组、排序、搜索开销

Sql server 加密列作为主键的一部分,按不工作分组、排序、搜索开销,sql-server,sql-server-2008,sorting,encryption,grouping,Sql Server,Sql Server 2008,Sorting,Encryption,Grouping,我在表中有一个主键列,它在早期阶段被设计为未加密列。现在,我们计划使用SQL Server内置的细粒度加密将此列作为加密列。 我使用以下示例代码进行测试 我对同一列有以下要求 该列在许多其他表中广泛用作外键 在应用程序中,同一列作为复合主键/非聚集索引的一部分在多个表中建立索引 需要基于通配符搜索来搜索列 按两个方向对列进行排序 我面临的问题是,当我加密值时,每次都会得到不同的值 我无法在同一列上进行分组 当需要执行基于通配符的搜索或排序时,需要取消列中存储的所有数据的加密 有没有更好的方法来解

我在表中有一个主键列,它在早期阶段被设计为未加密列。现在,我们计划使用SQL Server内置的细粒度加密将此列作为加密列。 我使用以下示例代码进行测试

我对同一列有以下要求

  • 该列在许多其他表中广泛用作外键
  • 在应用程序中,同一列作为复合主键/非聚集索引的一部分在多个表中建立索引
  • 需要基于通配符搜索来搜索列
  • 按两个方向对列进行排序
  • 我面临的问题是,当我加密值时,每次都会得到不同的值

  • 我无法在同一列上进行分组
  • 当需要执行基于通配符的搜索或排序时,需要取消列中存储的所有数据的加密
  • 有没有更好的方法来解决这些问题?我不喜欢使用任何用户定义的函数

    请帮帮我

    CREATE DATABASE Bank
    GO
    USE Bank
    GO
    
     CREATE TABLE Account ( 
      AccountId int NOT NULL IDENTITY(1,1) PRIMARY KEY, 
      AccountNumber varchar(50),  
      EncryptedAccountNumber varbinary(128)  )
    GO
    
    
      -----------------
       CREATE MASTER KEY ENCRYPTION BY  PASSWORD = 'Pa$$w0rd'
    
        -----------------
        CREATE CERTIFICATE BankCert
          WITH SUBJECT = 'Account Numbers';
    GO
        -----------------    
        CREATE SYMMETRIC KEY BankAccountKey  
        WITH ALGORITHM = AES_256  
        ENCRYPTION BY CERTIFICATE BankCert;
    GO
    
     --Encryption-----------------
          OPEN SYMMETRIC KEY BankAccountKey  
          DECRYPTION BY CERTIFICATE BankCert;   --insert original and encrypted values 
    
    INSERT INTO Account
        VALUES ('123456789', ENCRYPTBYKEY(KEY_GUID('BankAccountKey'), '123456789')),
        ('987654321', ENCRYPTBYKEY(KEY_GUID('BankAccountKey'), '987654321'))
    
    SELECT * FROM Account
    
    --Decryption-----------------------------------------------------------
    OPEN SYMMETRIC KEY BankAccountKey
          DECRYPTION BY CERTIFICATE BankCert;
    GO
    
    --list original and decrypted values
    SELECT
        AccountNumber,
        EncryptedAccountNumber,
        LEN(EncryptedAccountNumber) AS Size,
        CONVERT(varchar, DECRYPTBYKEY(EncryptedAccountNumber)) AS DecryptedAccountNumber
    FROM Account
    

    数据库中的所有列级加密都是不确定和随机的。您可以使用SQL Server 2016 Always Encrypted并将其配置为确定性加密,但如果基数较低,您将面临有人使用驱动程序创建帐户号码哈希表并破坏加密的风险。最好将其从主键中删除,并将其作为外键引用的所有表上的列删除,这样它将仅位于一个表上并进行加密。至于搜索,您可以在解密之前在最后四位数字上创建一个哈希来缩小结果范围。这将减少工作量。

    也许您不应该将帐号用作外键?帐号不是真正的列。我用这个例子解释了这个场景。也许你不应该把那个列用作外键?谢谢。你的解决方案会奏效的。但这是一个现有的系统。如果避免将该列作为外键,则需要使用另一个未加密的列在其他表中进行映射。这需要在存储过程中进行巨大的更改。