Будьте в спящем режиме шифрование базы данных, абсолютно Очевидной для приложения

В Java, enum полноценный класс :

типы перечисления языка программирования Java намного более мощны, чем их дубликаты на других языках. Перечислимое объявление определяет класс (названный перечислимым типом). Тело класса Enum может включать методы и другие поля.

для наблюдения фактического размера каждого enum, давайте сделаем фактическое enum и исследуйте содержание class файл, который он создает.

Скажем, у нас есть следующий Constants класс Enum:

public enum Constants {
  ONE,
  TWO,
  THREE;
}

Компиляция вышеупомянутое enum и разборка получающегося class файл с javap дает следующее:

Compiled from "Constants.java"
public final class Constants extends java.lang.Enum{
    public static final Constants ONE;
    public static final Constants TWO;
    public static final Constants THREE;
    public static Constants[] values();
    public static Constants valueOf(java.lang.String);
    static {};
}

дизассемблирование показывает, что то каждое поле enum является экземпляром Constants enum класс. (Дальнейший анализ с [1 113] покажет, что каждое поле инициализируется путем создания нового объекта путем вызова new Constants(String) конструктор в статическом блоке инициализации.)

Поэтому мы можем сказать, что каждый enum поле, которое мы создаем, будет, по крайней мере, так же как издержки создания объекта в JVM.

8
задан Azder 29 September 2009 в 00:30
поделиться

7 ответов

Являются ли канонические расположения подмодулей удаленными? Если да, то вы в порядке с клонированием их один раз? Другими словами, вы хотите неглубокие клоны только потому, что вы страдаете от пустой полосы пропускания частых субмодульных клонов?

Если вы хотите, чтобы неглубокие клоны спасали местное дисковое пространство, то ответ Райана Грэма кажется хорошим способом. Клонируйте хранилища вручную, чтобы они были неглубокими. Если вы считаете это полезным, адаптируйте субмодуль git для его поддержки. Отправьте электронное письмо по адресу в список с запросом об этом (рекомендации по его реализации, предложения по интерфейсу и т.д.). На мой взгляд, люди там вполне поддерживают потенциальных вкладчиков, которые искренне хотят улучшить Git конструктивным образом.

Если вы в порядке с выполнением одного полного клона каждого подмодуля (плюс более поздние выборки, чтобы поддерживать их в актуальном состоянии), вы можете попробовать использовать опцию --привязка git submodule update (находится в Git 1.6.4 и более поздних версиях) для обозначения локальных хранилищ объектов (например, сделайте -mirror клонами хранилищ канонических подмодулей, затем используйте --привязку в подмодулях, чтобы указать на эти локальные клоны). Перед использованием -привязки просто прочитайте о git clone --привязке / git clone --объединенной . Единственная вероятная проблема со ссылками на зеркала будет заключаться в том, что они когда-либо получат обновления без быстрой пересылки (хотя вы можете включить рефлоги и расширить их окна истечения срока действия, чтобы помочь сохранить любые заброшенные фиксаторы, которые могут вызвать проблему). У вас не должно быть проблем до тех пор, пока

  • не будут зафиксированы локальные подмодули, или
  • любые фиксаторы, которые остаются зависшими от небыстрых пересылок, которые канонические репозитории могут публиковать, не являются предками для ваших локальных субмодулей, или
  • вы усердно держите свои локальные субмодули на повторном уровне поверх любых небыстрых форвардов, которые могут быть опубликованы в канонических субмодульных хранилищах.

Если вы используете что-то подобное и есть вероятность того, что в ваших рабочих деревьях могут быть зафиксированы локальные подмодули, то, вероятно, было бы неплохо создать автоматизированную систему, которая обеспечивала бы, чтобы критические объекты, на которые ссылаются извлеченные подмодули, не зависали в зеркальных репозиториях (и, если они найдены, копирует их в нужные репозитории).

И, как говорится в git clone manpage, не используйте -привязку , если вы не понимаете этих последствий.

# Full clone (mirror), done once.
git clone --mirror $sub1_url $path_to_mirrors/$sub1_name.git
git clone --mirror $sub2_url $path_to_mirrors/$sub2_name.git

# Reference the full clones any time you initialize a submodule
git clone $super_url super
cd super
git submodule update --init --reference $path_to_mirrors/$sub1_name.git $sub1_path_in_super
git submodule update --init --reference $path_to_mirrors/$sub2_name.git $sub2_path_in_super

# To avoid extra packs in each of the superprojects' submodules,
#   update the mirror clones before any pull/merge in super-projects.
for p in $path_to_mirrors/*.git; do GIT_DIR="$p" git fetch; done

cd super
git pull             # merges in new versions of submodules
git submodule update # update sub refs, checkout new versions,
                     #   but no download since they reference the updated mirrors

В качестве альтернативы вместо -привязки можно использовать зеркальные клоны в сочетании со стандартной функцией жесткой привязки git clone , используя локальные зеркала в качестве источника для подмодулей. В новых клонах суперпроектов выполните команду git submodule init , измените URL-адреса подмодулей в .git/config , чтобы указать на локальные зеркала,затем выполните обновление подмодуля . Для получения жестких ссылок необходимо повторно объединить все существующие извлеченные подмодули. Вы сэкономите пропускную способность, загрузив только один раз в зеркала, а затем извлекая локально из них в извлеченные подмодули. Жесткая привязка позволила бы сэкономить место на диске (хотя выборки, как правило, накапливались и дублировались в нескольких экземплярах хранилищ объектов выданных подмодулей; можно периодически повторять извлеченные подмодули из зеркал, чтобы восстановить экономию дискового пространства, обеспечиваемую аппаратной привязкой).

-121--2033657-

Я не думаю, что это возможно. Блоки можно приблизительно рассматривать как расширенные функции (с доступом к глобальным или локальным переменным). Таким же образом нельзя сравнивать содержимое функций, нельзя сравнивать содержимое блоков.

Все, что вы можете сделать, это сравнить их низкоуровневую реализацию , но я сомневаюсь, что компилятор гарантирует, что два блока с одним и тем же содержимым будут использовать их реализацию.

-121--2249290-

Прошло много времени с тех пор, как я задал вопрос. А пока спасибо за все ответы. Они были великолепны при работе с первоначальной идеей шифрования всей базы данных, но требование изменилось только на шифрование конфиденциальной информации пользователя, такой как имя и адрес. Таким образом, решение было что-то вроде кода внизу.

Мы внедрили шифровальщик, который считывает метод шифрования из записи (так что может быть разное шифрование для каждой записи) и использовать его для подключения временных повторяющихся полей к полям, зашифрованным в базе данных. Добавленные бонус/недостатки:

  • Данные также зашифрованы в памяти, поэтому каждый доступ к методу getFirstName описывает данные (Я думаю, что есть способ кэшировать расшифрованные данные, но в этом случае они мне не нужны)
  • Зашифрованные поля нельзя использовать с методами Грааля/гибернации по умолчанию для поиска по базе данных, мы создали пользовательские методы в службах, которые получают данные, шифруют их и затем используют зашифрованные данные в предложении where запроса. При использовании класса User.w.Criteria

    пользователь {

     байт [] encryptedFirstName
    байт [] encryptedLastName
    байт [] encryptedAddress
    
    Дата Дата создания//автоматически установить дату/время при создании
    Дата обновления//автоматически установить дату/время при последнем обновлении
    
    EncryptionMethod encryptionMethod = ConfigurationHolder.config.encryption.method
    
    def encrypter = Util.encrypter
    
    статические переходные процессы = [
    'firstName',
    'lastName',
    'адрес',
    'encrypter'
    ]
    
    статическое конечное целое число BLOB_SIZE = 1024
    
    статические ограничения = {
    
    encryptedFirstName maxSize: BLOB_SIZE, значение null: false
    encryptedLastName maxSize: BLOB_SIZE, значение null: false
    
    encryptedAddress maxSize: BLOB_SIZE, значение null: true
    
    encrypityMethod, допускающий значение null: false
    
    }//ограничения
    
    Строка getFirstName () {
    decrypt («encryptedFirstName»)
    }
    
    void setFirstName (строковый предмет) {
    encryptedFirstName, предмет)
    }
    
    Строка getLastName () {
    decrypt («encryptedLastName»)}
    
    void setLastName (строковый предмет) {
    encryptedLastName, предмет)
    }
    
    Строка getAddress () {
    decrypt («encryptedAddress»)
    }
    
    void setAddress (строковый предмет) {
    encryptedAddress, предмет)
    }
    
    байт [] шифровать (последовательность, значение строки) {
    
    if (null = = значение) {
    log.debug «пустая последовательность для шифрования» $ name «, возвращает null»
    это. @ «$ name» = null
    вернуть
    }
    
    def bytes = value.getBytes (encrypter.ENCODING_CHARSET)
    def method = getEncrypityMethod ()
    
    
    байт [] res
    
    попробуй
    res = encrypter.encrypt (байты, метод)
    } улов (е) {
    log.warn «Проблема шифрования данных» $ name «:» $ последовательность «,» e
    }
    
    log.trace «Шифрование» $ name «с помощью» $ method «- >» $ {res? .size ()} «байт»
    
    это. @ «$ name» = res
    
    }
    
    Расшифровка последовательности (последовательность) {
    
    if (null = this. @ «$ name») {
    log.debug «null байт для расшифровки для» $ name «, возвращает null»
    возвращать значение null
    }
    
    def res
    def method = getEncrypityMethod ()
    
    попробуй
    res = новая последовательность (encrypter.decrypt (this. @ «$ name», метод), шифровальщик. ENCODING_CHARSET)
    } улов (е) {
    log.error «Ошибка расшифровки» $ name «», e
    }
    
    log.trace «Расшифровка» $ name «с помощью» $ method «- >» $ {res? .size ()} «байт»
    
    возврат res
    }
    

    }

2
ответ дан 5 December 2019 в 11:25
поделиться

Если вы закончите работу в приложении, вы можете использовать настраиваемые типы Hibernate, и это не внесет много изменений в ваш код.

Вот настраиваемый тип зашифрованной строки, который я использовал:

import org.hibernate.usertype.UserType
import org.apache.log4j.Logger

import java.sql.PreparedStatement
import java.sql.ResultSet
import java.sql.SQLException
import java.sql.Types

class EncryptedString implements UserType {

  // prefix category name with 'org.hibernate.type' to make logging of all types easier
  private final Logger _log = Logger.getLogger('org.hibernate.type.com.yourcompany.EncryptedString')

  Object nullSafeGet(ResultSet rs, String[] names, Object owner) throws SQLException {
    String value = rs.getString(names[0])

    if (!value) {
      _log.trace "returning null as column: $names[0]"
      return null
    }

    _log.trace "returning '$value' as column: $names[0]"
    return CryptoUtils.decrypt(value)
  }

  void nullSafeSet(PreparedStatement st, Object value, int index) throws SQLException {
    if (value) {
      String encrypted = CryptoUtils.encrypt(value.toString())
      _log.trace "binding '$encrypted' to parameter: $index"
      st.setString index, encrypted
    }
    else {
      _log.trace "binding null to parameter: $index"
      st.setNull(index, Types.VARCHAR)
    }
  }

  Class<String> returnedClass() { String }

  int[] sqlTypes() { [Types.VARCHAR] as int[] }

  Object assemble(Serializable cached, Object owner) { cached.toString() }

  Object deepCopy(Object value) { value.toString() }

  Serializable disassemble(Object value) { value.toString() }

  boolean equals(Object x, Object y) { x == y }

  int hashCode(Object x) { x.hashCode() }

  boolean isMutable() { true }

  Object replace(Object original, Object target, Object owner) { original }
}

, и на основе этого должно быть просто создать похожие классы для int, long и т. д. Чтобы использовать его, добавьте тип в замыкание сопоставления:

class MyDomainClass {

  String name
  String otherField

  static mapping = {
    name type: EncryptedString
    otherField type: EncryptedString
  }
}

Я пропустил CryptoUtils.encrypt () и CryptoUtils.decrypt (), поскольку они не относятся к Grails. Мы используем AES, например «Cipher cipher = Cipher.getInstance ('AES / CBC / PKCS5Padding')». Что бы вы ни использовали, убедитесь, что это двустороннее шифрование, т.е. не используйте SHA-256.

5
ответ дан 5 December 2019 в 11:25
поделиться

заказчик может легко сделать это, не меняя ничего в вашем приложении.

сначала зашифруйте связь между сервером, включив SSL на уровне mysql, или используйте туннель SSH.

во-вторых, храните базу данных mysql на зашифрованном томе.

любая атака, которая может раскрыть файловую систему базы данных mysql или учетные данные, необходимые для входа на сервер mysql, не смягчается шифрованием данных, поскольку та же атака может использоваться для получения ключа шифрования из самого приложения.

2
ответ дан 5 December 2019 в 11:25
поделиться

Если заказчик беспокоится о том, что кто-то физически уйдет с жестким диском, то использование полного диска, например Truecrypt , должно работать. Если вас беспокоит перехват трафика, посмотрите эту часть документации mysql по ssl поверх JDBC. Помните, что если кто-то скомпрометирует ваш сервер, все ставки отключены.

4
ответ дан 5 December 2019 в 11:25
поделиться

Another option is to use a JDBC driver that encrypts/decrypts data on the fly, two way. Bear in mind that any solution will probably invalidate searches by encrypted fields.

IMHO the best solution is the one proposed by longneck, it will make everything much easier, from administration to development. Besides, bear in mind that any solution with client-side encryption will render all your db data unusable outside of the client, ie, you will not be able to use nice tools like a jdbc client or MySQL query browser, etc.

1
ответ дан 5 December 2019 в 11:25
поделиться

Сгенерированные идентификаторы, версия, сопоставленные внешние ключи - в основном все, что поддерживается Hibernate - отсутствуют, если вы не намерены объявлять настраиваемый CRUD для всех своих классов и вручную шифровать их в запросах.

Для во всем остальном у вас есть несколько вариантов:

  1. @PostLoad и @PrePersist прослушиватели сущностей позаботятся обо всех операциях, не связанных с запросами.
  2. Реализация пользовательских типов String / Long / Integer / и т. Д. Для обработки шифрования позаботится как о запросах, так и об операциях CRUD; однако сопоставление станет довольно беспорядочным.
  3. Вы можете написать тонкую оболочку вокруг драйвера JDBC (а также Connection / Statement / PreparedStatement / ResultSet / и т. д.), чтобы выполнить шифрование за вас.

Насколько далеко по мере выполнения запросов вам придется обрабатывать шифрование вручную (если только вы не повторяется с # 2 выше), но вы должны иметь возможность сделать это через единственную точку входа. Я не уверен, как (и если) Grails справляется с этим, но, например, с помощью Spring это было бы так же просто, как расширение HibernateTemplate.

0
ответ дан 5 December 2019 в 11:25
поделиться

Jasypt интегрируется с Hibernate: http://jasypt.org/hibernate3.html . Однако нельзя использовать запросы, в которых используются предложения WHERE

1
ответ дан 5 December 2019 в 11:25
поделиться
Другие вопросы по тегам:

Похожие вопросы: