2016-10-13 2 views
2

В базе данных SQL Server 2012 у меня есть таблица с столбцом varbinary (128), в которой хранятся данные, зашифрованные с помощью ключа подписи (AppCert) (Secret_Key) и аутентификатор, используя хэш SHA2_512 первичного ключа:Hibernate/JPA и MS SQL Server - открыть симметричный ключ до DecryptByKey

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]; 

Все это прекрасно работает. Теперь у меня есть приложение Spring Boot, использующее JPA/Hibernate, который подключен и проверен/проверен для работы с этой базой данных. Класс 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=? 

Совершенно разумный запрос, который выполняется и возвращает 1 строку с Id = 1 Тайной = NULL, потому что SYMMETRIC KEY не открывается до выполнения запроса.

Мой вопрос: Как я могу выполнить команду ОТКРЫТЬ SYMMETRIC KEY ... в той же самой транзакции перед запросом и ЗАКРЫТЬ СИММЕТРИЧНОМ KEY ... команды в той же самой транзакции после запроса?

Я использовал Hibernate.initialize внутри методов класса обслуживания для ленивого извлечения во многие отношения внутри транзакций. Использую ли я здесь подобный подход? Как?

Я видел this article, так как я набирал этот вопрос, но ему пару лет, и он использует подход EntityManager с NativeQuery. Есть ли обновленный способ управления этим с помощью JPA/Hibernate?

ответ

0

Пока не точное решение, которое я искал, 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, поэтому вам нужно будет подставить соответствующую команду для поставщика базы данных.

Смежные вопросы