Hibernate / JPA和MS SQL Server - 在DecryptByKey之前打开对称密钥

时间:2016-10-13 00:07:51

标签: sql-server hibernate jpa encryption symmetric-key

在SQL Server 2012数据库中,我有一个带有varbinary(128)列的表,该列存储由证书(AppCert)支持的密钥(Secret_Key)加密的数据和使用主键的SHA2_512哈希的身份验证器:

CREATE TABLE [Lookup].[SecretStuff] (
    [Id] tinyint NOT NULL, 
    [Secret] varbinary(128) NOT NULL
        CONSTRAINT [PK_Lookup-SecretStuff_Id] PRIMARY KEY CLUSTERED ([Id] ASC), 
        CONSTRAINT [UN_Lookup-SecretStuff_Secret] UNIQUE NONCLUSTERED ([Secret])
);

OPEN SYMMETRIC KEY [Secret_Key] DECRYPTION BY CERTIFICATE [AppCert];
INSERT INTO [Lookup].[SecretStuff] ([Id], [Secret]) VALUES (1, ENCRYPTBYKEY(KEY_GUID('Secret_Key'), CONVERT(nvarchar(512), 'I have a secret'), 1, HASHBYTES('SHA2_512', CONVERT(varbinary(128), CONVERT(tinyint, 1)))));
CLOSE SYMMETRIC KEY [Secret_Key];

OPEN SYMMETRIC KEY [Secret_Key] DECRYPTION BY CERTIFICATE [AppCert];
SELECT [Id], CONVERT(nvarchar, DECRYPTBYKEY([Secret], 1, HASHBYTES('SHA2_512', CONVERT(varbinary, [Id])))) AS [Secret] FROM [Lookup].[SecretStuff];
CLOSE SYMMETRIC KEY [Secret_Key];

这一切都很美妙。现在,我有一个使用JPA / Hibernate的Spring Boot应用程序,它连接并经过测试/验证,可以使用这个数据库。 SecretStuff类:

@Entity
@Table(name="SecretStuff", schema="Lookup")
public class SecretStuff {

    @Id
    @Column(name = "Id", 
            nullable = false)
    private Integer id;

    @Column(name = "Secret", 
            nullable = false, 
            unique = true)
    @Size(min = 1, max = 255)
    @ColumnTransformer(
            read = "CONVERT(nvarchar(89), DECRYPTBYKEY([Secret], 1, 
                    HASHBYTES('SHA2_512', CONVERT(varbinary(128), [Id]))))")
    private String secret;
// getters/setter omitted
}

当我测试SecretStuff类时,我看到以下Hibernate生成的SQL:

select
    secretstuf0_.Id as Id1_7_0_,
    CONVERT(nvarchar(89), DECRYPTBYKEY(secretstuf0_.[Secret],
    1,
    HASHBYTES('SHA2_512',
    CONVERT(varbinary(128),
    secretstuf0_.[Id])))) as Secret2_7_0_ 
from
    Lookup.SecretStuff secretstuf0_ 
where
    secretstuf0_.Id=?

完全合理的查询,执行并返回Id = 1 Secret = NULL的1行,因为在执行查询之前未打开SYMMETRIC KEY。

我的问题: 如何在查询之前的同一事务中执行OPEN SYMMETRIC KEY ...命令,并在查询后的同一事务中执行CLOSE SYMMETRIC KEY ...命令?

我在服务类方法中使用了Hibernate.initialize来对事务内部的懒惰提取到多个关系。我会在这里使用类似的方法吗?怎么样?

我在输入这个问题时看到了this article,但它已经有几年的历史了,并且使用了NativeQuery的EntityManager方法。是否有更新的方法来管理JPA / Hibernate?

1 个答案:

答案 0 :(得分:1)

虽然不是我想要的确切解决方案,article I referenced in my original question@TrevorAbell的一些帮助使我得到了以下代码,这似乎符合我的需要。我在这里发布,以防其他人正在寻找类似的解决方案。我仍然愿意接受其他解决方案。

密钥是使用EntityManager在查询周围运行SYMMETRIC KEY命令。我将包含@Repository接口和@Service类以获得完整性,但关键是@Service类:

@Repository
public interface SecretStuffRepository extends JpaRepository<SecretStuff, Integer> {}

@Service
@Transactional(readOnly = true)
public class SecretStuffService {

    @PersistenceContext
    private EntityManager entityManager;

    @Autowired
    private SecretStuffRepository repository;

    public Iterable<SecretStuff> findAll() {

        this.entityManager.createNativeQuery("
              OPEN SYMMETRIC KEY [Secret_Key] 
              DECRYPTION BY CERTIFICATE [AppCert];
          ").executeUpdate();
        Iterable<SecurityQuestion> questions = this.repository.findAll();
        this.entityManager.createNativeQuery("
              CLOSE SYMMETRIC KEY [Secret_Key];
          ").executeUpdate();
        return stuff;
    }
}

现在,当我测试SecretStuffService时,我看到以下Hibernate生成的SQL:

Hibernate: 
    OPEN SYMMETRIC KEY [Secret_Key] DECRYPTION 
BY
    CERTIFICATE [AppCert];
Hibernate: 
    select
        secretstuf0_.Id as Id1_5_0_,
        CONVERT(nvarchar(89),
        DECRYPTBYKEY(secretstuf0_.[Secret],
        1,
        HASHBYTES('SHA2_512',
        CONVERT(varbinary(128),
        secretstuf0_.[Id])))) as Secret2_5_0_ 
    from
        Lookup.SecretStuff secretstuf0_ 
    where
        secretstuf0_.Id=?
Hibernate: 
    CLOSE SYMMETRIC KEY [Secret_Key];

调用SecretStuffService.findAll()现在打开密钥,调用存储库findAll()方法,并关闭同一事务中的密钥。请记住,在这种情况下,NativeQuery特定于Microsoft SQL Server,因此您需要将适当的命令替换为您的数据库供应商。