Сгенерировать правильный ключ AES-256-CBC / как хранить? - PullRequest
0 голосов
/ 23 января 2019

Я использую Laravel 5.7 и у меня есть два приложения, работающие на разных серверах. Я хочу общаться с шифрованием. Таким образом, оба конца должны иметь определенный ключ. По умолчанию шифрование Laravel установлено на AES-256-CBC.

Итак, я подумал, что мне нужен 32-байтовый ключ, например:

$ key = bin2hex (openssl_random_pseudo_bytes (32, $ cstrong));

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

Но почему-то этот ключ не принимается. Laravel бросает: Единственными поддерживаемыми шифрами являются AES-128-CBC и AES-256-CBC с правильной длиной ключа

Я также попытался установить его на 16 байт с помощью 32-символьной клавиши. Также не работает.

Тем не менее, он работает с установкой на 8 бит с 16-символьной клавишей. Но это не имеет никакого смысла для меня?

Сам Laravel использует ключ, похожий на этот: base64: X, где X = 44 символьная строка.

Я где-то читал, что AES-256-CBC нужен ключ из 64 символов, из которых 44 символа должны быть base64. Я не уверен, что это правильно, но мне трудно это понять. Как прочитать ключ с этим префиксом base64? Как вернуть это к обычной строке.

Пока я согласился с этой 16-символьной строкой, но, похоже, это неправильно. Итак, как создать действительный ключ AES-256-CBC и как его сохранить? Если требуется base64, как это работает? Кодирование сгенерированного шестнадцатеричного ключа возвращает мне строку из 88 символов.

Любая помощь приветствуется.

Ответы [ 2 ]

0 голосов
/ 30 января 2019

Laravel использует Подсветка \ Поддержка \ Фасады \ Крипта , которая предназначена для сквозного шифрования. Это означает, что вы можете надежно шифровать и дешифровать свои данные из базы данных, но она не предназначена для шифрования массовой коммуникации.

PHP 7.2+ поставляется вместе с LibSodium: он не одобряет использование собственных методов шифрования. Вы можете включить расширение в вашей конфигурации php.ini или скомпилировать PHP с этой конфигурацией. Вы можете читать больше на документах .

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

sodium_crypto_box_keypair();

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

Этого можно добиться, добавив файл Laravel \App\User.php и добавив новый заполняемый файл keypair. Создание новой миграции для таблицы users, добавление пары ключей столбца следующим образом:

public function up()
{
    Schema::table('users', function (Blueprint $table) {
        $table->string('key_pair')->unique()->nullable();
    });
}

Затем перейдите к файлу App\Http\Controllers\Auth\RegisterController.php и добавьте метод create.

Теперь, когда вы хотите зашифровать, вы можете ссылаться на пару ключей пользователя. Давайте возьмем Боба: Боб имеет идентификатор 1. Давайте возьмем Алису: Алиса имеет идентификатор 2.

$bob   = User::find(1);
$alice = User::find(2);

Теперь мы можем зашифровать сообщение от Боба и отправить его Алисе, создав натриевый криптобокс примерно так:

$kp = sodium_crypto_box_keypair_from_secretkey_and_publickey(
    sodium_crypto_box_secretkey($bob->keypair),
    sodium_crypto_box_publickey($alice->keypair) # Encrypt with Alices Public Key
);

$cbox = sodium_crypto_box(base64_encode('Hello, Alice. This is Bob.'), ($nonce = random_bytes(SODIUM_CRYPTO_BOX_NONCEBYTES)), $kp);

Теперь мы можем послать Алису IV, или лучше известную как одноразовый номер, и коробку с cyprto. Если Алиса сейчас хочет прочитать сообщение, она может использовать свой закрытый ключ и открытый ключ Бобса для чтения.

$kp = sodium_crypto_box_keypair_from_secretkey_and_publickey(
    sodium_crypto_box_secretkey($alice->keypair),
    sodium_crypto_box_publickey($bob->keypair) # Decrypt with Bobs public key
);

echo base64_decode(sodium_crypto_box_open($cbox, $nonce, $kp));

Я создал контейнер для упрощения шифрования и подписывания сообщений с помощью LibSodium. Я надеюсь, что это помогает понять концепцию и как использовать шифрование и хранить с base64* последним.

0 голосов
/ 24 января 2019

Я не в состоянии попробовать это сам, но посмотрите исходный код здесь :

/**
 * Create a new encryption key for the given cipher.
 *
 * @param  string  $cipher
 * @return string
 */
public static function generateKey($cipher)
{
    return random_bytes($cipher === 'AES-128-CBC' ? 16 : 32);
}

Таким образом, все, что вам нужно сделать, это вызвать random_bytes() (или его эквивалент openssl), либо запросить 16 байтов (в случае AES-128-CBC) или 32 байта (в случае AES-256-CBC). Это имеет смысл, поскольку в конечном итоге ключи для AES - это не что иное, как набор случайных байтов.

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

Именно поэтому поступает перевод Base64 . Он позволяет представлять коллекцию байтов только с помощью символов ASCII. Я подозреваю, что значение «base64: X, где X = 44 символьная строка», на которое вы ссылаетесь, находится в некотором файле конфигурации, который обычно должен содержать только читаемые символы. Действительно, перевод 32 байта в формат Base64 даст 44 символа. Префикс base64: в этом случае используется только для указания того, что значение хранится в формате Base64.

Пример, иллюстрирующий все это:

$key = random_bytes(32);
var_dump($key);
var_dump(base64_encode($key));

1024 * дает *

string(32) "?9???֔e?N??Y?&[??b?4@O|?\?"
string(44) "45U5nvetGyfWlGWOF06N+VnIJlvwx2L3fzRAT3z5XPY="

Последний - удобный формат для хранения ключа.

PS: В разделе Шифрование - Конфигурация документа упоминается

Перед использованием шифратора Laravel вы должны установить ключ файл конфигурации config / app.php. Вы должны использовать PHP ремесленника ключ: сгенерировать команду для генерации этого ключа

Может быть, эта команда делает все, что вы пытаетесь сделать самостоятельно?

...